Sync docs from master to gh-pages
This commit is contained in:
@@ -41,23 +41,32 @@ It also includes libraries to propagate the trace context over network boundarie
|
||||
Your names have to be explicit and concrete.
|
||||
Big names lead to latency issues and sometimes even thrown exceptions.</p></td></tr></table></div><p>The tracer creates and joins spans that model the latency of potentially distributed work.
|
||||
It can employ sampling to reduce overhead during the process, to reduce the amount of data sent to Zipkin, or both.</p><p>Spans returned by a tracer report data to Zipkin when finished or do nothing if unsampled.
|
||||
After starting a span, you can annotate events of interest or add tags containing details or lookup keys.</p><p>Spans have a context that includes trace identifiers that place the span at the correct spot in the tree representing the distributed operation.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_local_tracing" href="#_local_tracing"></a>3.1.2 Local Tracing</h3></div></div></div><p>When tracing local code, you can run it inside a span, as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
After starting a span, you can annotate events of interest or add tags containing details or lookup keys.</p><p>Spans have a context that includes trace identifiers that place the span at the correct spot in the tree representing the distributed operation.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_local_tracing" href="#_local_tracing"></a>3.1.2 Local Tracing</h3></div></div></div><p>When tracing code that never leaves your process, run it inside a scoped span.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
Span span = tracer.newTrace().name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"encode"</span>).start();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Start a new trace or a span within an existing trace representing an operation</span>
|
||||
ScopedSpan span = tracer.startScopedSpan(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"encode"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
doSomethingExpensive();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// The span is in "scope" meaning downstream code such as loggers can see trace IDs</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> encoder.encode();
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">catch</span> (RuntimeException | Error e) {
|
||||
span.error(e); <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Unless you handle exceptions, you might not know the operation failed!</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throw</span> e;
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
span.finish();
|
||||
}</pre><p>In the preceding example, the span is the root of the trace.
|
||||
In many cases, the span is part of an existing trace.
|
||||
When this is the case, call <code class="literal">newChild</code> instead of <code class="literal">newTrace</code>, as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
span.finish(); <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// always finish the span</span>
|
||||
}</pre><p>When you need more features, or finer control, use the <code class="literal">Span</code> type:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
Span span = tracer.newChild(root.context()).name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"encode"</span>).start();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
doSomethingExpensive();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Start a new trace or a span within an existing trace representing an operation</span>
|
||||
Span span = tracer.nextSpan().name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"encode"</span>).start();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Put the span in "scope" so that downstream code such as loggers can see trace IDs</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> (SpanInScope ws = tracer.withSpanInScope(span)) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> encoder.encode();
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">catch</span> (RuntimeException | Error e) {
|
||||
span.error(e); <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Unless you handle exceptions, you might not know the operation failed!</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throw</span> e;
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
span.finish();
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_customizing_spans" href="#_customizing_spans"></a>3.1.3 Customizing Spans</h3></div></div></div><p>Once you have a span, you can add tags to it.
|
||||
span.finish(); <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// note the scope is independent of the span. Always finish a span.</span>
|
||||
}</pre><p>Both of the above examples report the exact same span on finish!</p><p>In the above example, the span will be either a new root span or the
|
||||
next child in an existing trace.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_customizing_spans" href="#_customizing_spans"></a>3.1.3 Customizing Spans</h3></div></div></div><p>Once you have a span, you can add tags to it.
|
||||
The tags can be used as lookup keys or details.
|
||||
For example, you might add a tag with your runtime version, as shown in the following example:</p><pre class="programlisting">span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"clnt/finagle.version"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"6.36.0"</span>);</pre><p>When exposing the ability to customize spans to third parties, prefer <code class="literal">brave.SpanCustomizer</code> as opposed to <code class="literal">brave.Span</code>.
|
||||
The former is simpler to understand and test and does not tempt users with span lifecycle hooks.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> MyTraceCallback {
|
||||
@@ -71,32 +80,36 @@ The former is simpler to understand and test and does not tempt users with span
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> userCode() {
|
||||
span.annotate(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tx.started"</span>);
|
||||
...
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_rpc_tracing" href="#_rpc_tracing"></a>3.1.5 RPC tracing</h3></div></div></div><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Check for <a class="link" href="https://github.com/openzipkin/brave/tree/master/instrumentation" target="_top">instrumentation written here</a> and <a class="link" href="http://zipkin.io/pages/existing_instrumentations.html" target="_top">Zipkin’s list</a> before rolling your own RPC instrumentation.</p></td></tr></table></div><p>RPC tracing is often done automatically by interceptors. Behind the scenes, they add tags and events that relate to their role in an RPC operation.</p><p>The following example shows how to add a client span:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_rpc_tracing" href="#_rpc_tracing"></a>3.1.5 RPC tracing</h3></div></div></div><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Check for <a class="link" href="https://github.com/openzipkin/brave/tree/master/instrumentation" target="_top">instrumentation written here</a> and <a class="link" href="http://zipkin.io/pages/existing_instrumentations.html" target="_top">Zipkin’s list</a> before rolling your own RPC instrumentation.</p></td></tr></table></div><p>RPC tracing is often done automatically by interceptors. Behind the scenes, they add tags and events that relate to their role in an RPC operation.</p><p>The following example shows how to add a client span:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracing tracing;
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// before you send a request, add metadata that describes the operation</span>
|
||||
span = tracer.newTrace().name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"get"</span>).type(CLIENT);
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"clnt/finagle.version"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"6.36.0"</span>);
|
||||
span.tag(TraceKeys.HTTP_PATH, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/api"</span>);
|
||||
span.remoteEndpoint(Endpoint.builder()
|
||||
.serviceName(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"backend"</span>)
|
||||
.ipv4(<span class="hl-number">127</span> << <span class="hl-number">24</span> | <span class="hl-number">1</span>)
|
||||
.port(<span class="hl-number">8080</span>).build());
|
||||
span = tracer.nextSpan().name(service + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/"</span> + method).kind(CLIENT);
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"myrpc.version"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1.0.0"</span>);
|
||||
span.remoteServiceName(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"backend"</span>);
|
||||
span.remoteIpAndPort(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"172.3.4.1"</span>, <span class="hl-number">8108</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Add the trace context to the request, so it can be propagated in-band</span>
|
||||
tracing.propagation().injector(Request::addHeader)
|
||||
.inject(span.context(), request);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when the request is scheduled, start the span</span>
|
||||
span.start();
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// if you have callbacks for when data is on the wire, note those events</span>
|
||||
span.annotate(Constants.WIRE_SEND);
|
||||
span.annotate(Constants.WIRE_RECV);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// if there is an error, tag the span</span>
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"error"</span>, error.getCode());
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// or if there is an exception</span>
|
||||
span.error(exception);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when the response is complete, finish the span</span>
|
||||
span.finish();</pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_one_way_tracing" href="#_one_way_tracing"></a>One-Way tracing</h4></div></div></div><p>Sometimes, you need to model an asynchronous operation where there is a
|
||||
request but no response. In normal RPC tracing, you use <code class="literal">span.finish()</code>
|
||||
to indicate that the response was received. In one-way tracing, you use
|
||||
<code class="literal">span.flush()</code> instead, as you do not expect a response.</p><p>The following example shows how a client might model a one-way operation:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
<code class="literal">span.flush()</code> instead, as you do not expect a response.</p><p>The following example shows how a client might model a one-way operation:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracing tracing;
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// start a new span representing a client request</span>
|
||||
oneWaySend = tracer.newSpan(parent).kind(Span.Kind.CLIENT);
|
||||
oneWaySend = tracer.nextSpan().name(service + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/"</span> + method).kind(CLIENT);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Add the trace context to the request, so it can be propagated in-band</span>
|
||||
tracing.propagation().injector(Request::addHeader)
|
||||
|
||||
@@ -3,31 +3,44 @@
|
||||
<title>4. Sampling</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-sleuth.html" title="Spring Cloud Sleuth"><link rel="up" href="multi_spring-cloud-sleuth.html" title="Spring Cloud Sleuth"><link rel="prev" href="multi__features.html" title="3. Features"><link rel="next" href="multi__propagation.html" title="5. Propagation"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4. Sampling</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__features.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__propagation.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_sampling" href="#_sampling"></a>4. Sampling</h1></div></div></div><p>Sampling may be employed to reduce the data collected and reported out of process.
|
||||
When a span is not sampled, it adds no overhead (a noop).</p><p>Sampling is an up-front decision, meaning that the decision to report data is made at the first operation in a trace and that decision is propagated downstream.</p><p>By default, a global sampler applies a single rate to all traced operations.
|
||||
<code class="literal">Tracer.Builder.sampler</code> controls this setting, and it defaults to tracing every request.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_declarative_sampling" href="#_declarative_sampling"></a>4.1 Declarative sampling</h2></div></div></div><p>Some applications need to sample based on the type or annotations of a java method.</p><p>Most users use a framework interceptor to automate this sort of policy.
|
||||
The following example shows how that might work internally:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracing tracing;
|
||||
The following example shows how that might work internally:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// derives a sample rate from an annotation on a java method</span>
|
||||
DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sampleRate);
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Around("@annotation(traced)")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Object traceThing(ProceedingJoinPoint pjp, Traced traced) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Throwable {
|
||||
Span span = tracing.tracer().newTrace(sampler.sample(traced))...
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// When there is no trace in progress, this decides using an annotation</span>
|
||||
Sampler decideUsingAnnotation = declarativeSampler.toSampler(traced);
|
||||
Tracer tracer = tracer.withSampler(decideUsingAnnotation);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// This code looks the same as if there was no declarative override</span>
|
||||
ScopedSpan span = tracer.startScopedSpan(spanName(pjp));
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> pjp.proceed();
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">catch</span> (RuntimeException | Error e) {
|
||||
span.error(e);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throw</span> e;
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
span.finish();
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_sampling" href="#_custom_sampling"></a>4.2 Custom sampling</h2></div></div></div><p>Depending on what the operation is, you may want to apply different policies.
|
||||
For example, you might not want to trace requests to static resources such as images, or you might want to trace all requests to a new api.</p><p>Most users use a framework interceptor to automate this sort of policy.
|
||||
The following example shows how that might work internally:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Sampler fallback;
|
||||
|
||||
Span newTrace(Request input) {
|
||||
SamplingFlags flags = SamplingFlags.NONE;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (input.url().startsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/experimental"</span>)) {
|
||||
flags = SamplingFlags.SAMPLED;
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">else</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (input.url().startsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/static"</span>)) {
|
||||
flags = SamplingFlags.NOT_SAMPLED;
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> tracer.newTrace(flags);
|
||||
Span nextSpan(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Request input) {
|
||||
Sampler requestBased = Sampler() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> isSampled(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">long</span> traceId) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (input.url().startsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/experimental"</span>)) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> true;
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">else</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (input.url().startsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/static"</span>)) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> false;
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> fallback.isSampled(traceId);
|
||||
}
|
||||
};
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> tracer.withSampler(requestBased).nextSpan();
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_sampling_in_spring_cloud_sleuth" href="#_sampling_in_spring_cloud_sleuth"></a>4.3 Sampling in Spring Cloud Sleuth</h2></div></div></div><p>By default Spring Cloud Sleuth sets all spans to non-exportable.
|
||||
That means that traces appear in logs but not in any remote store.
|
||||
For testing the default is often enough, and it probably is all you need if you use only the logs (for example, with an ELK aggregator).
|
||||
|
||||
@@ -284,23 +284,32 @@ It also includes libraries to propagate the trace context over network boundarie
|
||||
Your names have to be explicit and concrete.
|
||||
Big names lead to latency issues and sometimes even thrown exceptions.</p></td></tr></table></div><p>The tracer creates and joins spans that model the latency of potentially distributed work.
|
||||
It can employ sampling to reduce overhead during the process, to reduce the amount of data sent to Zipkin, or both.</p><p>Spans returned by a tracer report data to Zipkin when finished or do nothing if unsampled.
|
||||
After starting a span, you can annotate events of interest or add tags containing details or lookup keys.</p><p>Spans have a context that includes trace identifiers that place the span at the correct spot in the tree representing the distributed operation.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_local_tracing" href="#_local_tracing"></a>3.1.2 Local Tracing</h3></div></div></div><p>When tracing local code, you can run it inside a span, as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
After starting a span, you can annotate events of interest or add tags containing details or lookup keys.</p><p>Spans have a context that includes trace identifiers that place the span at the correct spot in the tree representing the distributed operation.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_local_tracing" href="#_local_tracing"></a>3.1.2 Local Tracing</h3></div></div></div><p>When tracing code that never leaves your process, run it inside a scoped span.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
Span span = tracer.newTrace().name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"encode"</span>).start();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Start a new trace or a span within an existing trace representing an operation</span>
|
||||
ScopedSpan span = tracer.startScopedSpan(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"encode"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
doSomethingExpensive();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// The span is in "scope" meaning downstream code such as loggers can see trace IDs</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> encoder.encode();
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">catch</span> (RuntimeException | Error e) {
|
||||
span.error(e); <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Unless you handle exceptions, you might not know the operation failed!</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throw</span> e;
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
span.finish();
|
||||
}</pre><p>In the preceding example, the span is the root of the trace.
|
||||
In many cases, the span is part of an existing trace.
|
||||
When this is the case, call <code class="literal">newChild</code> instead of <code class="literal">newTrace</code>, as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
span.finish(); <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// always finish the span</span>
|
||||
}</pre><p>When you need more features, or finer control, use the <code class="literal">Span</code> type:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
Span span = tracer.newChild(root.context()).name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"encode"</span>).start();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
doSomethingExpensive();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Start a new trace or a span within an existing trace representing an operation</span>
|
||||
Span span = tracer.nextSpan().name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"encode"</span>).start();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Put the span in "scope" so that downstream code such as loggers can see trace IDs</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> (SpanInScope ws = tracer.withSpanInScope(span)) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> encoder.encode();
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">catch</span> (RuntimeException | Error e) {
|
||||
span.error(e); <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Unless you handle exceptions, you might not know the operation failed!</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throw</span> e;
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
span.finish();
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_customizing_spans" href="#_customizing_spans"></a>3.1.3 Customizing Spans</h3></div></div></div><p>Once you have a span, you can add tags to it.
|
||||
span.finish(); <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// note the scope is independent of the span. Always finish a span.</span>
|
||||
}</pre><p>Both of the above examples report the exact same span on finish!</p><p>In the above example, the span will be either a new root span or the
|
||||
next child in an existing trace.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_customizing_spans" href="#_customizing_spans"></a>3.1.3 Customizing Spans</h3></div></div></div><p>Once you have a span, you can add tags to it.
|
||||
The tags can be used as lookup keys or details.
|
||||
For example, you might add a tag with your runtime version, as shown in the following example:</p><pre class="programlisting">span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"clnt/finagle.version"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"6.36.0"</span>);</pre><p>When exposing the ability to customize spans to third parties, prefer <code class="literal">brave.SpanCustomizer</code> as opposed to <code class="literal">brave.Span</code>.
|
||||
The former is simpler to understand and test and does not tempt users with span lifecycle hooks.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> MyTraceCallback {
|
||||
@@ -314,32 +323,36 @@ The former is simpler to understand and test and does not tempt users with span
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> userCode() {
|
||||
span.annotate(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tx.started"</span>);
|
||||
...
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_rpc_tracing" href="#_rpc_tracing"></a>3.1.5 RPC tracing</h3></div></div></div><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Check for <a class="link" href="https://github.com/openzipkin/brave/tree/master/instrumentation" target="_top">instrumentation written here</a> and <a class="link" href="http://zipkin.io/pages/existing_instrumentations.html" target="_top">Zipkin’s list</a> before rolling your own RPC instrumentation.</p></td></tr></table></div><p>RPC tracing is often done automatically by interceptors. Behind the scenes, they add tags and events that relate to their role in an RPC operation.</p><p>The following example shows how to add a client span:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_rpc_tracing" href="#_rpc_tracing"></a>3.1.5 RPC tracing</h3></div></div></div><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>Check for <a class="link" href="https://github.com/openzipkin/brave/tree/master/instrumentation" target="_top">instrumentation written here</a> and <a class="link" href="http://zipkin.io/pages/existing_instrumentations.html" target="_top">Zipkin’s list</a> before rolling your own RPC instrumentation.</p></td></tr></table></div><p>RPC tracing is often done automatically by interceptors. Behind the scenes, they add tags and events that relate to their role in an RPC operation.</p><p>The following example shows how to add a client span:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracing tracing;
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// before you send a request, add metadata that describes the operation</span>
|
||||
span = tracer.newTrace().name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"get"</span>).type(CLIENT);
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"clnt/finagle.version"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"6.36.0"</span>);
|
||||
span.tag(TraceKeys.HTTP_PATH, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/api"</span>);
|
||||
span.remoteEndpoint(Endpoint.builder()
|
||||
.serviceName(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"backend"</span>)
|
||||
.ipv4(<span class="hl-number">127</span> << <span class="hl-number">24</span> | <span class="hl-number">1</span>)
|
||||
.port(<span class="hl-number">8080</span>).build());
|
||||
span = tracer.nextSpan().name(service + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/"</span> + method).kind(CLIENT);
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"myrpc.version"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1.0.0"</span>);
|
||||
span.remoteServiceName(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"backend"</span>);
|
||||
span.remoteIpAndPort(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"172.3.4.1"</span>, <span class="hl-number">8108</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Add the trace context to the request, so it can be propagated in-band</span>
|
||||
tracing.propagation().injector(Request::addHeader)
|
||||
.inject(span.context(), request);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when the request is scheduled, start the span</span>
|
||||
span.start();
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// if you have callbacks for when data is on the wire, note those events</span>
|
||||
span.annotate(Constants.WIRE_SEND);
|
||||
span.annotate(Constants.WIRE_RECV);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// if there is an error, tag the span</span>
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"error"</span>, error.getCode());
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// or if there is an exception</span>
|
||||
span.error(exception);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when the response is complete, finish the span</span>
|
||||
span.finish();</pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_one_way_tracing" href="#_one_way_tracing"></a>One-Way tracing</h4></div></div></div><p>Sometimes, you need to model an asynchronous operation where there is a
|
||||
request but no response. In normal RPC tracing, you use <code class="literal">span.finish()</code>
|
||||
to indicate that the response was received. In one-way tracing, you use
|
||||
<code class="literal">span.flush()</code> instead, as you do not expect a response.</p><p>The following example shows how a client might model a one-way operation:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
<code class="literal">span.flush()</code> instead, as you do not expect a response.</p><p>The following example shows how a client might model a one-way operation:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracing tracing;
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// start a new span representing a client request</span>
|
||||
oneWaySend = tracer.newSpan(parent).kind(Span.Kind.CLIENT);
|
||||
oneWaySend = tracer.nextSpan().name(service + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/"</span> + method).kind(CLIENT);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Add the trace context to the request, so it can be propagated in-band</span>
|
||||
tracing.propagation().injector(Request::addHeader)
|
||||
@@ -369,31 +382,44 @@ oneWayReceive.start().flush();
|
||||
next = tracer.newSpan(oneWayReceive.context()).name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"step2"</span>).start();</pre></div></div></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_sampling" href="#_sampling"></a>4. Sampling</h1></div></div></div><p>Sampling may be employed to reduce the data collected and reported out of process.
|
||||
When a span is not sampled, it adds no overhead (a noop).</p><p>Sampling is an up-front decision, meaning that the decision to report data is made at the first operation in a trace and that decision is propagated downstream.</p><p>By default, a global sampler applies a single rate to all traced operations.
|
||||
<code class="literal">Tracer.Builder.sampler</code> controls this setting, and it defaults to tracing every request.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_declarative_sampling" href="#_declarative_sampling"></a>4.1 Declarative sampling</h2></div></div></div><p>Some applications need to sample based on the type or annotations of a java method.</p><p>Most users use a framework interceptor to automate this sort of policy.
|
||||
The following example shows how that might work internally:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracing tracing;
|
||||
The following example shows how that might work internally:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// derives a sample rate from an annotation on a java method</span>
|
||||
DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sampleRate);
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Around("@annotation(traced)")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Object traceThing(ProceedingJoinPoint pjp, Traced traced) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Throwable {
|
||||
Span span = tracing.tracer().newTrace(sampler.sample(traced))...
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// When there is no trace in progress, this decides using an annotation</span>
|
||||
Sampler decideUsingAnnotation = declarativeSampler.toSampler(traced);
|
||||
Tracer tracer = tracer.withSampler(decideUsingAnnotation);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// This code looks the same as if there was no declarative override</span>
|
||||
ScopedSpan span = tracer.startScopedSpan(spanName(pjp));
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> pjp.proceed();
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">catch</span> (RuntimeException | Error e) {
|
||||
span.error(e);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throw</span> e;
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
span.finish();
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_sampling" href="#_custom_sampling"></a>4.2 Custom sampling</h2></div></div></div><p>Depending on what the operation is, you may want to apply different policies.
|
||||
For example, you might not want to trace requests to static resources such as images, or you might want to trace all requests to a new api.</p><p>Most users use a framework interceptor to automate this sort of policy.
|
||||
The following example shows how that might work internally:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Sampler fallback;
|
||||
|
||||
Span newTrace(Request input) {
|
||||
SamplingFlags flags = SamplingFlags.NONE;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (input.url().startsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/experimental"</span>)) {
|
||||
flags = SamplingFlags.SAMPLED;
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">else</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (input.url().startsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/static"</span>)) {
|
||||
flags = SamplingFlags.NOT_SAMPLED;
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> tracer.newTrace(flags);
|
||||
Span nextSpan(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Request input) {
|
||||
Sampler requestBased = Sampler() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> isSampled(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">long</span> traceId) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (input.url().startsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/experimental"</span>)) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> true;
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">else</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (input.url().startsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/static"</span>)) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> false;
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> fallback.isSampled(traceId);
|
||||
}
|
||||
};
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> tracer.withSampler(requestBased).nextSpan();
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_sampling_in_spring_cloud_sleuth" href="#_sampling_in_spring_cloud_sleuth"></a>4.3 Sampling in Spring Cloud Sleuth</h2></div></div></div><p>By default Spring Cloud Sleuth sets all spans to non-exportable.
|
||||
That means that traces appear in logs but not in any remote store.
|
||||
For testing the default is often enough, and it probably is all you need if you use only the logs (for example, with an ELK aggregator).
|
||||
|
||||
@@ -757,26 +757,37 @@ After starting a span, you can annotate events of interest or add tags containin
|
||||
</section>
|
||||
<section xml:id="_local_tracing">
|
||||
<title>Local Tracing</title>
|
||||
<simpara>When tracing local code, you can run it inside a span, as shown in the following example:</simpara>
|
||||
<simpara>When tracing code that never leaves your process, run it inside a scoped span.</simpara>
|
||||
<programlisting language="java" linenumbering="unnumbered">@Autowired Tracer tracer;
|
||||
|
||||
Span span = tracer.newTrace().name("encode").start();
|
||||
// Start a new trace or a span within an existing trace representing an operation
|
||||
ScopedSpan span = tracer.startScopedSpan("encode");
|
||||
try {
|
||||
doSomethingExpensive();
|
||||
// The span is in "scope" meaning downstream code such as loggers can see trace IDs
|
||||
return encoder.encode();
|
||||
} catch (RuntimeException | Error e) {
|
||||
span.error(e); // Unless you handle exceptions, you might not know the operation failed!
|
||||
throw e;
|
||||
} finally {
|
||||
span.finish();
|
||||
span.finish(); // always finish the span
|
||||
}</programlisting>
|
||||
<simpara>In the preceding example, the span is the root of the trace.
|
||||
In many cases, the span is part of an existing trace.
|
||||
When this is the case, call <literal>newChild</literal> instead of <literal>newTrace</literal>, as shown in the following example:</simpara>
|
||||
<simpara>When you need more features, or finer control, use the <literal>Span</literal> type:</simpara>
|
||||
<programlisting language="java" linenumbering="unnumbered">@Autowired Tracer tracer;
|
||||
|
||||
Span span = tracer.newChild(root.context()).name("encode").start();
|
||||
try {
|
||||
doSomethingExpensive();
|
||||
// Start a new trace or a span within an existing trace representing an operation
|
||||
Span span = tracer.nextSpan().name("encode").start();
|
||||
// Put the span in "scope" so that downstream code such as loggers can see trace IDs
|
||||
try (SpanInScope ws = tracer.withSpanInScope(span)) {
|
||||
return encoder.encode();
|
||||
} catch (RuntimeException | Error e) {
|
||||
span.error(e); // Unless you handle exceptions, you might not know the operation failed!
|
||||
throw e;
|
||||
} finally {
|
||||
span.finish();
|
||||
span.finish(); // note the scope is independent of the span. Always finish a span.
|
||||
}</programlisting>
|
||||
<simpara>Both of the above examples report the exact same span on finish!</simpara>
|
||||
<simpara>In the above example, the span will be either a new root span or the
|
||||
next child in an existing trace.</simpara>
|
||||
</section>
|
||||
<section xml:id="_customizing_spans">
|
||||
<title>Customizing Spans</title>
|
||||
@@ -814,23 +825,26 @@ void userCode() {
|
||||
</tip>
|
||||
<simpara>RPC tracing is often done automatically by interceptors. Behind the scenes, they add tags and events that relate to their role in an RPC operation.</simpara>
|
||||
<simpara>The following example shows how to add a client span:</simpara>
|
||||
<programlisting language="java" linenumbering="unnumbered">@Autowired Tracer tracer;
|
||||
<programlisting language="java" linenumbering="unnumbered">@Autowired Tracing tracing;
|
||||
@Autowired Tracer tracer;
|
||||
|
||||
// before you send a request, add metadata that describes the operation
|
||||
span = tracer.newTrace().name("get").type(CLIENT);
|
||||
span.tag("clnt/finagle.version", "6.36.0");
|
||||
span.tag(TraceKeys.HTTP_PATH, "/api");
|
||||
span.remoteEndpoint(Endpoint.builder()
|
||||
.serviceName("backend")
|
||||
.ipv4(127 << 24 | 1)
|
||||
.port(8080).build());
|
||||
span = tracer.nextSpan().name(service + "/" + method).kind(CLIENT);
|
||||
span.tag("myrpc.version", "1.0.0");
|
||||
span.remoteServiceName("backend");
|
||||
span.remoteIpAndPort("172.3.4.1", 8108);
|
||||
|
||||
// Add the trace context to the request, so it can be propagated in-band
|
||||
tracing.propagation().injector(Request::addHeader)
|
||||
.inject(span.context(), request);
|
||||
|
||||
// when the request is scheduled, start the span
|
||||
span.start();
|
||||
|
||||
// if you have callbacks for when data is on the wire, note those events
|
||||
span.annotate(Constants.WIRE_SEND);
|
||||
span.annotate(Constants.WIRE_RECV);
|
||||
// if there is an error, tag the span
|
||||
span.tag("error", error.getCode());
|
||||
// or if there is an exception
|
||||
span.error(exception);
|
||||
|
||||
// when the response is complete, finish the span
|
||||
span.finish();</programlisting>
|
||||
@@ -841,10 +855,11 @@ request but no response. In normal RPC tracing, you use <literal>span.finish()</
|
||||
to indicate that the response was received. In one-way tracing, you use
|
||||
<literal>span.flush()</literal> instead, as you do not expect a response.</simpara>
|
||||
<simpara>The following example shows how a client might model a one-way operation:</simpara>
|
||||
<programlisting language="java" linenumbering="unnumbered">@Autowired Tracer tracer;
|
||||
<programlisting language="java" linenumbering="unnumbered">@Autowired Tracing tracing;
|
||||
@Autowired Tracer tracer;
|
||||
|
||||
// start a new span representing a client request
|
||||
oneWaySend = tracer.newSpan(parent).kind(Span.Kind.CLIENT);
|
||||
oneWaySend = tracer.nextSpan().name(service + "/" + method).kind(CLIENT);
|
||||
|
||||
// Add the trace context to the request, so it can be propagated in-band
|
||||
tracing.propagation().injector(Request::addHeader)
|
||||
@@ -890,16 +905,24 @@ When a span is not sampled, it adds no overhead (a noop).</simpara>
|
||||
<simpara>Some applications need to sample based on the type or annotations of a java method.</simpara>
|
||||
<simpara>Most users use a framework interceptor to automate this sort of policy.
|
||||
The following example shows how that might work internally:</simpara>
|
||||
<programlisting language="java" linenumbering="unnumbered">@Autowired Tracing tracing;
|
||||
<programlisting language="java" linenumbering="unnumbered">@Autowired Tracer tracer;
|
||||
|
||||
// derives a sample rate from an annotation on a java method
|
||||
DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sampleRate);
|
||||
|
||||
@Around("@annotation(traced)")
|
||||
public Object traceThing(ProceedingJoinPoint pjp, Traced traced) throws Throwable {
|
||||
Span span = tracing.tracer().newTrace(sampler.sample(traced))...
|
||||
// When there is no trace in progress, this decides using an annotation
|
||||
Sampler decideUsingAnnotation = declarativeSampler.toSampler(traced);
|
||||
Tracer tracer = tracer.withSampler(decideUsingAnnotation);
|
||||
|
||||
// This code looks the same as if there was no declarative override
|
||||
ScopedSpan span = tracer.startScopedSpan(spanName(pjp));
|
||||
try {
|
||||
return pjp.proceed();
|
||||
} catch (RuntimeException | Error e) {
|
||||
span.error(e);
|
||||
throw e;
|
||||
} finally {
|
||||
span.finish();
|
||||
}
|
||||
@@ -912,15 +935,20 @@ For example, you might not want to trace requests to static resources such as im
|
||||
<simpara>Most users use a framework interceptor to automate this sort of policy.
|
||||
The following example shows how that might work internally:</simpara>
|
||||
<programlisting language="java" linenumbering="unnumbered">@Autowired Tracer tracer;
|
||||
@Autowired Sampler fallback;
|
||||
|
||||
Span newTrace(Request input) {
|
||||
SamplingFlags flags = SamplingFlags.NONE;
|
||||
if (input.url().startsWith("/experimental")) {
|
||||
flags = SamplingFlags.SAMPLED;
|
||||
} else if (input.url().startsWith("/static")) {
|
||||
flags = SamplingFlags.NOT_SAMPLED;
|
||||
}
|
||||
return tracer.newTrace(flags);
|
||||
Span nextSpan(final Request input) {
|
||||
Sampler requestBased = Sampler() {
|
||||
@Override public boolean isSampled(long traceId) {
|
||||
if (input.url().startsWith("/experimental")) {
|
||||
return true;
|
||||
} else if (input.url().startsWith("/static")) {
|
||||
return false;
|
||||
}
|
||||
return fallback.isSampled(traceId);
|
||||
}
|
||||
};
|
||||
return tracer.withSampler(requestBased).nextSpan();
|
||||
}</programlisting>
|
||||
</section>
|
||||
<section xml:id="_sampling_in_spring_cloud_sleuth">
|
||||
|
||||
Reference in New Issue
Block a user