diff options
Diffstat (limited to 'src/main/scala/xyz/driver/core/reporting/Reporter.scala')
-rw-r--r-- | src/main/scala/xyz/driver/core/reporting/Reporter.scala | 183 |
1 files changed, 0 insertions, 183 deletions
diff --git a/src/main/scala/xyz/driver/core/reporting/Reporter.scala b/src/main/scala/xyz/driver/core/reporting/Reporter.scala deleted file mode 100644 index 469084c..0000000 --- a/src/main/scala/xyz/driver/core/reporting/Reporter.scala +++ /dev/null @@ -1,183 +0,0 @@ -package xyz.driver.core -package reporting - -import scala.concurrent.Future - -/** Context-aware diagnostic utility for distributed systems, combining logging and tracing. - * - * Diagnostic messages (i.e. logs) are a vital tool for monitoring applications. Tying such messages to an - * execution context, such as a stack trace, simplifies debugging greatly by giving insight to the chains of events - * that led to a particular message. In synchronous systems, execution contexts can easily be determined by an - * external observer, and, as such, do not need to be propagated explicitly to sub-components (e.g. a stack trace on - * the JVM shows all relevant information). In asynchronous systems and especially distributed systems however, - * execution contexts are not easily determined by an external observer and hence need to be explicitly passed across - * service boundaries. - * - * This reporter provides tracing and logging utilities that explicitly require references to execution contexts - * (called [[SpanContext]]s here) intended to be passed across service boundaries. It embraces Scala's - * implicit-parameter-as-a-context paradigm. - * - * Tracing is intended to be compatible with the - * [[https://github.com/opentracing/specification/blob/master/specification.md OpenTrace specification]], and hence its - * guidelines on naming and tagging apply to methods provided by this Reporter as well. - * - * Usage example: - * {{{ - * val reporter: Reporter = ??? - * object Repo { - * def getUserQuery(userId: String)(implicit ctx: SpanContext) = reporter.trace("query"){ implicit ctx => - * reporter.debug("Running query") - * // run query - * } - * } - * object Service { - * def getUser(userId: String)(implicit ctx: SpanContext) = reporter.trace("get_user"){ implicit ctx => - * reporter.debug("Getting user") - * Repo.getUserQuery(userId) - * } - * } - * reporter.traceRoot("static_get", Map("user" -> "john")) { implicit ctx => - * Service.getUser("john") - * } - * }}} - * - * '''Note that computing traces may be a more expensive operation than traditional logging frameworks provide (in terms - * of memory and processing). It should be used in interesting and actionable code paths.''' - * - * @define rootWarning Note: the idea of the reporting framework is to pass along references to traces as - * implicit parameters. This method should only be used for top-level traces when no parent - * traces are available. - */ -trait Reporter { - import Reporter._ - - def traceWithOptionalParent[A]( - name: String, - tags: Map[String, String], - parent: Option[(SpanContext, CausalRelation)])(op: SpanContext => A): A - def traceWithOptionalParentAsync[A]( - name: String, - tags: Map[String, String], - parent: Option[(SpanContext, CausalRelation)])(op: SpanContext => Future[A]): Future[A] - - /** Trace the execution of an operation, if no parent trace is available. - * - * $rootWarning - */ - final def traceRoot[A](name: String, tags: Map[String, String] = Map.empty)(op: SpanContext => A): A = - traceWithOptionalParent( - name, - tags, - None - )(op) - - /** Trace the execution of an asynchronous operation, if no parent trace is available. - * - * $rootWarning - * - * @see traceRoot - */ - final def traceRootAsync[A](name: String, tags: Map[String, String] = Map.empty)( - op: SpanContext => Future[A]): Future[A] = - traceWithOptionalParentAsync( - name, - tags, - None - )(op) - - /** Trace the execution of an operation, in relation to a parent context. - * - * @param name The name of the operation. Note that this name should not be too specific. According to the - * OpenTrace RFC: "An operation name, a human-readable string which concisely represents the work done - * by the Span (for example, an RPC method name, a function name, or the name of a subtask or stage - * within a larger computation). The operation name should be the most general string that identifies a - * (statistically) interesting class of Span instances. That is, `"get_user"` is better than - * `"get_user/314159"`". - * @param tags Attributes associated with the traced event. Following the above example, if `"get_user"` is an - * operation name, a good tag would be `("account_id" -> 314159)`. - * @param relation Relation of the operation to its parent context. - * @param op The operation to be traced. The trace will complete once the operation returns. - * @param ctx Context of the parent trace. - * @tparam A Return type of the operation. - * @return The value of the child operation. - */ - final def trace[A]( - name: String, - tags: Map[String, String] = Map.empty, - relation: CausalRelation = CausalRelation.Child)(op: /* implicit (gotta wait for Scala 3) */ SpanContext => A)( - implicit ctx: SpanContext): A = - traceWithOptionalParent( - name, - tags, - Some(ctx -> relation) - )(op) - - /** Trace the operation of an asynchronous operation. - * - * Contrary to the synchronous version of this method, a trace is completed once the child operation completes - * (rather than returns). - * - * @see trace - */ - final def traceAsync[A]( - name: String, - tags: Map[String, String] = Map.empty, - relation: CausalRelation = CausalRelation.Child)( - op: /* implicit (gotta wait for Scala 3) */ SpanContext => Future[A])(implicit ctx: SpanContext): Future[A] = - traceWithOptionalParentAsync( - name, - tags, - Some(ctx -> relation) - )(op) - - /** Log a message. */ - def log(severity: Severity, message: String, reason: Option[Throwable])(implicit ctx: SpanContext): Unit - - /** Log a debug message. */ - final def debug(message: String)(implicit ctx: SpanContext): Unit = log(Severity.Debug, message, None) - final def debug(message: String, reason: Throwable)(implicit ctx: SpanContext): Unit = - log(Severity.Debug, message, Some(reason)) - - /** Log an informational message. */ - final def info(message: String)(implicit ctx: SpanContext): Unit = log(Severity.Informational, message, None) - final def info(message: String, reason: Throwable)(implicit ctx: SpanContext): Unit = - log(Severity.Informational, message, Some(reason)) - - /** Log a warning message. */ - final def warn(message: String)(implicit ctx: SpanContext): Unit = log(Severity.Warning, message, None) - final def warn(message: String, reason: Throwable)(implicit ctx: SpanContext): Unit = - log(Severity.Warning, message, Some(reason)) - - /** Log an error message. */ - final def error(message: String)(implicit ctx: SpanContext): Unit = log(Severity.Error, message, None) - final def error(message: String, reason: Throwable)(implicit ctx: SpanContext): Unit = - log(Severity.Error, message, Some(reason)) - -} - -object Reporter { - - /** A relation in cause. - * - * Corresponds to - * [[https://github.com/opentracing/specification/blob/master/specification.md#references-between-spans OpenTrace references between spans]] - */ - sealed trait CausalRelation - object CausalRelation { - - /** One event is the child of another. The parent completes once the child is complete. */ - case object Child extends CausalRelation - - /** One event follows from another, not necessarily being the parent. */ - case object Follows extends CausalRelation - } - - sealed trait Severity - object Severity { - case object Debug extends Severity - case object Informational extends Severity - case object Warning extends Severity - case object Error extends Severity - } - -} |