0

我正在尝试使用 Kamon 进行 MDC 传播,如本文档中所示,但它似乎不像他们说的那样工作

Play framework - 2.5

kamon-core - 0.6.2

kamon-play-25 - 0.6.2

我的登录模式:

<pattern>%d{HH:mm:ss.SSS} [%thread] [%level] [%traceToken]- %logger{36}\(%L\) %X{X-ApplicationId} - %message%n%xException</pattern>

我创建了一个过滤器:

class AccessLoggingFilter @Inject() (implicit val mat: Materializer, ec: ExecutionContext) extends Filter with LazyLogging {
val ApplicationIdKey = AvailableToMdc("X-ApplicationId")
def apply(next: (RequestHeader) => Future[Result])(request: RequestHeader): Future[Result] = {
TraceLocal.storeForMdc("X-ApplicationId", request.id.toString)
logger.error("first Location")
withMdc {
  logger.error("Second location")
  next(request)
}}}

并像这样添加它:

class MyFilters @Inject() (accessLoggingFilter: AccessLoggingFilter) extends DefaultHttpFilters(accessLoggingFilter)

现在,当我对服务器进行 http 调用时,我得到以下输出:

c.v.i.utils.AccessLoggingFilter(24)  - first Location
c.v.i.utils.AccessLoggingFilter(26) 1 - Second location

之后的所有日志打印都不会显示“1”X-ApplicationId

无法弄清楚我做错了什么。

4

1 回答 1

1

这是一个完整的(几乎)示例:

构建.sbt:

name := "kamon-play-example"

version := "1.0"

scalaVersion := "2.11.7"

val kamonVersion = "0.6.2"

val resolutionRepos = Seq("Kamon Repository Snapshots" at "http://snapshots.kamon.io")

val dependencies = Seq(
  "io.kamon"    %% "kamon-play-25"        % kamonVersion,
  "io.kamon"    %% "kamon-log-reporter"   % kamonVersion
)

lazy val root = (project in file(".")).enablePlugins(PlayScala)
                                      .settings(resolvers ++= resolutionRepos)
                                      .settings(libraryDependencies ++= dependencies)

基本过滤器:

class TraceLocalFilter @Inject() (implicit val mat: Materializer, ec: ExecutionContext) extends Filter {
  val logger = Logger(this.getClass)
  val TraceLocalStorageKey = "MyTraceLocalStorageKey"

  val userAgentHeader = "User-Agent"

  //this value will be available in the MDC at the moment to call  to Logger.*()s
  val UserAgentHeaderAvailableToMDC = AvailableToMdc(userAgentHeader)

  override def apply(next: (RequestHeader) ⇒ Future[Result])(header: RequestHeader): Future[Result] = {

    def onResult(result:Result) = {
      val traceLocalContainer = TraceLocal.retrieve(TraceLocalKey).getOrElse(TraceLocalContainer("unknown","unknown"))
      result.withHeaders(TraceLocalStorageKey -> traceLocalContainer.traceToken)
    }

    //update the TraceLocalStorage
    TraceLocal.store(TraceLocalKey)(TraceLocalContainer(header.headers.get(TraceLocalStorageKey).getOrElse("unknown"), "unknown"))
    TraceLocal.store(UserAgentHeaderAvailableToMDC)(header.headers.get(userAgentHeader).getOrElse("unknown"))

    //call the action
    next(header).map(onResult)
  }
}

我们需要添加过滤器:

class Filters @Inject() (traceLocalFilter: TraceLocalFilter)  extends HttpFilters {
  val filters = Seq(traceLocalFilter)
}

一个非常简单的控制器和动作:

class KamonPlayExample @Inject() (kamon: Kamon) extends Controller {

  def sayHello = Action.async {
    Future {
      logger.info("Say hello to Kamon")
      Ok("Say hello to Kamon")
    }
  }
}

在 logback.xml 添加以下模式:

    <pattern>%date{HH:mm:ss.SSS} %-5level [%traceToken][%X{User-Agent}] [%thread] %logger{55} - %msg%n</pattern>

添加sbt-aspectj-runner插件以便Aspectjweaver在 DEV 模式下运行应用程序:

addSbtPlugin("io.kamon" % "aspectj-play-runner" % "0.1.3")

运行应用程序aspectj-runner:run并制作一些curls

  curl -i -H 'X-Trace-Token:kamon-test' -H 'User-Agent:Super-User-Agent' -X GET "http://localhost:9000/helloKamon"

  curl -i -H 'X-Trace-Token:kamon-test'-X GET "http://localhost:9000/helloKamon"

在控制台中:

15:09:16.027 INFO  [kamon-test][Super-User-Agent] [application-akka.actor.default-dispatcher-8] controllers.KamonPlayExample - Say hello to Kamon

15:09:24.034 INFO  [kamon-test][curl/7.47.1] [application-akka.actor.default-dispatcher-8] controllers.KamonPlayExample - Say hello to Kamon

希望你能帮忙。

于 2016-07-27T18:16:51.447 回答