All Downloads are FREE. Search and download functionalities are using the official Maven repository.

brave.propagation.Propagation Maven / Gradle / Ivy

There is a newer version: 6.0.3
Show newest version
/*
 * Copyright 2013-2020 The OpenZipkin Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package brave.propagation;

import brave.Request;
import brave.Span.Kind;
import brave.baggage.BaggagePropagation;
import brave.internal.Nullable;
import brave.internal.propagation.StringPropagationAdapter;
import java.util.List;

/**
 * Injects and extracts {@link TraceContext trace identifiers} as text into requests that travel
 * in-band across process boundaries. Identifiers are often encoded as messaging or RPC request
 * headers.
 *
 * 

Propagation example: HTTP

* *

When using HTTP, the client (injector) and server (extractor) use request headers. The client * {@linkplain TraceContext.Injector#inject injects} the trace context into headers before the * request is sent to the server. The server {@linkplain TraceContext.Extractor#extract extracts} a * trace context from these headers before processing the request. * * @param Deprecated except when a {@link String}. * @since 4.0 */ public interface Propagation { /** * Defaults B3 formats based on {@link Request} type. When not a {@link Request} (e.g. in-process * messaging), this uses {@link B3Propagation.Format#SINGLE_NO_PARENT}. * * @since 4.0 */ Propagation B3_STRING = B3Propagation.get(); /** * @deprecated Since 5.9, use {@link B3Propagation#newFactoryBuilder()} to control inject formats. */ @Deprecated Propagation B3_SINGLE_STRING = B3SinglePropagation.FACTORY.get(); /** @since 4.0 */ abstract class Factory { /** * Does the propagation implementation support sharing client and server span IDs. For example, * should an RPC server span share the same identifiers extracted from an incoming request? * * In usual B3 Propagation, the * parent span ID is sent across the wire so that the client and server can share the same * identifiers. Other propagation formats, like trace-context * only propagate the calling trace and span ID, with an assumption that the receiver always * starts a new child span. When join is supported, you can assume that when {@link * TraceContext#parentId() the parent span ID} is null, you've been propagated a root span. When * join is not supported, you must always fork a new child. * * @since 4.7 */ public boolean supportsJoin() { return false; } /** * Returns {@code true} if the implementation cannot use 64-bit trace IDs. * * @since 4.9 */ public boolean requires128BitTraceId() { return false; } /** * This is deprecated: end users and instrumentation should never call this, and instead use * {@link #get()}. * *

Implementation advice

* This is deprecated, but abstract. This means those implementing custom propagation formats * will have to implement this until it is removed in Brave 6. If you are able to use a tool * such as "maven-shade-plugin", consider using {@link StringPropagationAdapter}. * * @param Deprecated except when a {@link String}. * @see KeyFactory#STRING * @since 4.0 * @deprecated Since 5.12, use {@link #get()} */ @Deprecated public abstract Propagation create(KeyFactory keyFactory); /** * Returns a possibly cached propagation instance. * *

Implementations should override and implement this method directly. * * @since 5.12 */ public Propagation get() { return create(KeyFactory.STRING); } /** * Decorates the input such that it can propagate extra state, such as a timestamp or baggage. * *

Implementations are responsible for data scoping, if relevant. For example, if only * global configuration is present, it could suffice to simply ensure that data is present. If * data is span-scoped, an implementation might compare the context to its last span ID, copying * on write or otherwise to ensure writes to one context don't affect another. * *

Implementations should be idempotent, returning the same instance instead of re-applying * change. * * @see TraceContext#extra() * @since 4.9 */ public TraceContext decorate(TraceContext context) { return context; } } /** * @since 4.0 * @deprecated since 5.12 non-string keys are no longer supported */ @Deprecated interface KeyFactory { KeyFactory STRING = new KeyFactory() { // retrolambda no likey @Override public String create(String name) { return name; } @Override public String toString() { return "StringKeyFactory{}"; } }; K create(String name); } /** * Replaces a propagated key with the given value. * * @param Usually, but not always, an instance of {@link Request}. * @param Deprecated except when a {@link String}. * @see RemoteSetter * @since 4.0 */ interface Setter { void put(R request, K key, String value); } /** * Returns the key names used for propagation of the current span. The result can be cached in the * same scope as the propagation instance. * *

This method exists to support remote propagation of trace IDs: *

    *
  • To generate constants for all key names. ex. gRPC Metadata.Key
  • *
  • To iterate fields when missing a get field by name function. ex. OpenTracing TextMap
  • *
  • Detection of if a context is likely to be present in a request object
  • *
  • To clear trace ID fields on re-usable requests. ex. JMS message
  • *
* *

Notes

*

Depending on the format, keys returned may not all be mandatory. * *

If your implementation carries baggage, such as correlation IDs, do not return the names of * those fields here. If you do, they will be deleted, which can interfere with user headers. * Instead, use {@link BaggagePropagation} which returns those names in {@link BaggagePropagation#allKeyNames(Propagation)}. * *

Edge-cases

* When a request is a single-use or immutable request object, there are no known edge cases to * consider. Mutable, retryable objects such as messaging headers should be careful about some * edge cases: * *

When multiple headers are used for trace identifiers, ex {@link B3Propagation.Format#MULTI}, * producers should be careful to clear fields here before calling {@link TraceContext.Injector#inject(TraceContext, Object)} * when the input is a new root span. Otherwise, a stale {@link TraceContext#parentIdString()} * could be left in the headers and be mistaken for a missing root span. * *

Headers here should be cleared when invoking listeners in * {@linkplain CurrentTraceContext.Scope scope}. Doing so prevents precedence rules that prefer * the trace context in message headers from overriding the current span. Doing so would place any * follow-up activity in the wrong spot in the trace tree. * * @see BaggagePropagation#allKeyNames(Propagation) * @since 4.0 */ List keys(); /** * Replaces a propagated field with the given value. Saved as a constant to avoid runtime * allocations. * * For example, a setter for an {@link java.net.HttpURLConnection} would be the method reference * {@link java.net.HttpURLConnection#addRequestProperty(String, String)} * * @param setter invoked for each propagation key to add. * @param Usually, but not always, an instance of {@link Request}. * @see RemoteSetter * @since 4.0 */ TraceContext.Injector injector(Setter setter); /** * Gets the first value of the given propagation key or returns {@code null}. * * @param Usually, but not always, an instance of {@link Request}. * @param Deprecated except when a {@link String}. * @see RemoteGetter * @since 4.0 */ interface Getter { @Nullable String get(R request, K key); } /** * Used as an input to {@link Propagation#injector(Setter)} inject the {@linkplain TraceContext * trace context} and any {@linkplain BaggagePropagation baggage} as propagated fields. * * @param usually {@link Request}, such as an HTTP server request or message * @see RemoteGetter * @since 5.12 */ // this is not `R extends Request` for APIs like OpenTracing that know the remote kind, but don't // implement the `Request` abstraction interface RemoteSetter extends Setter { /** * The only valid options are {@link Kind#CLIENT}, {@link Kind#PRODUCER}, and {@link * Kind#CONSUMER}. * * @see Request#spanKind() * @since 5.12 */ Kind spanKind(); /** * Replaces a propagation field with the given value. * *

Note: Implementations attempt to overwrite all values. This means that when the * caller is encoding multi-value (comma-separated list) HTTP header, they MUST join all values * on comma into a single string. * * @param request see {@link #} * @param fieldName typically a header name * @param value non-{@code null} value to replace any values with * @see RemoteGetter * @since 5.12 */ @Override void put(R request, String fieldName, String value); } /** * @param getter invoked for each propagation key to get. * @param Usually, but not always, an instance of {@link Request}. * @see RemoteGetter * @since 4.0 */ TraceContext.Extractor extractor(Getter getter); /** * Used as an input to {@link Propagation#extractor(Getter)} extract the {@linkplain TraceContext * trace context} and any {@linkplain BaggagePropagation baggage} from propagated fields. * * @param usually {@link Request}, such as an HTTP server request or message * @see RemoteSetter * @since 5.12 */ // this is not `R extends Request` for APIs like OpenTracing that know the remote kind, but don't // implement the `Request` abstraction interface RemoteGetter extends Getter { /** * The only valid options are {@link Kind#SERVER}, {@link Kind#PRODUCER}, and {@link * Kind#CONSUMER}. * * @see Request#spanKind() * @since 5.12 */ Kind spanKind(); /** * Gets the propagation field as a single value. * *

Note: HTTP only permits multiple header fields with the same name when the * format * is a comma-separated list. An HTTP implementation of this method will assume presence of * multiple values is valid and join them with a comma. See RFC * 7230 for more. * * @param request see {@link #} * @param fieldName typically a header name * @return the value of the field or {@code null} * @since 5.12 */ @Nullable @Override String get(R request, String fieldName); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy