操作 TraceContext
收集trace信息全都在于与tracing API以及当前的存储了信息的TraceContext交互,因为他是由你的应用程序产生的。这一节将教你能创建的所有基本的操作,并实关闭一个TraceContext和与它有关的segment。
注意:即使你了解到如何操作TraceContext很重要,一些kamon模块如Akka,Scala,Spray和Play!模块也已经提供了而记之的基本组件,而且能够自动的创建、传播和关闭trace,在某些特定条件下还可以关闭segment。因此,你好像不需要自己操作TraceContext。
创建和关闭TraceContext
你可以通过使用Kamon.tracer
中的成员提供的.newContext(...)
方法创建一个新的TraceContext
。如开始章节描述的,你需要保证你通过这个API启动Kamon。当你创建了一个县的context,你至少需要提供一个名字。这样你举可以在关闭这个trace之前在任何时候修改它。此外,你可以提供一个trace-token, 如果你不愿意,kamon会为你生成一个。
Scala:
val testTrace = Kamon.tracer.newContext("test-trace")
val testTraceWithToken = Kamon.tracer.newContext("trace-with-token", Some("token-42"))
// You can rename a trace before it is finished.
testTrace.rename("cool-functinality-X")
testTrace.finish()
// And you can also access it's token if you want to.
println("Test Trace Token: " + testTrace.token)
Java :
final TraceContext testTrace = Kamon.tracer().newContext("test-trace");
final TraceContext testTraceWithToken = Kamon.tracer().newContext("trace-with-token", Some.apply("token-42"));
// You can rename a trace before it is finished.
testTrace.rename("cool-functinality-X");
testTrace.finish();
// And you can also access it's token if you want to.
System.out.println("Test Trace Token: " + testTrace.token());
如上面所示,你可以通过调用.finish()
方法关闭一个TraceContext
。一旦你关闭了trace,你就不能对其进行重命名了。
此外,Tracer伴随对象提供了一个可选的.withNewTraceContext(...)
,他不仅仅创建了一个TraceContext
,它还将当前trace的context赋值给它,并选择在这段代码结束后结束这个context.执行情况如以下代码所示:
Scala:
Java
Tracer.withNewContext("GetUserDetails", autoFinish = true) {
// While this block of codes executes a new TraceContext
// is set as the current context and finished after the
// block returns.
println("Current Trace Token: " + Tracer.currentContext.token)
"Some awesome result";
}
// No TraceContext is present when you reach this point.
Java:
Tracer.withNewContext("GetUserDetails", true, ()-> {
// While this block of codes executes a new TraceContext
// is set as the current context and finished after the
// block returns.
System.out.println("Current Trace Token: " + Tracer.currentContext().token());
return "Some awesome result";
});
// No TraceContext is present when you reach this point.
新的TraceContext仅仅是在当前代码块中可以使用的,一旦方法退出,则会移除掉TraceContext,理解这一点很重要。
TraceContext 存储
你也许已经注意到上一节我们提到了”当前trace的context”,当我们提到这个时,我们指的是与当前线程中运行的这个trace关联的TraceContext
。他被存储在线程的局部trace变量中。确保一旦你不在需要TraceContext, 你总是能够关闭所有的线程。因此,如果你使用Tracer.withContext(...)
而不是直接使用Tracer.setCueentContext(...)
和Tracer.clearCurrentContext(...)
函数则更好。一旦代码结束执行,将确保trace context存储被设置,无论以前是什么样子。
Scala:
val context = Kamon.tracer.newContext("example-trace")
Tracer.withContext(context) {
// While this code executes, `context` is the current
// TraceContext.
println("Current Trace Token: " + Tracer.currentContext.token)
}
Java:
final TraceContext context = Kamon.tracer().newContext("example-trace");
Tracer.withContext(context, () -> {
// While this code executes, `context` is the current
// TraceContext.
System.out.println("Current Trace Token: " + Tracer.currentContext().token());
return "Some awesome result";
});
注意:一旦完成,Tracer.withContext(...)
变量将会关闭一个trace。
创建和关闭Segment
Tracer伴随对象没有直接提供创建segment的API,但是通过TraceContext实例,你可以创建你segment。一旦你访问了TraceContext,你就能够调用.startSegment(…)方法,从而获得一个与这个TraceContext关联的segment。
Scala:
Tracer.withNewContext("trace-with-segments", autoFinish = true) {
val segment = Tracer.currentContext.startSegment("some-cool-section", "business-logic", "kamon")
// Some application code here.
segment.finish()
}
java:
Tracer.withNewContext("trace-with-segments", true, () -> {
final Segment segment = Tracer.currentContext().startSegment("some-cool-section", "business-logic", "kamon");
// Some application code here.
segment.finish();
return "done";
});
记住:关闭trace之后,与之对应的segment也会被关闭。因此不要在还在.withContext(...)
代码块中强制关闭segment。segment清晰的知道它属于哪个TraceContext.
上面提到的方法更灵活。你可以通过segment实例做任何你想做的,除了TraceContext也提供了一个.withNewSegment(…)方法,他创建一个segment,并在代码执行结束的时候自动的关闭它。
Scala:
Tracer.withNewContext("trace-with-segments", autoFinish = true) {
Tracer.currentContext.withNewSegment("some-cool-section", "business-logic", "kamon") {
// Here is where the segment does it's job.
}
}
java:
Tracer.withNewContext("trace-with-segments", true, () -> {
Tracer.currentContext().withNewSegment("some-cool-section", "business-logic", "kamon", () -> {
// Here is where the segment does it's job.
return 0;
});
return "done";
});
显然,你不需要通关过Tracer.currentContext获得context,但那时你可以在任何以恶搞TraceContext中启动一个segment。
最后,另一个对Scala开发者友好的方法是.withAsyncSegment,它可以从代码中创建一个新的segment兵返回一个Future[T],还能在future完成时自动的关闭这个segment。代码:
Scala:
Scala
Tracer.withNewContext("trace-with-segments", autoFinish = true) {
Tracer.currentContext.withNewAsyncSegment("some-cool-section", "business-logic", "kamon") {
Future {
// Some code that will be executed asynchronously.
}
}
}