diff --git a/.cspell/en-words.txt b/.cspell/en-words.txt index 6754dcb9e611..4800905ccbf6 100644 --- a/.cspell/en-words.txt +++ b/.cspell/en-words.txt @@ -52,6 +52,7 @@ jaeger jaegertracing javaagent javadoc +javadocs jboss jdbc julia diff --git a/.htmltest.yml b/.htmltest.yml index 834ed075c8ae..4744a0a95ced 100644 --- a/.htmltest.yml +++ b/.htmltest.yml @@ -10,7 +10,7 @@ IgnoreDirs: - ^blog/(\d+/)?page/\d+ IgnoreInternalURLs: # list of paths IgnoreURLs: # list of regexs of paths or URLs to be ignored - - ^(/..)?/docs/languages/\w+/(api|examples|registry)/$ + - ^((/..)?/docs/languages/\w+|\.\.)/(api|examples|registry)/$ - ^(/..)?/docs/collector/registry/$ - ^(/..)?/docs/languages/net/(metrics-api|traces-api)/ - ^((/..)?/docs/migration/)?opencensus/$ diff --git a/.textlintrc.yml b/.textlintrc.yml index d91cf25f3597..229847f8fc03 100644 --- a/.textlintrc.yml +++ b/.textlintrc.yml @@ -136,6 +136,7 @@ rules: - '(? + + +The [SDK](../sdk/) is the built-in reference implementation of the +[API](../instrumentation/), processing and exporting telemetry produced by +instrumentation API calls. Configuring the SDK to process and export +appropriately is an essential step to integrating OpenTelemetry into an +application. + +All SDK components have +[programmatic configuration APIs](#programmatic-configuration). This is the most +flexible, expressive way to configure the SDK. However, changing configuration +requires adjusting code and recompiling the application, and there is no +language interoperability since the API is written in java. + +The [zero-code SDK autoconfigure](#zero-code-sdk-autoconfigure) module +configures SDK components through system properties or environment variables, +with various extension points for instances where the properties are +insufficient. + +{{% alert %}} We recommend using the +[zero-code SDK autoconfigure](#zero-code-sdk-autoconfigure) module since it +reduces boilerplate code, allows reconfiguration without rewriting code or +recompiling the application, and has language interoperability. {{% /alert %}} + +{{% alert %}} The [Java agent](/docs/zero-code/java/agent/) and +[Spring starter](/docs/zero-code/java/spring-boot-starter/) automatically +configure the SDK using the zero-code SDK autoconfigure module, and install +instrumentation with it. All autoconfigure content is applicable to Java agent +and Spring starter users. {{% /alert %}} + +## Programmatic configuration + +The programmatic configuration interface is the set of APIs for constructing +[SDK](../sdk/) components. All SDK components have a programmatic configuration +API, and all other configuration mechanisms are built on top of this API. For +example, the +[autoconfigure environment variable and system property](#environment-variables-and-system-properties) +configuration interface interprets well-known environment variables and system +properties into a series of calls to the programmatic configuration API. + +While other configuration mechanisms offer more convenience, none offer the +flexibility of writing code expressing the precise configuration required. When +a particular capability isn't supported by a higher order configuration +mechanism, you might have no choice but to use programmatic configuration. + +The [SDK components](../sdk/#sdk-components) sections demonstrate simple +programmatic configuration API for key user-facing areas of the SDK. Consult the +code for complete API reference. + +## Zero-code SDK autoconfigure + +The autoconfigure module (artifact +`io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:{{% param vers.otel %}}`) +is a configuration interface built on top of the +[programmatic configuration interface](#programmatic-configuration), which +configures [SDK components](../sdk/#sdk-components) with zero code. There are +two distinct autoconfigure workflows: + +- [Environment variables and system properties](#environment-variables-and-system-properties) + interprets environment variables and system properties to create SDK + components, including various customization points for overlaying programmatic + configuration. +- [Declarative configuration](#declarative-configuration) (**currently under + development**) interprets a configuration model to create SDK components, + which is typically encoded in a YAML configuration file. + +Automatically configure SDK components using with autoconfigure as follows: + + + +```java +package otel; + +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; + +public class AutoConfiguredSdk { + public static OpenTelemetrySdk autoconfiguredSdk() { + return AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk(); + } +} +``` + + +{{% alert %}} The [Java agent](/docs/zero-code/java/agent/) and +[Spring starter](/docs/zero-code/java/spring-boot-starter/) automatically +configure the SDK using the zero-code SDK autoconfigure module, and install +instrumentation with it. All autoconfigure content is applicable to Java agent +and Spring starter users. {{% /alert %}} {{% alert color="info" %}} The autoconfigure module registers Java shutdown -hooks to shut down the SDK when appropriate. Because OpenTelemetry Java uses -`java.util.logging` for its logging, some of that logging may be suppressed -during shutdown hooks. This is a bug in the JDK itself, and not something under -the control of OpenTelemetry Java. If you require logging during shutdown hooks, -consider using `System.out` rather than a logging framework that might shut -itself down in a shutdown hook, thus suppressing your log messages. See this -[JDK bug](https://bugs.openjdk.java.net/browse/JDK-8161253) for more details. -{{% /alert %}} - -{{% alert title="Signal configuration" color="primary" %}} - -The text placeholder `{signal}` refers to the supported -[OpenTelemetry Signal](/docs/concepts/signals/). Valid values include `traces`, -`metrics`, and `logs`. - -Signal specific configurations take priority over the generic versions. - -For example, if you set both `otel.exporter.otlp.endpoint` and -`otel.exporter.otlp.traces.endpoint`, the latter will take precedence. - -{{% /alert %}} - -### Disabling OpenTelemetrySdk - -The OpenTelemetry SDK can be disabled entirely. If disabled, -`AutoConfiguredOpenTelemetrySdk#getOpenTelemetrySdk()` will return a minimally -configured instance (i.e. `OpenTelemetrySdk.builder().build()`). - -| System property | Description | Default | -| ------------------- | ----------------------------------------- | ------- | -| `otel.sdk.disabled` | If `true`, disable the OpenTelemetry SDK. | `false` | - -### Resources - -A resource is the immutable representation of the entity producing the -telemetry. See [resources](/docs/concepts/resources/) for more details. - -| System Property | Description | -| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | -| `otel.resource.attributes` | Specify resource attributes in the following format: `key1=val1,key2=val2,key3=val3`. | -| `otel.service.name` | Specify logical service name. Takes precedence over `service.name` defined with `otel.resource.attributes`. | -| `otel.experimental.resource.disabled-keys` | Specify resource attribute keys that are filtered. | - -Make sure to use `otel.service.name` to set the -[`service.name`](/docs/specs/semconv/resource/#service) resource attribute, -which represents the logical name of your service. If unspecified, the SDK sets -`service.name=unknown_service:java` by default. - -### ResourceProvider SPI - -The -[autoconfigure-spi](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure-spi) -SDK extension provides a `ResourceProvider` SPI that allows libraries to -automatically provide resources, which are merged into a single resource by the -autoconfiguration module. You can create your own `ResourceProvider`, or -optionally use an artifact that includes built-in ResourceProviders: - -- [io.opentelemetry.instrumentation:opentelemetry-resources](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/resources) - includes providers for a - [predefined set of common resources](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources) -- [io.opentelemetry.contrib:opentelemetry-aws-resources](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources) - includes providers for - [common AWS resources](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource) -- [io.opentelemetry.contrib:opentelemetry-gcp-resources](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/gcp-resources) - includes providers for - [common GCP resources](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource) - -### Disabling automatic ResourceProviders - -Many instrumentation agent distributions automatically include various -`ResourceProvider` implementations. These can be turned on or off as follows: - -| Environment variable | Description | -| --------------------------------------- | -------------------------------------------------------------------------------------------- | -| `otel.java.enabled.resource.providers` | Turns on one or more `ResourceProvider` types. If unset, all resource providers are enabled. | -| `otel.java.disabled.resource.providers` | Turns off one or more `ResourceProvider` types. | - -The value for these properties must be a comma-separated list of fully qualified -`ResourceProvider` class names. For example, if you don't want to expose the -name of the operating system through the resource, you can pass the following -JVM argument: - -`-Dotel.java.disabled.resource.providers=io.opentelemetry.instrumentation.resources.OsResourceProvider` - -### Attribute limits - -The following properties can be used to control the maximum number and length of -attributes. - -| System property | Description | Default | -| ----------------------------------- | -------------------------------------------------------------------------------------- | -------- | -| `otel.attribute.value.length.limit` | The maximum length of attribute values. Applies to spans and logs. | No limit | -| `otel.attribute.count.limit` | The maximum number of attributes. Applies to spans, span events, span links, and logs. | `128` | - -### Propagators - -Propagators determine which distributed tracing header formats are used, and -which baggage propagation header formats are used. - -| System property | Description | Default | -| ------------------ | -------------------------------------------------------------------------------- | ---------------------------- | -| `otel.propagators` | The propagators to be used. Use a comma-separated list for multiple propagators. | `tracecontext,baggage` (W3C) | - -Supported values are the following: - -| Value | Description | Artifacts | -| -------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | -| `tracecontext` | [W3C Trace Context](https://www.w3.org/TR/trace-context/) (add `baggage` as well to include W3C baggage). | `opentelemetry-api` | -| `baggage` | [W3C Baggage](https://www.w3.org/TR/baggage/). | `opentelemetry-api` | -| `b3` | [B3 Single](https://github.com/openzipkin/b3-propagation#single-header). | `opentelemetry-extension-tracepropagators` | -| `b3multi` | [B3 Multi](https://github.com/openzipkin/b3-propagation#multiple-headers). | `opentelemetry-extension-tracepropagators` | -| `jaeger` | [Jaeger](https://www.jaegertracing.io/docs/1.21/client-libraries/#propagation-format) (includes Jaeger baggage). | `opentelemetry-extension-tracepropagators` | -| `xray` | [AWS X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader). | `io.opentelemetry.contrib:opentelemetry-aws-xray-propagator` | -| `ottrace` | [OT Trace](https://github.com/opentracing?q=basic&type=&language=). | `opentelemetry-extension-trace-propagators` | - -### Exporters - -> These configuration options apply when using -> `opentelemetry-exporter-{SDK exporter}` artifacts (see -> [list of available exporters](https://github.com/open-telemetry/opentelemetry-java#sdk-exporters)). - -Exporters output the telemetry. The following configuration properties are -common to all exporters: - -| System property | Purpose | -| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `otel.{signal}.exporter` | List of exporters to be used for {signal}, separated by commas. Default is `otlp`. `none` means no auto-configured exporter. | -| `otel.java.experimental.exporter.memory_mode` | If `reusable_data`, enable reusable memory mode (on exporters which support it) to reduce allocations. Default is `immutable_data`. This option is experimental and subject to change or removal.[^1] | - -[^1]: - Exporters which adhere to - `otel.java.experimental.exporter.memory_mode=reusable_data` are - `OtlpGrpc{Signal}Exporter`, `OtlpHttp{Signal}Exporter`, and - `PrometheusHttpServer`. - -#### OTLP exporter (span, metric, and log exporters) - -The [OpenTelemetry Protocol (OTLP)](/docs/specs/otlp) span, metric, and log -exporters. - -| System property | Description | Default | -| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- | -| `otel.{signal}.exporter` | Select the OpenTelemetry exporter for {signal}. | otlp | -| `otel.exporter.otlp.endpoint` | The endpoint to send all OTLP traces, metrics, and logs to. Often the address of an OpenTelemetry Collector. Must be a URL with a scheme of either `http` or `https` based on the use of TLS. If protocol is `http/protobuf` the version and signal will be appended to the path (e.g. `v1/traces`, `v1/metrics`, or `v1/logs`). | `http://localhost:4317` when protocol is `grpc`, and `http://localhost:4318/v1/{signal}` when protocol is `http/protobuf`. | -| `otel.exporter.otlp.{signal}.endpoint` | The endpoint to send OTLP {signal} to. Often the address of an OpenTelemetry Collector. Must be a URL with a scheme of either `http` or `https` based on the use of TLS. | `http://localhost:4317` when protocol is `grpc`, and `http://localhost:4318/v1/{signal}` when protocol is `http/protobuf`. | -| `otel.exporter.otlp.certificate` | The path to the file containing trusted certificates to use when verifying an OTLP trace, metric, or log server's TLS credentials. The file should contain one or more X.509 certificates in PEM format. | The host platform's trusted root certificates are used. | -| `otel.exporter.otlp.{signal}.certificate` | The path to the file containing trusted certificates to use when verifying an OTLP {signal} server's TLS credentials. The file should contain one or more X.509 certificates in PEM format. | The host platform's trusted root certificates are used | -| `otel.exporter.otlp.client.key` | The path to the file containing private client key to use when verifying an OTLP trace, metric, or log client's TLS credentials. The file should contain one private key PKCS8 PEM format. | No client key file is used. | -| `otel.exporter.otlp.{signal}.client.key` | The path to the file containing private client key to use when verifying an OTLP {signal} client's TLS credentials. The file should contain one private key PKCS8 PEM format. | No client key file is used. | -| `otel.exporter.otlp.client.certificate` | The path to the file containing trusted certificates to use when verifying an OTLP trace, metric, or log client's TLS credentials. The file should contain one or more X.509 certificates in PEM format. | No chain file is used. | -| `otel.exporter.otlp.{signal}.client.certificate` | The path to the file containing trusted certificates to use when verifying an OTLP {signal} server's TLS credentials. The file should contain one or more X.509 certificates in PEM format. | No chain file is used. | -| `otel.exporter.otlp.headers` | Key-value pairs separated by commas to pass as request headers on OTLP trace, metric, and log requests. | | -| `otel.exporter.otlp.{signal}.headers` | Key-value pairs separated by commas to pass as request headers on OTLP {signal} requests. | | -| `otel.exporter.otlp.compression` | The compression type to use on OTLP trace, metric, and log requests. Options include `gzip`. | No compression will be used. | -| `otel.exporter.otlp.{signal}.compression` | The compression type to use on OTLP {signal} requests. Options include `gzip`. | No compression will be used. | -| `otel.exporter.otlp.timeout` | The maximum waiting time, in milliseconds, allowed to send each OTLP trace, metric, and log batch. | `10000` | -| `otel.exporter.otlp.{signal}.timeout` | The maximum waiting time, in milliseconds, allowed to send each OTLP {signal} batch. | `10000` | -| `otel.exporter.otlp.protocol` | The transport protocol to use on OTLP trace, metric, and log requests. Options include `grpc` and `http/protobuf`. | `grpc` [^2] | -| `otel.exporter.otlp.{signal}.protocol` | The transport protocol to use on OTLP {signal} requests. Options include `grpc` and `http/protobuf`. | `grpc` [^2] | -| `otel.exporter.otlp.metrics.temporality.preference` | The preferred output aggregation temporality. Options include `DELTA`, `LOWMEMORY`, and `CUMULATIVE`. If `CUMULATIVE`, all instruments will have cumulative temporality. If `DELTA`, counter (sync and async) and histograms will be delta, up down counters (sync and async) will be cumulative. If `LOWMEMORY`, sync counter and histograms will be delta, async counter and up down counters (sync and async) will be cumulative. | `CUMULATIVE` | -| `otel.exporter.otlp.metrics.default.histogram.aggregation` | The preferred default histogram aggregation. Options include `BASE2_EXPONENTIAL_BUCKET_HISTOGRAM` and `EXPLICIT_BUCKET_HISTOGRAM`. | `EXPLICIT_BUCKET_HISTOGRAM` | -| `otel.experimental.exporter.otlp.retry.enabled` | If `true`, enable [experimental retry support](#otlp-exporter-retry). | `false` | - -[^2]: - The OpenTelemetry Java agent 2.x and the OpenTelemetry Spring Boot starter - use `http/protobuf` by default. - -##### OTLP exporter retry - -[OTLP](/docs/specs/otlp/#otlpgrpc-response) requires that -[transient](/docs/specs/otel/protocol/exporter/#retry) errors be handled with a -retry strategy. When retry is enabled, retryable gRPC status codes are retried -using an exponential backoff with jitter algorithm as described in the -[gRPC Retry Design](https://github.com/grpc/proposal/blob/master/A6-client-retries.md#exponential-backoff). - -The policy has the following configuration, which is can only be customized via -programmatic configuration (see -[customizing the OpenTelemetry SDK](#customizing-the-opentelemetry-sdk)): +hooks to shut down the SDK when appropriate. Because OpenTelemetry Java +[uses `java.util.logging` for internal logging](../sdk/#internal-logging), some +logging might be suppressed during shutdown hooks. This is a bug in the JDK +itself, and not something under the control of OpenTelemetry Java. If you +require logging during shutdown hooks, consider using `System.out` rather than a +logging framework which might shut itself down in a shutdown hook, thus +suppressing your log messages. For more details, see this +[JDK bug](https://bugs.openjdk.java.net/browse/JDK-8161253). {{% /alert %}} -| Option | Description | Default | -| ------------------- | --------------------------------------------------------------- | ------- | -| `maxAttempts` | The maximum number of attempts, including the original request. | `5` | -| `initialBackoff` | The initial backoff duration. | `1s` | -| `maxBackoff` | The maximum backoff duration. | `5s` | -| `backoffMultiplier` | The backoff multiplier. | `1.5` | +### Environment variables and system properties -#### Logging exporter +The autoconfigure module supports properties listed in the +[environment variable configuration specification](/docs/specs/otel/configuration/sdk-environment-variables/), +with occasional experimental and Java-specific additions. -The logging exporter prints the name of the span along with its attributes to -stdout. It's mainly used for testing and debugging. +The following properties are listed as system properties, but can also be set +using environment variables. Apply the following steps to convert a system +property to an environment variable: -> This configuration option applies when using the -> `opentelemetry-exporter-logging` artifact. For full artifact ID and version -> information, reference the -> [SDK exporter list](https://github.com/open-telemetry/opentelemetry-java#sdk-exporters). - -| Environment variable | Description | -| -------------------------------- | ----------------------------------------- | -| `otel.{signal}.exporter=console` | Select the logging exporter for {signal}. | - -The logging exporter is also set when `otel.{signal}.exporter`, is set to -`logging`. `logging` is a deprecated alias for `console`, the preferred value as -[defined in the specification](/docs/specs/otel/configuration/sdk-environment-variables/#exporter-selection). +- Convert the name to uppercase. +- Replace all `.` and `-` characters with `_`. -#### Logging OTLP JSON exporter +For example, the `otel.sdk.enabled` system property is equivalent to the +`OTEL_SDK_ENABLED` environment variable. -The logging-otlp exporter writes the telemetry data to the JUL logger in OTLP -JSON form. It's a more verbose output mainly used for testing and debugging. +If a property is defined as both a system property and environment variable, the +system property takes priority. -> This configuration option applies when using the -> `opentelemetry-exporter-logging-otlp` artifact. For full artifact ID and -> version information, reference the -> [SDK exporter list](https://github.com/open-telemetry/opentelemetry-java#sdk-exporters). +#### Properties: general -| Environment variable | Description | -| ------------------------------------- | --------------------------------------------------- | -| `otel.{signal}.exporter=logging-otlp` | Select the logging OTLP JSON exporter for {signal}. | +Properties for disabling the [SDK](../sdk/#opentelemetrysdk): -{{% alert title="Note" color="info" %}} While the -`OtlpJsonLogging{Signal}Exporters` are stable, specifying their use via -`otel.{signal}.exporter=logging-otlp` is experimental and subject to change or -removal. {{% /alert %}} +| System property | Description | Default | +| ------------------- | ------------------------------------------------- | ------- | +| `otel.sdk.disabled` | If `true`, disable the OpenTelemetry SDK. **[1]** | `false` | -## Tracer provider +**[1]**: If disabled, `AutoConfiguredOpenTelemetrySdk#getOpenTelemetrySdk()` +returns a minimally configured instance (for example, +`OpenTelemetrySdk.builder().build()`). -The following configuration options are specific to `SdkTracerProvider`. See -[general configuration](#general) for general configuration. +Properties for configuring [resource](../sdk/#resource): -### Span exporters +| System property | Description | Default | +| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | +| `otel.service.name` | Specify logical service name. Takes precedence over `service.name` defined with `otel.resource.attributes`. | `unknown_service:java` | +| `otel.resource.attributes` | Specify resource attributes in the following format: `key1=val1,key2=val2,key3=val3`. | | +| `otel.experimental.resource.disabled-keys` | Specify resource attribute keys to filter. This option is experimental and subject to change or removal. | | +| `otel.java.enabled.resource.providers` | Comma-separated list of `ResourceProvider` fully qualified class names to enable. **[1]** If unset, all resource providers are enabled. | | +| `otel.java.disabled.resource.providers` | Comma-separated list of `ResourceProvider` fully qualified class names to disable. **[1]** | | -The following exporters are only available for the trace signal. See -[exporters](#exporters) for general exporter configuration. +**[1]**: For example, to disable the +[OS resource provider](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/OsResourceProvider.java), +set +`-Dotel.java.disabled.resource.providers=io.opentelemetry.instrumentation.resources.OsResourceProvider`. +See [ResourceProvider](#resourceprovider) for resource provider artifact +coordinates. -#### Jaeger exporter +Properties for attribute limits (see [span limits](../sdk/#spanlimits), +[log limits](../sdk/#loglimits)): -{{% alert color="info" %}} The Jaeger exporters (artifacts -`opentelemetry-exporter-jaeger` and `opentelemetry-exporter-jaeger-thrift`) were -removed in the -[1.35.0](https://github.com/open-telemetry/opentelemetry-java/releases/tag/v1.35.0) -release (last published in `1.34.0`) and are no longer available in later -versions of autoconfigure. {{% /alert %}} +| System property | Description | Default | +| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | +| `otel.attribute.value.length.limit` | The maximum length of attribute values. Applies to spans and logs. Overridden by `otel.span.attribute.value.length.limit`, `otel.span.attribute.count.limit`. | No limit | +| `otel.attribute.count.limit` | The maximum number of attributes. Applies to spans, span events, span links, and logs. | `128` | -Jaeger now has [native support for OTLP](/blog/2022/jaeger-native-otlp/), and -users should export to Jaeger using [OTLP](/docs/languages/java/exporters/#otlp) -instead. +Properties for [context propagation](../sdk/#textmappropagator): -#### Zipkin exporter +| System property | Description | Default | +| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | +| `otel.propagators` | Comma-separated list of propagators. Known values include `tracecontext`, `baggage`, `b3`, `b3multi`, `jaeger`, `ottrace`, `xray`, `xray-lambda`. **[1]** | `tracecontext,baggage` (W3C) | -The [Zipkin](https://zipkin.io/zipkin-api/) exporter sends JSON in -[Zipkin format](https://zipkin.io/zipkin-api/#/default/post_spans) to a -specified HTTP URL. +**[1]**: Known propagators and artifacts (see +[text map propagator](../sdk/#textmappropagator) for artifact coordinates): -> These configuration options apply when using the -> `opentelemetry-exporter-zipkin` artifact. For full artifact ID and version -> information, reference the -> [SDK exporter list](https://github.com/open-telemetry/opentelemetry-java#sdk-exporters). +- `tracecontext` configures `W3CTraceContextPropagator`. +- `baggage` configures `W3CBaggagePropagator`. +- `b3`, `b3multi` configures `B3Propagator`. +- `jaeger` configures `JaegerPropagator`. +- `ottrace` configures `OtTracePropagator`. +- `xray` configures `AwsXrayPropagator`. +- `xray-lambda` configures `AwsXrayLambdaPropagator`. -| System property | Description | -| ------------------------------- | --------------------------------------------------------------------------------------------------------------------- | -| `otel.traces.exporter=zipkin` | Select the Zipkin exporter | -| `otel.exporter.zipkin.endpoint` | The Zipkin endpoint to connect to. Default is `http://localhost:9411/api/v2/spans`. Currently only HTTP is supported. | +#### Properties: traces -### Batch span processor +Properties for [batch span processor(s)](../sdk/#spanprocessor) paired with +exporters specified via `otel.traces.exporter`: | System property | Description | Default | | -------------------------------- | --------------------------------------------------------------- | ------- | @@ -308,34 +193,29 @@ specified HTTP URL. | `otel.bsp.max.export.batch.size` | The maximum batch size. | `512` | | `otel.bsp.export.timeout` | The maximum allowed time, in milliseconds, to export data. | `30000` | -### Sampler - -The sampler configures whether spans will be recorded for any call to -`SpanBuilder.startSpan`. - -| System property | Description | Default | -| ------------------------- | ----------------------------------------------------------------------- | ----------------------- | -| `otel.traces.sampler` | The sampler to use for tracing. | `parentbased_always_on` | -| `otel.traces.sampler.arg` | An argument to the configured tracer if supported, for example a ratio. | | - -Supported values for `otel.traces.sampler` are: +Properties for [sampler](../sdk/#sampler): -| Value | Description | -| -------------------------- | ------------------------------------------------------------------------------ | -| `always_on` | AlwaysOnSampler | -| `always_off` | AlwaysOffSampler | -| `traceidratio` | TraceIdRatioBased. `otel.traces.sampler.arg` sets the ratio. | -| `parentbased_always_on` | ParentBased(root=AlwaysOnSampler) | -| `parentbased_always_off` | ParentBased(root=AlwaysOffSampler) | -| `parentbased_traceidratio` | ParentBased(root=TraceIdRatioBased). `otel.traces.sampler.arg` sets the ratio. | +| System property | Description | Default | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | +| `otel.traces.sampler` | The sampler to use. Known values include `always_on`, `always_off`, `traceidratio`, `parentbased_always_on`, `parentbased_always_off`, `parentbased_traceidratio`, `jaeger_remote`. **[1]** | `parentbased_always_on` | +| `otel.traces.sampler.arg` | An argument to the configured tracer if supported, for example a ratio. | | -### Span limits +**[1]**: Known samplers and artifacts (see [sampler](../sdk/#sampler) for +artifact coordinates): -See [attribute limits](#attribute-limits) for general attribute limit -configuration. +- `always_on` configures `AlwaysOnSampler`. +- `always_off` configures `AlwaysOffSampler`. +- `traceidratio` configures `TraceIdRatioBased`. `otel.traces.sampler.arg` sets + the ratio. +- `parentbased_always_on` configures `ParentBased(root=AlwaysOnSampler)`. +- `parentbased_always_off` configures `ParentBased(root=AlwaysOffSampler)`. +- `parentbased_traceidratio` configures `ParentBased(root=TraceIdRatioBased)`. + `otel.traces.sampler.arg` sets the ratio. +- `jaeger_remote` configures `JaegerRemoteSampler`. `otel.traces.sampler.arg` is + a comma-separated list of args as described in the + [specification](/docs/specs/otel/configuration/sdk-environment-variables/#general-sdk-configuration). -These properties can be used to control the maximum size of spans by placing -limits on attributes, events, and links. +Properties for [span limits](../sdk/#spanlimits): | System property | Description | Default | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------- | -------- | @@ -344,59 +224,30 @@ limits on attributes, events, and links. | `otel.span.event.count.limit` | The maximum number of events per span. | `128` | | `otel.span.link.count.limit` | The maximum number of links per span. | `128` | -## Meter provider +#### Properties: metrics -The following configuration options are specific to `SdkMeterProvider`. See -[general configuration](#general) for general configuration. - -### Exemplars - -| System property | Description | Default | -| ------------------------------ | ------------------------------------------------------------------------------------ | ------------- | -| `otel.metrics.exemplar.filter` | The filter for exemplar sampling. Can be `ALWAYS_OFF`, `ALWAYS_ON` or `TRACE_BASED`. | `TRACE_BASED` | - -### Periodic Metric Reader +Properties for [periodic metric reader](../sdk/#metricreader): | System property | Description | Default | | ----------------------------- | ------------------------------------------------------------------------ | ------- | | `otel.metric.export.interval` | The interval, in milliseconds, between the start of two export attempts. | `60000` | -### Metric exporters - -The following exporters are only available for the metric signal. See -[exporters](#exporters) for general exporter configuration. - -#### Prometheus exporter +Properties for exemplars: -The -[Prometheus](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md) -exporter. - -> The following configuration options apply when using the -> `opentelemetry-exporter-prometheus` artifact. - -| System property | Description | Default | -| ---------------------------------- | ---------------------------------------------------------------------------------- | --------- | -| `otel.metrics.exporter=prometheus` | Select the Prometheus exporter | | -| `otel.exporter.prometheus.port` | The local port used to bind the prometheus metric server. Default is `9464`. | `9464` | -| `otel.exporter.prometheus.host` | The local address used to bind the prometheus metric server. Default is `0.0.0.0`. | `0.0.0.0` | - -Note that this is a pull exporter - it opens up a server on the local process -listening on the specified host and port, which a Prometheus server scrapes -from. - -### Cardinality Limits +| System property | Description | Default | +| ------------------------------ | ------------------------------------------------------------------------------------ | ------------- | +| `otel.metrics.exemplar.filter` | The filter for exemplar sampling. Can be `ALWAYS_OFF`, `ALWAYS_ON` or `TRACE_BASED`. | `TRACE_BASED` | -| System property | Description | Default | -| --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------- | -| `otel.experimental.metrics.cardinality.limit` | If set, configure experimental cardinality limit. The value dictates the maximum number of distinct points per metric. | `2000` | +Properties for cardinality limits: -## Logger provider +| System property | Description | Default | +| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `otel.experimental.metrics.cardinality.limit` | If set, configure cardinality limit. The value dictates the maximum number of distinct points per metric. This option is experimental and subject to change or removal. | `2000` | -The following configuration options are specific to `SdkLoggerProvider`. See -[general configuration](#general) for general configuration. +#### Properties: logs -### Batch log record processor +Properties for [log record processor(s)](../sdk/#logrecordprocessor) pared with +exporters via `otel.logs.exporter`: | System property | Description | Default | | --------------------------------- | --------------------------------------------------------------- | ------- | @@ -405,31 +256,452 @@ The following configuration options are specific to `SdkLoggerProvider`. See | `otel.blrp.max.export.batch.size` | The maximum batch size. | `512` | | `otel.blrp.export.timeout` | The maximum allowed time, in milliseconds, to export data. | `30000` | -## Customizing the OpenTelemetry SDK +#### Properties: exporters -Autoconfiguration exposes SPI -[hooks](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi) -for customizing behavior programmatically as needed. It's recommended to use the -above configuration properties where possible, only implementing the SPI to add -functionality not found in the SDK by default. +Properties for setting exporters: -## File Configuration +| System property | Purpose | Default | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- | +| `otel.traces.exporter` | Comma-separated list of span exporters. Known values include `otlp`, `zipkin`, `console`, `logging-otlp`, `none`. **[1]** | `otlp` | +| `otel.metrics.exporter` | Comma-separated list of metric exporters. Known values include `otlp`, `prometheus`, `none`. **[1]** | `otlp` | +| `otel.logs.exporter` | Comma-separated list of log record exporters. Known values include `otlp`, `console`, `logging-otlp`, `none`. **[1]** | `otlp` | +| `otel.java.experimental.exporter.memory_mode` | If `reusable_data`, enable reusable memory mode (on exporters which support it) to reduce allocations. Known values include `reusable_data`, `immutable_data`. This option is experimental and subject to change or removal. **[2]** | `immutable_data` | -**Status**: [Experimental](/docs/specs/otel/versioning-and-stability) +**[1]**: Known exporters and artifacts (see +[span exporter](../sdk/#spanexporter), +[metric exporter](../sdk/#metricexporter), +[log exporter](../sdk/#logrecordexporter) for exporter artifact coordinates): -{{% alert title="Note" color="warning" %}} When a config file is specified, -other environment variables described in this document along with SPI -[customizations](#customizing-the-opentelemetry-sdk) are ignored. The contents -of the file alone dictate SDK configuration. {{% /alert %}} +- `otlp` configures `OtlpHttp{Signal}Exporter` / `OtlpGrpc{Signal}Exporter`. +- `zipkin` configures `ZipkinSpanExporter`. +- `console` configures `LoggingSpanExporter`, `LoggingMetricExporter`, + `SystemOutLogRecordExporter`. +- `logging-otlp` configures `OtlpJsonLogging{Signal}Exporter`. + +**[2]**: Exporters which adhere to +`otel.java.experimental.exporter.memory_mode=reusable_data` are +`OtlpGrpc{Signal}Exporter`, `OtlpHttp{Signal}Exporter`, and +`PrometheusHttpServer`. -File configuration allows for configuration via a YAML as described in +Properties for `otlp` span, metric, and log exporters: + +| System property | Description | Default | +| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- | +| `otel.{signal}.exporter=otlp` | Select the OpenTelemetry exporter for {signal}. | | +| `otel.exporter.otlp.protocol` | The transport protocol to use on OTLP trace, metric, and log requests. Options include `grpc` and `http/protobuf`. | `grpc` **[1]** | +| `otel.exporter.otlp.{signal}.protocol` | The transport protocol to use on OTLP {signal} requests. Options include `grpc` and `http/protobuf`. | `grpc` **[1]** | +| `otel.exporter.otlp.endpoint` | The endpoint to send all OTLP traces, metrics, and logs to. Often the address of an OpenTelemetry Collector. Must be a URL with a scheme of either `http` or `https` based on the use of TLS. If protocol is `http/protobuf` the version and signal will be appended to the path (e.g. `v1/traces`, `v1/metrics`, or `v1/logs`). | `http://localhost:4317` when protocol is `grpc`, and `http://localhost:4318/v1/{signal}` when protocol is `http/protobuf`. | +| `otel.exporter.otlp.{signal}.endpoint` | The endpoint to send OTLP {signal} to. Often the address of an OpenTelemetry Collector. Must be a URL with a scheme of either `http` or `https` based on the use of TLS. | `http://localhost:4317` when protocol is `grpc`, and `http://localhost:4318/v1/{signal}` when protocol is `http/protobuf`. | +| `otel.exporter.otlp.certificate` | The path to the file containing trusted certificates to use when verifying an OTLP trace, metric, or log server's TLS credentials. The file should contain one or more X.509 certificates in PEM format. | The host platform's trusted root certificates are used. | +| `otel.exporter.otlp.{signal}.certificate` | The path to the file containing trusted certificates to use when verifying an OTLP {signal} server's TLS credentials. The file should contain one or more X.509 certificates in PEM format. | The host platform's trusted root certificates are used | +| `otel.exporter.otlp.client.key` | The path to the file containing private client key to use when verifying an OTLP trace, metric, or log client's TLS credentials. The file should contain one private key PKCS8 PEM format. | No client key file is used. | +| `otel.exporter.otlp.{signal}.client.key` | The path to the file containing private client key to use when verifying an OTLP {signal} client's TLS credentials. The file should contain one private key PKCS8 PEM format. | No client key file is used. | +| `otel.exporter.otlp.client.certificate` | The path to the file containing trusted certificates to use when verifying an OTLP trace, metric, or log client's TLS credentials. The file should contain one or more X.509 certificates in PEM format. | No chain file is used. | +| `otel.exporter.otlp.{signal}.client.certificate` | The path to the file containing trusted certificates to use when verifying an OTLP {signal} server's TLS credentials. The file should contain one or more X.509 certificates in PEM format. | No chain file is used. | +| `otel.exporter.otlp.headers` | Key-value pairs separated by commas to pass as request headers on OTLP trace, metric, and log requests. | | +| `otel.exporter.otlp.{signal}.headers` | Key-value pairs separated by commas to pass as request headers on OTLP {signal} requests. | | +| `otel.exporter.otlp.compression` | The compression type to use on OTLP trace, metric, and log requests. Options include `gzip`. | No compression will be used. | +| `otel.exporter.otlp.{signal}.compression` | The compression type to use on OTLP {signal} requests. Options include `gzip`. | No compression will be used. | +| `otel.exporter.otlp.timeout` | The maximum waiting time, in milliseconds, allowed to send each OTLP trace, metric, and log batch. | `10000` | +| `otel.exporter.otlp.{signal}.timeout` | The maximum waiting time, in milliseconds, allowed to send each OTLP {signal} batch. | `10000` | +| `otel.exporter.otlp.metrics.temporality.preference` | The preferred output aggregation temporality. Options include `DELTA`, `LOWMEMORY`, and `CUMULATIVE`. If `CUMULATIVE`, all instruments will have cumulative temporality. If `DELTA`, counter (sync and async) and histograms will be delta, up down counters (sync and async) will be cumulative. If `LOWMEMORY`, sync counter and histograms will be delta, async counter and up down counters (sync and async) will be cumulative. | `CUMULATIVE` | +| `otel.exporter.otlp.metrics.default.histogram.aggregation` | The preferred default histogram aggregation. Options include `BASE2_EXPONENTIAL_BUCKET_HISTOGRAM` and `EXPLICIT_BUCKET_HISTOGRAM`. | `EXPLICIT_BUCKET_HISTOGRAM` | +| `otel.experimental.exporter.otlp.retry.enabled` | If `true`, retry on when transient errors occur. **[2]** | `false` | + +**NOTE:** The text placeholder `{signal}` refers to the supported +[OpenTelemetry Signal](/docs/concepts/signals/). Valid values include `traces`, +`metrics`, and `logs`. Signal specific configurations take priority over the +generic versions. For example, if you set both `otel.exporter.otlp.endpoint` and +`otel.exporter.otlp.traces.endpoint`, the latter will take precedence. + +**[1]**: OpenTelemetry Java agent 2.x and the OpenTelemetry Spring Boot starter +use `http/protobuf` by default. + +**[2]**: [OTLP](/docs/specs/otlp/#otlpgrpc-response) requires +[transient](/docs/specs/otel/protocol/exporter/#retry) errors to be handled with +a retry strategy. When retry is enabled, retryable gRPC status codes are retried +using an exponential backoff with jitter algorithm. The specific options of +`RetryPolicy` can only be customized via +[programmatic customization](#programmatic-customization). + +Properties for `zipkin` span exporter: + +| System property | Description | Default | +| ------------------------------- | ---------------------------------------------------------- | ------------------------------------ | +| `otel.traces.exporter=zipkin` | Select the Zipkin exporter | | +| `otel.exporter.zipkin.endpoint` | The Zipkin endpoint to connect to. Only HTTP is supported. | `http://localhost:9411/api/v2/spans` | + +Properties for `prometheus` metric exporter. + +| System property | Description | Default | +| ---------------------------------- | ------------------------------------------------------------ | --------- | +| `otel.metrics.exporter=prometheus` | Select the Prometheus exporter | | +| `otel.exporter.prometheus.port` | The local port used to bind the prometheus metric server. | `9464` | +| `otel.exporter.prometheus.host` | The local address used to bind the prometheus metric server. | `0.0.0.0` | + +#### Programmatic customization + +Programmatic customization provides hooks to supplement the +[supported properties](#environment-variables-and-system-properties) with +[programmatic configuration](#programmatic-configuration). + +If using the [Spring starter](/docs/zero-code/java/spring-boot-starter/), see +also +[spring starter programmatic configuration](/docs/zero-code/java/spring-boot-starter/sdk-configuration/#programmatic-configuration). + + + +```java +package otel; + +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; +import java.util.Collections; + +public class CustomizedAutoConfiguredSdk { + public static OpenTelemetrySdk autoconfiguredSdk() { + return AutoConfiguredOpenTelemetrySdk.builder() + // Optionally customize TextMapPropagator. + .addPropagatorCustomizer((textMapPropagator, configProperties) -> textMapPropagator) + // Optionally customize Resource. + .addResourceCustomizer((resource, configProperties) -> resource) + // Optionally customize Sampler. + .addSamplerCustomizer((sampler, configProperties) -> sampler) + // Optionally customize SpanExporter. + .addSpanExporterCustomizer((spanExporter, configProperties) -> spanExporter) + // Optionally customize SpanProcessor. + .addSpanProcessorCustomizer((spanProcessor, configProperties) -> spanProcessor) + // Optionally supply additional properties. + .addPropertiesSupplier(Collections::emptyMap) + // Optionally customize ConfigProperties. + .addPropertiesCustomizer(configProperties -> Collections.emptyMap()) + // Optionally customize SdkTracerProviderBuilder. + .addTracerProviderCustomizer((builder, configProperties) -> builder) + // Optionally customize SdkMeterProviderBuilder. + .addMeterProviderCustomizer((builder, configProperties) -> builder) + // Optionally customize MetricExporter. + .addMetricExporterCustomizer((metricExporter, configProperties) -> metricExporter) + // Optionally customize MetricReader. + .addMetricReaderCustomizer((metricReader, configProperties) -> metricReader) + // Optionally customize SdkLoggerProviderBuilder. + .addLoggerProviderCustomizer((builder, configProperties) -> builder) + // Optionally customize LogRecordExporter. + .addLogRecordExporterCustomizer((logRecordExporter, configProperties) -> logRecordExporter) + // Optionally customize LogRecordProcessor. + .addLogRecordProcessorCustomizer((processor, configProperties) -> processor) + .build() + .getOpenTelemetrySdk(); + } +} +``` + + +#### SPI (Service provider interface) + +[SPIs](https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html) (artifact +`io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:{{% param vers.otel %}}`) +extend SDK autoconfiguration beyond the components built-in to the SDK. + +The following sections describe the available SPIs. Each SPI section includes: + +- A brief description, including link to Javadoc type reference. +- A table of available built-in and `opentelemetry-java-contrib` + implementations. +- A simple demonstration of a custom implementation. + +##### ResourceProvider + +[ResourceProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/ResourceProvider.html)s +contribute to the autoconfigured [resource](../sdk/#resource). + +`ResourceProvider`s built-in to the SDK and maintained by the community in +`opentelemetry-java-contrib`: + +| Class | Artifact | Description | +| ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | +| `io.opentelemetry.instrumentation.resources.ContainerResourceProvider` | `io.opentelemetry.instrumentation:opentelemetry-resources:{{% param vers.instrumentation %}}-alpha` | Provides container resource attributes. | +| `io.opentelemetry.instrumentation.resources.HostResourceProvider` | `io.opentelemetry.instrumentation:opentelemetry-resources:{{% param vers.instrumentation %}}-alpha` | Provides host resource attributes. | +| `io.opentelemetry.instrumentation.resources.HostIdResourceProvider` | `io.opentelemetry.instrumentation:opentelemetry-resources:{{% param vers.instrumentation %}}-alpha` | Provides host ID resource attribute. | +| `io.opentelemetry.instrumentation.resources.ManifestResourceProvider` | `io.opentelemetry.instrumentation:opentelemetry-resources:{{% param vers.instrumentation %}}-alpha` | Provides service resource attributes based on jar manifest. | +| `io.opentelemetry.instrumentation.resources.OsResourceProvider` | `io.opentelemetry.instrumentation:opentelemetry-resources:{{% param vers.instrumentation %}}-alpha` | Provides OS resource attributes. | +| `io.opentelemetry.instrumentation.resources.ProcessResourceProvider` | `io.opentelemetry.instrumentation:opentelemetry-resources:{{% param vers.instrumentation %}}-alpha` | Provides process resource attributes. | +| `io.opentelemetry.instrumentation.resources.ProcessRuntimeProvider` | `io.opentelemetry.instrumentation:opentelemetry-resources:{{% param vers.instrumentation %}}-alpha` | Provides process runtime resource attributes. | +| `io.opentelemetry.contrib.gcp.resource.GCPResourceProvider` | `io.opentelemetry.contrib:opentelemetry-gcp-resources:{{% param vers.contrib %}}-alpha` | Provides GCP runtime environment resource attributes. | +| `io.opentelemetry.contrib.aws.resource.BeanstalkResourceProvider` | `io.opentelemetry.contrib:opentelemetry-aws-resources:{{% param vers.contrib %}}-alpha` | Provides AWS beanstalk runtime environment resource attributes. | +| `io.opentelemetry.contrib.aws.resource.Ec2ResourceProvider` | `io.opentelemetry.contrib:opentelemetry-aws-resources:{{% param vers.contrib %}}-alpha` | Provides AWS ec2 runtime environment resource attributes. | +| `io.opentelemetry.contrib.aws.resource.EcsResourceProvider` | `io.opentelemetry.contrib:opentelemetry-aws-resources:{{% param vers.contrib %}}-alpha` | Provides AWS ecs runtime environment resource attributes. | +| `io.opentelemetry.contrib.aws.resource.EksResourceProvider` | `io.opentelemetry.contrib:opentelemetry-aws-resources:{{% param vers.contrib %}}-alpha` | Provides AWS eks runtime environment resource attributes. | +| `io.opentelemetry.contrib.aws.resource.LambdaResourceProvider` | `io.opentelemetry.contrib:opentelemetry-aws-resources:{{% param vers.contrib %}}-alpha` | Provides AWS lambda runtime environment resource attributes. | + +Implement the `ResourceProvider` interface to participate in resource +autoconfiguration. For example: + + + +```java +package otel; + +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; +import io.opentelemetry.sdk.resources.Resource; + +public class CustomResourceProvider implements ResourceProvider { + + @Override + public Resource createResource(ConfigProperties config) { + // Callback invoked to contribute to the resource. + return Resource.builder().put("my.custom.resource.attribute", "abc123").build(); + } + + @Override + public int order() { + // Optionally influence the order of invocation. + return 0; + } +} +``` + + +##### AutoConfigurationCustomizerProvider + +Implement the +[AutoConfigurationCustomizerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizerProvider.html) +interface to customize a variety of autoconfigured SDK components. For example: + + + +```java +package otel; + +import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; +import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; +import java.util.Collections; + +public class CustomizerProvider implements AutoConfigurationCustomizerProvider { + + @Override + public void customize(AutoConfigurationCustomizer customizer) { + // Optionally customize TextMapPropagator. + customizer.addPropagatorCustomizer((textMapPropagator, configProperties) -> textMapPropagator); + // Optionally customize Resource. + customizer.addResourceCustomizer((resource, configProperties) -> resource); + // Optionally customize Sampler. + customizer.addSamplerCustomizer((sampler, configProperties) -> sampler); + // Optionally customize SpanExporter. + customizer.addSpanExporterCustomizer((spanExporter, configProperties) -> spanExporter); + // Optionally customize SpanProcessor. + customizer.addSpanProcessorCustomizer((spanProcessor, configProperties) -> spanProcessor); + // Optionally supply additional properties. + customizer.addPropertiesSupplier(Collections::emptyMap); + // Optionally customize ConfigProperties. + customizer.addPropertiesCustomizer(configProperties -> Collections.emptyMap()); + // Optionally customize SdkTracerProviderBuilder. + customizer.addTracerProviderCustomizer((builder, configProperties) -> builder); + // Optionally customize SdkMeterProviderBuilder. + customizer.addMeterProviderCustomizer((builder, configProperties) -> builder); + // Optionally customize MetricExporter. + customizer.addMetricExporterCustomizer((metricExporter, configProperties) -> metricExporter); + // Optionally customize MetricReader. + customizer.addMetricReaderCustomizer((metricReader, configProperties) -> metricReader); + // Optionally customize SdkLoggerProviderBuilder. + customizer.addLoggerProviderCustomizer((builder, configProperties) -> builder); + // Optionally customize LogRecordExporter. + customizer.addLogRecordExporterCustomizer((exporter, configProperties) -> exporter); + // Optionally customize LogRecordProcessor. + customizer.addLogRecordProcessorCustomizer((processor, configProperties) -> processor); + } + + @Override + public int order() { + // Optionally influence the order of invocation. + return 0; + } +} +``` + + +##### ConfigurableSpanExporterProvider + +Implement the +[ConfigurableSpanExporterProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/traces/ConfigurableSpanExporterProvider.html) +interface to allow a custom span exporter to participate in autoconfiguration. +For example: + + + +```java +package otel; + +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider; +import io.opentelemetry.sdk.trace.export.SpanExporter; + +public class CustomSpanExporterProvider implements ConfigurableSpanExporterProvider { + + @Override + public SpanExporter createExporter(ConfigProperties config) { + // Callback invoked when OTEL_TRACES_EXPORTER includes the value from getName(). + return new CustomSpanExporter(); + } + + @Override + public String getName() { + return "custom-exporter"; + } +} +``` + + +##### ConfigurableMetricExporterProvider + +Implement the +[ConfigurableMetricExporterProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/metrics/ConfigurableMetricExporterProvider.html) +interface to allow a custom metric exporter to participate in autoconfiguration. +For example: + + + +```java +package otel; + +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider; +import io.opentelemetry.sdk.metrics.export.MetricExporter; + +public class CustomMetricExporterProvider implements ConfigurableMetricExporterProvider { + + @Override + public MetricExporter createExporter(ConfigProperties config) { + // Callback invoked when OTEL_METRICS_EXPORTER includes the value from getName(). + return new CustomMetricExporter(); + } + + @Override + public String getName() { + return "custom-exporter"; + } +} +``` + + +##### ConfigurableLogRecordExporterProvider + +Implement the +[ConfigurableLogRecordExporterProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/logs/ConfigurableLogRecordExporterProvider.html) +interface to allow a custom log record exporter to participate in +autoconfiguration. For example: + + + +```java +package otel; + +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider; +import io.opentelemetry.sdk.logs.export.LogRecordExporter; + +public class CustomLogRecordExporterProvider implements ConfigurableLogRecordExporterProvider { + + @Override + public LogRecordExporter createExporter(ConfigProperties config) { + // Callback invoked when OTEL_LOGS_EXPORTER includes the value from getName(). + return new CustomLogRecordExporter(); + } + + @Override + public String getName() { + return "custom-exporter"; + } +} +``` + + +##### ConfigurableSamplerProvider + +Implement the +[ConfigurableSamplerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/traces/ConfigurableSamplerProvider.html) +interface to allow a custom sampler to participate in autoconfiguration. For +example: + + + +```java +package otel; + +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider; +import io.opentelemetry.sdk.trace.samplers.Sampler; + +public class CustomSamplerProvider implements ConfigurableSamplerProvider { + + @Override + public Sampler createSampler(ConfigProperties config) { + // Callback invoked when OTEL_TRACES_SAMPLER is set to the value from getName(). + return new CustomSampler(); + } + + @Override + public String getName() { + return "custom-sampler"; + } +} +``` + + +##### ConfigurablePropagatorProvider + +Implement the +[ConfigurablePropagatorProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/ConfigurablePropagatorProvider.html) +interface to allow a custom propagator to participate in autoconfiguration. For +example: + + + +```java +package otel; + +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigurablePropagatorProvider; + +public class CustomTextMapPropagatorProvider implements ConfigurablePropagatorProvider { + @Override + public TextMapPropagator getPropagator(ConfigProperties config) { + // Callback invoked when OTEL_PROPAGATORS includes the value from getName(). + return new CustomTextMapPropagator(); + } + + @Override + public String getName() { + return "custom-propagator"; + } +} +``` + + +### Declarative configuration + +Declarative configuration is currently under development. It allows for YAML +file-based configuration as described in [opentelemetry-configuration](https://github.com/open-telemetry/opentelemetry-configuration) and [file configuration](/docs/specs/otel/configuration/file-configuration/). To use, include -`io.opentelemetry:opentelemetry-sdk-extension:incubator:` and specify -the path to the config file as described in the table below. +`io.opentelemetry:opentelemetry-sdk-extension-incubator:{{% param vers.otel %}}-alpha` +and specify the path to the config file as described in the table below. | System property | Purpose | Default | | ------------------------------- | --------------------------------------- | ------- | | `otel.experimental.config.file` | The path to the SDK configuration file. | Unset | + +{{% alert title="Note" color="warning" %}} When a config file is specified, +[environment variables and system properties](#environment-variables-and-system-properties) +are ignored, [programmatic customization](#programmatic-customization) and +[SPIs](#spi-service-provider-interface) are skipped. The contents of the file +alone dictate SDK configuration. {{% /alert %}} + +For additional details, consult the following resources: + +- [Usage documentation](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/incubator#file-configuration) +- [Example with Java agent](https://github.com/open-telemetry/opentelemetry-java-examples/tree/main/javaagent#file-configuration) +- [Example without Java agent](https://github.com/open-telemetry/opentelemetry-java-examples/tree/main/file-configuration) diff --git a/content/en/docs/languages/java/exporters.md b/content/en/docs/languages/java/exporters.md deleted file mode 100644 index 5bccb877e889..000000000000 --- a/content/en/docs/languages/java/exporters.md +++ /dev/null @@ -1,410 +0,0 @@ ---- -title: Exporters -weight: 50 -cSpell:ignore: okhttp ---- - - - - -{{% docs/languages/exporters/intro java %}} - -### Dependencies {#otlp-dependencies} - -If you want to send telemetry data to an OTLP endpoint (like the -[OpenTelemetry Collector](#collector-setup), [Jaeger](#jaeger) or -[Prometheus](#prometheus)), there are multiple OTLP options available, each -catering to different use cases. For most users, the default artifact will -suffice and be the most simple: - -{{< tabpane text=true >}} {{% tab Gradle %}} - -```kotlin -dependencies { - implementation("io.opentelemetry:opentelemetry-exporter-otlp:{{% param vers.otel %}}") - implementation("io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}") - implementation("io.opentelemetry.semconv:opentelemetry-semconv:{{% param vers.semconv %}}-alpha") -} -``` - -{{% /tab %}} {{% tab Maven %}} - -```xml - - - - io.opentelemetry - opentelemetry-exporter-otlp - - - io.opentelemetry - opentelemetry-sdk - - - io.opentelemetry.semconv - opentelemetry-semconv - {{% param vers.semconv %}}-alpha - - - -``` - -{{< /tab >}} {{< /tabpane>}} - -Under the hood, there are two protocol options supported, each with different -"sender" implementations. - -- `grpc` - gRPC implementation of OTLP exporters, represented by - `OtlpGrpcSpanExporter`, `OtlpGrpcMetricExporter`, `OtlpGrpcLogRecordExporter`. -- `http/protobuf` - HTTP with protobuf encoded payload implementation of OTLP - exporters, represented by `OtlpHttpSpanExporter`, `OtlpHttpMetricExporter`, - `OtlpHttpLogRecordExporter`. - -A sender is an abstraction which allows different gRPC / HTTP client -implementations to fulfill the OTLP contract. Regardless of the sender -implementation, the same exporter classes are used. A sender implementation is -automatically used when it is detected on the classpath. The sender -implementations are described in detail below: - -- `{groupId}:{artifactId}` - Sender description. -- `io.opentelemetry:opentelemetry-exporter-sender-okhttp` - The default sender, - included automatically with `opentelemetry-exporter-otlp` and bundled with the - OpenTelemetry Java agent. This includes an - [OkHttp](https://square.github.io/okhttp/) based implementation for both the - `grpc` and `http/protobuf` versions of the protocol, and will be suitable for - most users. However, OkHttp has a transitive dependency on kotlin which is - problematic in some environments. -- `io.opentelemetry:opentelemetry-exporter-sender-jdk` - This sender includes a - JDK 11+ - [HttpClient](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html) - based implementation for the `http/protobuf` version of the protocol. It - requires zero additional dependencies, but requires Java 11+. To use, include - the artifact and explicitly exclude the default - `io.opentelemetry:opentelemetry-exporter-sender-okhttp` dependency. -- `io.opentelemetry:opentelemetry-exporter-sender-grpc-managed-channel` - This - sender includes a [grpc-java](https://github.com/grpc/grpc-java) based - implementation for the `grpc` version of the protocol. To use, include the - artifact, explicitly exclude the default - `io.opentelemetry:opentelemetry-exporter-sender-okhttp` dependency, and - include one of the - [gRPC transport implementations](https://github.com/grpc/grpc-java#transport). - -### Usage - -Next, configure the exporter to point at an OTLP endpoint. - -If you use -[SDK autoconfiguration](/docs/languages/java/instrumentation/#automatic-configuration) -all you need to do is update your environment variables: - -```shell -env OTEL_EXPORTER_OTLP_ENDPOINT=http://example:4317 java -jar ./build/libs/java-simple.jar -``` - -Note, that in the case of exporting via OTLP you do not need to set -`OTEL_TRACES_EXPORTER`, `OTEL_METRICS_EXPORTER` and `OTEL_LOGS_EXPORTER` since -`otlp` is their default value - -In the case of [manual configuration] you can update the [example app](/docs/languages/java/instrumentation#example-app) -like the following: - - - -```java -package otel; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; -import io.opentelemetry.context.propagation.ContextPropagators; -import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter; -import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter; -import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.sdk.logs.SdkLoggerProvider; -import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor; -import io.opentelemetry.sdk.metrics.SdkMeterProvider; -import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; -import io.opentelemetry.semconv.ServiceAttributes; -import org.springframework.boot.Banner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -@SpringBootApplication -public class DiceApplication { - public static void main(String[] args) { - SpringApplication app = new SpringApplication(DiceApplication.class); - app.setBannerMode(Banner.Mode.OFF); - app.run(args); - } - - @Bean - public OpenTelemetry openTelemetry() { - Resource resource = - Resource.getDefault().toBuilder() - .put(ServiceAttributes.SERVICE_NAME, "dice-server") - .put(ServiceAttributes.SERVICE_VERSION, "0.1.0") - .build(); - - SdkTracerProvider sdkTracerProvider = - SdkTracerProvider.builder() - .addSpanProcessor( - BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder().build()).build()) - .setResource(resource) - .build(); - - SdkMeterProvider sdkMeterProvider = - SdkMeterProvider.builder() - .registerMetricReader( - PeriodicMetricReader.builder(OtlpGrpcMetricExporter.builder().build()).build()) - .setResource(resource) - .build(); - - SdkLoggerProvider sdkLoggerProvider = - SdkLoggerProvider.builder() - .addLogRecordProcessor( - BatchLogRecordProcessor.builder(OtlpGrpcLogRecordExporter.builder().build()) - .build()) - .setResource(resource) - .build(); - - OpenTelemetry openTelemetry = - OpenTelemetrySdk.builder() - .setTracerProvider(sdkTracerProvider) - .setMeterProvider(sdkMeterProvider) - .setLoggerProvider(sdkLoggerProvider) - .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) - .buildAndRegisterGlobal(); - - return openTelemetry; - } -} -``` - - -## Console - -To debug your instrumentation or see the values locally in development, you can -use exporters writing telemetry data to the console (stdout). - -If you followed the [Getting Started](/docs/languages/java/getting-started/) or -[Manual Instrumentation](/docs/languages/java/instrumentation/) guides, you -already have the console exporter installed. - -The `LoggingSpanExporter`, the `LoggingMetricExporter` and the -`SystemOutLogRecordExporter` are included in the -`opentelemetry-exporter-logging` artifact. - -If you use -[SDK autoconfiguration](/docs/languages/java/instrumentation/#automatic-configuration) -all you need to do is update your environment variables: - -```shell -env OTEL_TRACES_EXPORTER=logging OTEL_METRICS_EXPORTER=logging OTEL_LOGS_EXPORTER=logging java -jar ./build/libs/java-simple.jar -``` - -{{% docs/languages/exporters/jaeger %}} - -{{% docs/languages/exporters/prometheus-setup %}} - -### Dependencies {#prometheus-dependencies} - -Install the -[`opentelemetry-exporter-prometheus`](https://javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-prometheus/latest) -artifact as a dependency for your application: - -{{< tabpane text=true >}} {{% tab Gradle %}} - -```kotlin -dependencies { - implementation 'io.opentelemetry:opentelemetry-exporter-prometheus:{{% param vers.otel %}}-alpha' -} -``` - -{{% /tab %}} {{% tab Maven %}} - -```xml - - - - io.opentelemetry - opentelemetry-exporter-prometheus - - - -``` - -{{< /tab >}} {{< /tabpane>}} - -Update your OpenTelemetry configuration to use the exporter and to send data to -your Prometheus backend: - - - -```java -package otel; - -import io.opentelemetry.exporter.prometheus.PrometheusHttpServer; -import io.opentelemetry.sdk.metrics.SdkMeterProvider; -import io.opentelemetry.sdk.resources.Resource; - -public class PrometheusExporter { - public static SdkMeterProvider create(Resource resource) { - int prometheusPort = 9464; - SdkMeterProvider sdkMeterProvider = - SdkMeterProvider.builder() - .registerMetricReader(PrometheusHttpServer.builder().setPort(prometheusPort).build()) - .setResource(resource) - .build(); - - return sdkMeterProvider; - } -} -``` - - -With the above you can access your metrics at . -Prometheus or an OpenTelemetry Collector with the Prometheus receiver can scrape -the metrics from this endpoint. - -{{% docs/languages/exporters/zipkin-setup %}} - -### Dependencies {#zipkin-dependencies} - -To send your trace data to [Zipkin](https://zipkin.io/), you can use the -`ZipkinSpanExporter`. - -Install the -[`opentelemetry-exporter-zipkin`](https://javadoc.io/doc/io.opentelemetry/opentelemetry-exporter-zipkin/latest) -artifact as a dependency for your application: - -{{< tabpane text=true >}} {{% tab Gradle %}} - -```kotlin -dependencies { - implementation 'io.opentelemetry:opentelemetry-exporter-zipkin:{{% param vers.otel %}}-alpha' -} -``` - -{{% /tab %}} {{% tab Maven %}} - -```xml - - - - io.opentelemetry - opentelemetry-exporter-zipkin - - - -``` - -{{< /tab >}} {{< /tabpane>}} - -Update your OpenTelemetry configuration to use the exporter and to send data to -your Zipkin backend: - - - -```java -package otel; - -import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; - -public class ZipkinExporter { - public static SdkTracerProvider create(Resource resource) { - SdkTracerProvider sdkTracerProvider = - SdkTracerProvider.builder() - .addSpanProcessor( - BatchSpanProcessor.builder( - ZipkinSpanExporter.builder() - .setEndpoint("http://localhost:9411/api/v2/spans") - .build()) - .build()) - .setResource(resource) - .build(); - - return sdkTracerProvider; - } -} -``` - - -{{% docs/languages/exporters/outro java "https://javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/export/SpanExporter.html" %}} - -{{< tabpane text=true >}} {{% tab Batch %}} - - - -```java -package otel; - -import io.opentelemetry.sdk.logs.SdkLoggerProvider; -import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor; -import io.opentelemetry.sdk.logs.export.LogRecordExporter; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; -import io.opentelemetry.sdk.trace.export.SpanExporter; - -public class BatchExporter { - public static void create( - Resource resource, SpanExporter spanExporter, LogRecordExporter logExporter) { - SdkTracerProvider sdkTracerProvider = - SdkTracerProvider.builder() - .addSpanProcessor(BatchSpanProcessor.builder(spanExporter).build()) - .setResource(resource) - .build(); - - SdkLoggerProvider sdkLoggerProvider = - SdkLoggerProvider.builder() - .addLogRecordProcessor(BatchLogRecordProcessor.builder(logExporter).build()) - .setResource(resource) - .build(); - } -} -``` - -{{% /tab %}} {{% tab Simple %}} - - -```java -package otel; - -import io.opentelemetry.sdk.logs.SdkLoggerProvider; -import io.opentelemetry.sdk.logs.export.LogRecordExporter; -import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; -import io.opentelemetry.sdk.trace.export.SpanExporter; - -public class SimpleExporter { - public static void create( - Resource resource, SpanExporter spanExporter, LogRecordExporter logExporter) { - SdkTracerProvider sdkTracerProvider = - SdkTracerProvider.builder() - .addSpanProcessor(SimpleSpanProcessor.builder(spanExporter).build()) - .setResource(resource) - .build(); - - SdkLoggerProvider sdkLoggerProvider = - SdkLoggerProvider.builder() - .addLogRecordProcessor(SimpleLogRecordProcessor.create(logExporter)) - .setResource(resource) - .build(); - } -} -``` - -{{< /tab >}} {{< /tabpane>}} - - - -{{% /docs/languages/exporters/outro %}} diff --git a/content/en/docs/languages/java/getting-started.md b/content/en/docs/languages/java/getting-started.md index 83555c56af26..bb4078b15cfd 100644 --- a/content/en/docs/languages/java/getting-started.md +++ b/content/en/docs/languages/java/getting-started.md @@ -26,7 +26,7 @@ The following example uses a basic [Spring Boot] application. You can use anothe web framework, such as Apache Wicket or Play. For a complete list of libraries and supported frameworks, consult the [registry](/ecosystem/registry/?component=instrumentation&language=java). -For more elaborate examples, see [examples](/docs/languages/java/examples/). +For more elaborate examples, see [examples](../examples/). ### Dependencies @@ -248,7 +248,7 @@ For more: - Try [zero-code instrumentation](/docs/zero-code/java/agent/) on one of your own apps. - For light-weight customized telemetry, try [annotations][]. -- Learn about [manual instrumentation][] and try out more [examples](/docs/languages/java/examples/). +- Learn about [manual instrumentation][] and try out more [examples](../examples/). - Take a look at the [OpenTelemetry Demo](/docs/demo/), which includes Java based [Ad Service](/docs/demo/services/ad/) and Kotlin based [Fraud Detection Service](/docs/demo/services/fraud-detection/) diff --git a/content/en/docs/languages/java/instrumentation.md b/content/en/docs/languages/java/instrumentation.md index dec20efbf304..f106bfc12bcc 100644 --- a/content/en/docs/languages/java/instrumentation.md +++ b/content/en/docs/languages/java/instrumentation.md @@ -15,6 +15,13 @@ cSpell:ignore: Autowired customizer logback loggable multivalued rolldice spring {{% docs/languages/instrumentation-intro %}} +{{% alert title="Note" color="info" %}} See [Manage Telemetry with SDK](../sdk/) +for a conceptual overview of OpenTelemetry Java SDK concepts. See +**[Configure the SDK](../configuration/)** for details on SDK configuration, +including +[zero-code SDK autoconfigure](../configuration/#zero-code-sdk-autoconfigure). +{{% /alert %}} + {{% alert title="Note" color="info" %}} On this page you will learn how you can add traces, metrics and logs to your @@ -27,16 +34,15 @@ skip manual instrumentation and only use automatic instrumentation. Also, for libraries your code depends on, you don't have to write instrumentation code yourself, since they might come with OpenTelemetry built-in -_natively_ or you can make use of -[instrumentation libraries](/docs/languages/java/libraries/). +_natively_ or you can make use of [instrumentation libraries](../libraries/). {{% /alert %}} ## Example app preparation {#example-app} This page uses a modified version of the example app from -[Getting Started](/docs/languages/java/getting-started/) to help you learn about -manual instrumentation. +[Getting Started](../getting-started/) to help you learn about manual +instrumentation. You don't have to use the example app: if you want to instrument your own app or library, follow the instructions here to adapt the process to your own code. @@ -266,310 +272,11 @@ dependencies { {{% /tab %}} {{% /tabpane %}} -### Initialize the SDK - -{{% alert title="Note" color="info" %}} If you’re instrumenting a library, -**skip this step**. {{% /alert %}} - -The OpenTelemetry API provides a set of interfaces for collecting telemetry, but -the data is dropped without an implementation. The OpenTelemetry SDK is the -implementation of the OpenTelemetry API provided by OpenTelemetry. To use it if -you instrument a Java app, begin by installing dependencies: - -{{< tabpane text=true >}} {{% tab Gradle %}} - -```kotlin { hl_lines="4-6" } -dependencies { - implementation("org.springframework.boot:spring-boot-starter-web"); - implementation("io.opentelemetry:opentelemetry-api"); - implementation("io.opentelemetry:opentelemetry-sdk"); - implementation("io.opentelemetry:opentelemetry-exporter-logging"); - implementation("io.opentelemetry.semconv:opentelemetry-semconv:{{% param vers.semconv %}}-alpha"); -} -``` - -{{% /tab %}} {{% tab Maven %}} - -```xml - - - - io.opentelemetry - opentelemetry-sdk - - - io.opentelemetry - opentelemetry-exporter-logging - - - - io.opentelemetry.semconv - opentelemetry-semconv - {{% param vers.semconv %}}-alpha - - - -``` - -{{% /tab %}} {{< /tabpane>}} - -If you are an application developer, you need to configure an instance of the -`OpenTelemetrySdk` as early as possible in your application. This can either be -done manually by using the `OpenTelemetrySdk.builder()` or by using the SDK -autoconfiguration extension through the -`opentelemetry-sdk-extension-autoconfigure` module. It is recommended to use -autoconfiguration, as it is easier to use and comes with various additional -capabilities. - -#### Automatic Configuration - -To use autoconfiguration add the following dependency to your application: - -{{< tabpane text=true >}} {{% tab Gradle %}} - -```kotlin { hl_lines="7" } -dependencies { - implementation("org.springframework.boot:spring-boot-starter-web"); - implementation("io.opentelemetry:opentelemetry-api"); - implementation("io.opentelemetry:opentelemetry-sdk"); - implementation("io.opentelemetry:opentelemetry-exporter-logging"); - implementation("io.opentelemetry.semconv:opentelemetry-semconv:{{% param vers.semconv %}}-alpha"); - implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure"); -} -``` - -{{% /tab %}} {{% tab Maven %}} - -```xml - - - - io.opentelemetry - opentelemetry-sdk-extension-autoconfigure - - - io.opentelemetry - opentelemetry-sdk-extension-autoconfigure-spi - - - -``` - -{{% /tab %}} {{< /tabpane>}} - -It allows you to autoconfigure the OpenTelemetry SDK based on a standard set of -supported environment variables and system properties. Each environment variable -has a corresponding system property named the same way but as lower case and -using the `.` (dot) character instead of the `_` (underscore) as separator. -Reference the [configuration](/docs/languages/java/configuration/) page for -details on all available options. - -The logical service name can be specified via the `OTEL_SERVICE_NAME` -environment variable (or `otel.service.name` system property). - -The traces, metrics or logs exporters can be set via the `OTEL_TRACES_EXPORTER`, -`OTEL_METRICS_EXPORTER` and `OTEL_LOGS_EXPORTER` environment variables. For -example `OTEL_TRACES_EXPORTER=logging` configures your application to use an -exporter that writes all traces to the console. The corresponding exporter -library has to be provided in the classpath of the application as well. - -For debugging and local development purposes, use the `logging` exporter. After -you have finished setting up manual instrumentation, provide an appropriate -exporter library in the classpath of the application to -[export the app's telemetry data](/docs/languages/java/exporters/) to one or -more telemetry backends. - -The SDK autoconfiguration has to be initialized as early as possible in the -application lifecycle in order to allow the module to go through the provided -environment variables (or system properties) and set up the `OpenTelemetry` -instance by using the builders internally. - -```java -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; - -OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.initialize() - .getOpenTelemetrySdk(); -``` - -In the case of the [example app](#example-app) the `DiceApplication` class gets -updated as follows: - -```java { hl_lines=["6-9","19-22"] } -package otel; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.Banner; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; - -@SpringBootApplication -public class DiceApplication { - public static void main(String[] args) { - SpringApplication app = new SpringApplication(DiceApplication.class); - app.setBannerMode(Banner.Mode.OFF); - app.run(args); - } - - @Bean - public OpenTelemetry openTelemetry() { - return AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk(); - } -} -``` - -To verify your code, build and run the app: - -```sh -gradle assemble -env \ -OTEL_SERVICE_NAME=dice-server \ -OTEL_TRACES_EXPORTER=logging \ -OTEL_METRICS_EXPORTER=logging \ -OTEL_LOGS_EXPORTER=logging \ -OTEL_METRIC_EXPORT_INTERVAL=15000 \ -java -jar ./build/libs/java-simple.jar -``` - -This basic setup has no effect on your app yet. You need to add code for -[traces](#traces), [metrics](#metrics), and/or [logs](#logs). - -Note that `OTEL_METRIC_EXPORT_INTERVAL=15000` (milliseconds) is a temporary -setting to test that your metrics are properly generated. Remember to remove the -setting once you are done testing. The default is 60000 milliseconds. - -#### Manual Configuration - -`OpenTelemetrySdk.builder()` returns an instance of `OpenTelemetrySdkBuilder`, -which gets the providers related to the signals, tracing and metrics, in order -to build the `OpenTelemetry` instance. - -You can build the providers by using the `SdkTracerProvider.builder()` and -`SdkMeterProvider.builder()` methods. - -In the case of the [example app](#example-app) the the `DiceApplication` class -gets updated as follows: - -```java { hl_lines=["6-24","34-62"] } -package otel; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.Banner; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.context.propagation.TextMapPropagator; -import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; -import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator; -import io.opentelemetry.context.propagation.ContextPropagators; -import io.opentelemetry.exporter.logging.LoggingMetricExporter; -import io.opentelemetry.exporter.logging.LoggingSpanExporter; -import io.opentelemetry.exporter.logging.SystemOutLogRecordExporter; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.sdk.metrics.SdkMeterProvider; -import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; -import io.opentelemetry.sdk.logs.SdkLoggerProvider; -import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor; -import io.opentelemetry.sdk.logs.export.LogRecordExporter; -import io.opentelemetry.semconv.ResourceAttributes; - -@SpringBootApplication -public class DiceApplication { - public static void main(String[] args) { - SpringApplication app = new SpringApplication(DiceApplication.class); - app.setBannerMode(Banner.Mode.OFF); - app.run(args); - } - - @Bean - public OpenTelemetry openTelemetry() { - Resource resource = Resource.getDefault().toBuilder().put(ResourceAttributes.SERVICE_NAME, "dice-server").put(ResourceAttributes.SERVICE_VERSION, "0.1.0").build(); - - SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() - .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) - .setResource(resource) - .build(); - - SdkMeterProvider sdkMeterProvider = SdkMeterProvider.builder() - .registerMetricReader(PeriodicMetricReader.builder(LoggingMetricExporter.create()).build()) - .setResource(resource) - .build(); - - SdkLoggerProvider sdkLoggerProvider = SdkLoggerProvider.builder() - .addLogRecordProcessor(BatchLogRecordProcessor.builder(SystemOutLogRecordExporter.create()).build()) - .setResource(resource) - .build(); - - OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() - .setTracerProvider(sdkTracerProvider) - .setMeterProvider(sdkMeterProvider) - .setLoggerProvider(sdkLoggerProvider) - .setPropagators(ContextPropagators.create(TextMapPropagator.composite(W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance()))) - .buildAndRegisterGlobal(); - - return openTelemetry; - } -} -``` - -For debugging and local development purposes, the example exports telemetry to -the console. After you have finished setting up manual instrumentation, you need -to configure an appropriate exporter to -[export the app's telemetry data](/docs/languages/java/exporters/) to one or -more telemetry backends. - -The example also sets up the mandatory SDK default attribute `service.name`, -which holds the logical name of the service, and the optional (but highly -encouraged!) attribute `service.version`, which holds the version of the service -API or implementation. - -Alternative methods exist for setting up resource attributes. For more -information, see [Resources](/docs/languages/java/resources/). - -To verify your code, build and run the app: - -```sh -gradle assemble -java -jar ./build/libs/java-simple.jar -``` - -This basic setup has no effect on your app yet. You need to add code for -[traces](#traces), [metrics](#metrics), and/or [logs](#logs). - ## Traces -### Initialize Tracing - -{{% alert title="Note" color="info" %}} If you’re instrumenting a library, -**skip this step**. {{% /alert %}} - -To enable [tracing](/docs/concepts/signals/traces/) in your app, you'll need to -have an initialized -[`TracerProvider`](/docs/concepts/signals/traces/#tracer-provider) that will let -you create a [`Tracer`](/docs/concepts/signals/traces/#tracer): - -```java -import io.opentelemetry.sdk.trace.SdkTracerProvider; - -SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() - .addSpanProcessor(spanProcessor) - .setResource(resource) - .build(); -``` - -If a `TracerProvider` is not created, the OpenTelemetry APIs for tracing will -use a no-op implementation and fail to generate data. - -If you followed the instructions to [initialize the SDK](#initialize-the-sdk) -above, you have a `TracerProvider` setup for you already. You can continue with -[acquiring a tracer](#acquiring-a-tracer). +The following sections describe the OpenTelemetry Java tracing API. See +[SdkTracerProvider](../sdk/#sdktracerprovider) for an overview of trace SDK +concepts and configuration. ### Acquiring a tracer @@ -1205,41 +912,9 @@ Synchronous instruments record measurements as they happen. Asynchronous instruments register a callback, which is invoked once per collection, and which records measurements at that point in time. -### Initialize Metrics - -{{% alert color="info" %}} If you’re instrumenting a library, skip this step. -{{% /alert %}} - -To enable [metrics](/docs/concepts/signals/metrics/) in your app, you need to -have an initialized -[`MeterProvider`](/docs/concepts/signals/metrics/#meter-provider) that lets you -create a [`Meter`](/docs/concepts/signals/metrics/#meter). If a `MeterProvider` -is not created, the OpenTelemetry APIs for metrics use a no-op implementation -and fail to generate data. - -If you followed the instructions to [initialize the SDK](#initialize-the-sdk) -above, you have a `MeterProvider` setup for you already. You can continue with -[acquiring a meter](#acquiring-a-meter). - -When creating a `MeterProvider` you can specify a [MetricReader](#metric-reader) -and [MetricExporter](/docs/languages/java/exporters/). The -`LoggingMetricExporter` is included in the `opentelemetry-exporter-logging` -artifact that was added in the [Initialize the SDK](#initialize-the-sdk) step. - -```java -SdkMeterProvider sdkMeterProvider = SdkMeterProvider.builder() - .registerMetricReader( - PeriodicMetricReader - .builder(LoggingMetricExporter.create()) - // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. - .setInterval(Duration.ofSeconds(10)).build()) - .build(); - -// Register MeterProvider with OpenTelemetry instance -OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() - .setMeterProvider(sdkMeterProvider) - .build(); -``` +The following sections describe the OpenTelemetry Java metrics API. See +[SdkMeterProvider](../sdk/#sdkmeterprovider) for an overview of metrics SDK +concepts and configuration. ### Acquiring a meter @@ -1412,91 +1087,6 @@ Attributes attrs = Attributes.of( histogram.record(7, attrs); ``` -### Metric Views - -Views provide a mechanism for controlling how measurements are aggregated into -metrics. They consist of an `InstrumentSelector` and a `View`. The instrument -selector consists of a series of options for selecting which instruments the -view applies to. Instruments can be selected by a combination of name, type, -meter name, meter version, and meter schema URL. The view describes how -measurement should be aggregated. The view can change the name, description, the -aggregation, and define the set of attribute keys that should be retained. - -```java -SdkMeterProvider meterProvider = SdkMeterProvider.builder() - .registerView( - InstrumentSelector.builder() - .setName("my-counter") // Select instrument(s) called "my-counter" - .build(), - View.builder() - .setName("new-counter-name") // Change the name to "new-counter-name" - .build()) - .registerMetricReader(...) - .build(); -``` - -Every instrument has a default view, which retains the original name, -description, and attributes, and has a default aggregation that is based on the -type of instrument. When a registered view matches an instrument, the default -view is replaced by the registered view. Additional registered views that match -the instrument are additive, and result in multiple exported metrics for the -instrument. - -#### Selectors - -To instantiate a view, one must first select a target instrument. The following -are valid selectors for metrics: - -- instrumentType -- instrumentName -- meterName -- meterVersion -- meterSchemaUrl - -Selecting by `instrumentName` (of type string) has support for wildcards, so you -can select all instruments using `*` or select all instruments whose name starts -with `http` by using `http*`. - -#### Examples - -Filter attributes on all metric types: - -```java -SdkMeterProvider meterProvider = SdkMeterProvider.builder() - .registerView( - // apply the view to all instruments - InstrumentSelector.builder().setName("*").build(), - // only export the attribute 'environment' - View.builder().setAttributeFilter(Set.of("environment")).build()) - .build(); -``` - -Drop all instruments with the meter name "pubsub": - -```java -SdkMeterProvider meterProvider = SdkMeterProvider.builder() - .registerView( - InstrumentSelector.builder().setMeterName("pubsub").build(), - View.builder().setAggregation(Aggregation.drop()).build()) - .build(); -``` - -Define explicit bucket sizes for the Histogram named -`http.server.request.duration`: - -```java -SdkMeterProvider meterProvider = SdkMeterProvider.builder() - .registerView( - InstrumentSelector.builder().setName("http.server.request.duration").build(), - View.builder() - .setAggregation( - Aggregation.explicitBucketHistogram( - List.of(0.0, 1.0, 5.0, 10.0, 20.0, 25.0, 30.0) - ) - ).build() - ).build(); -``` - ## Logs Logs are distinct from metrics and traces in that **there is no user-facing @@ -1521,15 +1111,16 @@ suitable for all applications. To use this workflow: - Install appropriate [Log Appender](#log-appenders). -- Configure the OpenTelemetry [Log SDK](#logs-sdk) to export log records to - desired target destination (the [collector][opentelemetry collector] or - other). +- Configure the OpenTelemetry [Log SDK](../sdk/#sdkloggerprovider) to export log + records to desired target destination (the + [collector][opentelemetry collector] or other). #### Log appenders A log appender bridges logs from a log framework into the OpenTelemetry -[Log SDK](#logs-sdk) using the [Logs Bridge API][logs bridge API]. Log appenders -are available for various popular Java log frameworks: +[Log SDK](../sdk/#sdkloggerprovider) using the [Logs Bridge +API][logs bridge API]. Log appenders are available for various popular Java log +frameworks: - [Log4j2 Appender][log4j2 appender] - [Logback Appender][logback appender] @@ -1552,6 +1143,9 @@ log correlation with traces. The [Log Appender example][log appender example] demonstrates setup for a variety of scenarios. +See [SdkLoggerProvider](../sdk/#sdkloggerprovider) for an overview of log SDK +concepts and configuration. + ### Via file or stdout In the file or stdout workflow, logs are written to files or standout output. @@ -1583,348 +1177,6 @@ installation is generally as follows: - Extend the application's log configuration (i.e. `logback.xml` or `log4j.xml`, etc) to reference the trace context fields in the log pattern. -## SDK Configuration - -The configuration examples reported in this document only apply to the SDK -provided by `opentelemetry-sdk`. Other implementation of the API might provide -different configuration mechanisms. - -### Tracing SDK - -The application has to install a span processor with an exporter and may -customize the behavior of the OpenTelemetry SDK. - -For example, a basic configuration instantiates the SDK tracer provider and sets -to export the traces to a logging stream. - -```java -SdkTracerProvider tracerProvider = SdkTracerProvider.builder() - .addSpanProcessor(BatchSpanProcessor.builder(LoggingSpanExporter.create()).build()) - .build(); -``` - -#### Sampler - -It is not always feasible to trace and export every user request in an -application. In order to strike a balance between observability and expenses, -traces can be sampled. - -The OpenTelemetry SDK offers four samplers out of the box: - -- [AlwaysOnSampler] which samples every trace regardless of upstream sampling - decisions. -- [AlwaysOffSampler] which doesn't sample any trace, regardless of upstream - sampling decisions. -- [ParentBased] which uses the parent span to make sampling decisions, if - present. -- [TraceIdRatioBased] which samples a configurable percentage of traces, and - additionally samples any trace that was sampled upstream. - -Additional samplers can be provided by implementing the -`io.opentelemetry.sdk.trace.Sampler` interface. - -```java -SdkTracerProvider tracerProvider = SdkTracerProvider.builder() - .setSampler(Sampler.alwaysOn()) - //or - .setSampler(Sampler.alwaysOff()) - //or - .setSampler(Sampler.traceIdRatioBased(0.5)) - .build(); -``` - -#### Span Processor - -Different Span processors are offered by OpenTelemetry. The -`SimpleSpanProcessor` immediately forwards ended spans to the exporter, while -the `BatchSpanProcessor` batches them and sends them in bulk. Multiple Span -processors can be configured to be active at the same time using the -`MultiSpanProcessor`. - -```java -SdkTracerProvider tracerProvider = SdkTracerProvider.builder() - .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) - .addSpanProcessor(BatchSpanProcessor.builder(LoggingSpanExporter.create()).build()) - .build(); -``` - -#### Exporter - -Span processors are initialized with an exporter which is responsible for -sending the telemetry data a particular backend. OpenTelemetry offers five -exporters out of the box: - -- `InMemorySpanExporter`: keeps the data in memory, useful for testing and - debugging. -- Jaeger Exporter: prepares and sends the collected telemetry data to a Jaeger - backend via gRPC. Varieties include `JaegerGrpcSpanExporter` and - `JaegerThriftSpanExporter`. -- `ZipkinSpanExporter`: prepares and sends the collected telemetry data to a - Zipkin backend via the Zipkin APIs. -- Logging Exporter: saves the telemetry data into log streams. Varieties include - `LoggingSpanExporter` and `OtlpJsonLoggingSpanExporter`. -- OpenTelemetry Protocol Exporter: sends the data in OTLP to the [OpenTelemetry - Collector] or other OTLP receivers. Varieties include `OtlpGrpcSpanExporter` and - `OtlpHttpSpanExporter`. - -Other exporters can be found in the [OpenTelemetry Registry]. - -```java -ManagedChannel jaegerChannel = ManagedChannelBuilder.forAddress("localhost", 3336) - .usePlaintext() - .build(); - -JaegerGrpcSpanExporter jaegerExporter = JaegerGrpcSpanExporter.builder() - .setEndpoint("localhost:3336") - .setTimeout(30, TimeUnit.SECONDS) - .build(); - -SdkTracerProvider tracerProvider = SdkTracerProvider.builder() - .addSpanProcessor(BatchSpanProcessor.builder(jaegerExporter).build()) - .build(); -``` - -### Metrics SDK - -The application has to install a metric reader with an exporter, and may further -customize the behavior of the OpenTelemetry SDK. - -For example, a basic configuration instantiates the SDK meter provider and sets -to export the metrics to a logging stream. - -```java -SdkMeterProvider meterProvider = SdkMeterProvider.builder() - .registerMetricReader(PeriodicMetricReader.builder(LoggingMetricExporter.create()).build()) - .build(); -``` - -#### Metric Reader - -Metric readers read aggregated metrics. - -```java -SdkMeterProvider meterProvider = SdkMeterProvider.builder() - .registerMetricReader(...) - .build(); -``` - -OpenTelemetry provides a variety of metric readers out of the box: - -- `PeriodicMetricReader`: reads metrics on a configurable interval and pushes to - a `MetricExporter`. -- `InMemoryMetricReader`: reads metrics into memory, useful for debugging and - testing. -- `PrometheusHttpServer` (alpha): an HTTP server that reads metrics and - serializes to Prometheus text format. - -Custom metric reader implementations are not currently supported. - -#### Exporter - -The `PeriodicMetricReader` is paired with a metric exporter, which is -responsible for sending the telemetry data to a particular backend. -OpenTelemetry provides the following exporters out of the box: - -- `InMemoryMetricExporter`: keeps the data in memory, useful for testing and - debugging. -- Logging Exporter: saves the telemetry data into log streams. Varieties include - `LoggingMetricExporter` and `OtlpJsonLoggingMetricExporter`. -- OpenTelemetry Protocol Exporter: sends the data in OTLP to the [OpenTelemetry - Collector] or other OTLP receivers. Varieties include `OtlpGrpcMetricExporter` - and `OtlpHttpMetricExporter`. - -Other exporters can be found in the [OpenTelemetry Registry]. - -### Logs SDK - -The logs SDK dictates how logs are processed when using the -[direct to collector](#direct-to-collector) workflow. No log SDK is needed when -using the [log forwarding](#via-file-or-stdout) workflow. - -The typical log SDK configuration installs a log record processor and exporter. -For example, the following installs the -[BatchLogRecordProcessor](#logrecord-processor), which periodically exports to a -network location via the [OtlpGrpcLogRecordExporter](#logrecord-exporter): - -```java -SdkLoggerProvider loggerProvider = SdkLoggerProvider.builder() - .addLogRecordProcessor( - BatchLogRecordProcessor.builder( - OtlpGrpcLogRecordExporter.builder() - .setEndpoint("http://localhost:4317") - .build()) - .build()) - .build(); -``` - -#### LogRecord Processor - -LogRecord processors process LogRecords emitted by -[log appenders](#log-appenders). - -OpenTelemetry provides the following LogRecord processors out of the box: - -- `BatchLogRecordProcessor`: periodically sends batches of LogRecords to a - [LogRecordExporter](#logrecord-exporter). -- `SimpleLogRecordProcessor`: immediately sends each LogRecord to a - [LogRecordExporter](#logrecord-exporter). - -Custom LogRecord processors are supported by implementing the -`LogRecordProcessor` interface. Common use cases include enriching the -LogRecords with contextual data like baggage, or filtering / obfuscating -sensitive data. - -#### LogRecord Exporter - -`BatchLogRecordProcessor` and `SimpleLogRecordProcessor` are paired with -`LogRecordExporter`, which is responsible for sending telemetry data to a -particular backend. OpenTelemetry provides the following exporters out of the -box: - -- OpenTelemetry Protocol Exporter: sends the data in OTLP to the [OpenTelemetry - Collector] or other OTLP receivers. Varieties include `OtlpGrpcLogRecordExporter` - and `OtlpHttpLogRecordExporter`. -- `InMemoryLogRecordExporter`: keeps the data in memory, useful for testing and - debugging. -- Logging Exporter: saves the telemetry data into log streams. Varieties include - `SystemOutLogRecordExporter` and `OtlpJsonLoggingLogRecordExporter`. Note: - `OtlpJsonLoggingLogRecordExporter` logs to JUL, and may cause infinite loops - (i.e. JUL -> SLF4J -> Logback -> OpenTelemetry Appender -> OpenTelemetry Log - SDK -> JUL) if not carefully configured. - -Custom exporters are supported by implementing the `LogRecordExporter` -interface. - -### Autoconfiguration - -Instead of manually creating the `OpenTelemetry` instance by using the SDK -builders directly from your code, it is also possible to use the SDK -autoconfiguration extension through the -`opentelemetry-sdk-extension-autoconfigure` module. - -This module is made available by adding the following dependency to your -application. - -```xml - - io.opentelemetry - opentelemetry-sdk-extension-autoconfigure - -``` - -It allows you to autoconfigure the OpenTelemetry SDK based on a standard set of -supported environment variables and system properties. Each environment variable -has a corresponding system property named the same way but as lower case and -using the `.` (dot) character instead of the `_` (underscore) as separator. - -The logical service name can be specified via the `OTEL_SERVICE_NAME` -environment variable (or `otel.service.name` system property). - -The traces, metrics or logs exporters can be set via the `OTEL_TRACES_EXPORTER`, -`OTEL_METRICS_EXPORTER` and `OTEL_LOGS_EXPORTER` environment variables. For -example `OTEL_TRACES_EXPORTER=jaeger` configures your application to use the -Jaeger exporter. The corresponding Jaeger exporter library has to be provided in -the classpath of the application as well. - -If you use the `console` or `logging` exporter for metrics, consider temporarily -setting `OTEL_METRIC_EXPORT_INTERVAL` to a small value like `15000` -(milliseconds) while testing that your metrics are properly recorded. Remember -to remove the setting once you are done testing. - -It's also possible to set up the propagators via the `OTEL_PROPAGATORS` -environment variable, like for example using the `tracecontext` value to use -[W3C Trace Context](https://www.w3.org/TR/trace-context/). - -For more details, see all the supported configuration options in the module's -[README](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure). - -The SDK autoconfiguration has to be initialized from your code in order to allow -the module to go through the provided environment variables (or system -properties) and set up the `OpenTelemetry` instance by using the builders -internally. - -```java -OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.initialize() - .getOpenTelemetrySdk(); -``` - -When environment variables or system properties are not sufficient, you can use -some extension points provided through the autoconfigure -[SPI](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure-spi) -and several methods in the `AutoConfiguredOpenTelemetrySdk` class. - -Following an example with a code snippet for adding an additional custom span -processor. - -```java -AutoConfiguredOpenTelemetrySdk.builder() - .addTracerProviderCustomizer( - (sdkTracerProviderBuilder, configProperties) -> - sdkTracerProviderBuilder.addSpanProcessor( - new SpanProcessor() { /* implementation omitted for brevity */ })) - .build(); -``` - -## SDK Logging and Error Handling - -OpenTelemetry uses -[java.util.logging](https://docs.oracle.com/javase/7/docs/api/java/util/logging/package-summary.html) -to log information about OpenTelemetry, including errors and warnings about -misconfigurations or failures exporting data. - -By default, log messages are handled by the root handler in your application. If -you have not installed a custom root handler for your application, logs of level -`INFO` or higher are sent to the console by default. - -You may want to change the behavior of the logger for OpenTelemetry. For -example, you can reduce the logging level to output additional information when -debugging, increase the level for a particular class to ignore errors coming -from that class, or install a custom handler or filter to run custom code -whenever OpenTelemetry logs a particular message. - -### Examples - -```properties -## Turn off all OpenTelemetry logging -io.opentelemetry.level = OFF -``` - -```properties -## Turn off logging for just the BatchSpanProcessor -io.opentelemetry.sdk.trace.export.BatchSpanProcessor.level = OFF -``` - -```properties -## Log "FINE" messages for help in debugging -io.opentelemetry.level = FINE - -## Sets the default ConsoleHandler's logger's level -## Note this impacts the logging outside of OpenTelemetry as well -java.util.logging.ConsoleHandler.level = FINE -``` - -For more fine-grained control and special case handling, custom handlers and -filters can be specified with code. - -```java -// Custom filter which does not log errors that come from the export -public class IgnoreExportErrorsFilter implements Filter { - - public boolean isLoggable(LogRecord record) { - return !record.getMessage().contains("Exception thrown by the export"); - } -} -``` - -```properties -## Registering the custom filter on the BatchSpanProcessor -io.opentelemetry.sdk.trace.export.BatchSpanProcessor = io.opentelemetry.extension.logging.IgnoreExportErrorsFilter -``` - -[alwaysoffsampler]: - https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/AlwaysOffSampler.java -[alwaysonsampler]: - https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/AlwaysOnSampler.java [httpexchange]: https://docs.oracle.com/javase/8/docs/jre/api/net/httpserver/spec/com/sun/net/httpserver/HttpExchange.html [java-vers]: @@ -1946,10 +1198,5 @@ io.opentelemetry.sdk.trace.export.BatchSpanProcessor = io.opentelemetry.extensio [obtaining a tracer]: /docs/specs/otel/trace/api/#get-a-tracer [opentelemetry collector]: https://github.com/open-telemetry/opentelemetry-collector -[opentelemetry registry]: /ecosystem/registry/?component=exporter&language=java -[parentbased]: - https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/ParentBasedSampler.java -[traceidratiobased]: - https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/TraceIdRatioBasedSampler.java [Java agent]: /docs/zero-code/java/agent/ [Spring Boot starter]: /docs/zero-code/java/spring-boot-starter/ diff --git a/content/en/docs/languages/java/libraries.md b/content/en/docs/languages/java/libraries.md index 8d854a4b86a8..e222378b2738 100644 --- a/content/en/docs/languages/java/libraries.md +++ b/content/en/docs/languages/java/libraries.md @@ -30,8 +30,7 @@ The following example instruments an HTTP client application using library instrumentation which calls an HTTP server. You can use the dice example app as HTTP server from -[Getting Started](/docs/languages/java/getting-started/) or you can create your -own HTTP server. +[Getting Started](../getting-started/) or you can create your own HTTP server. ### Dependencies @@ -147,8 +146,7 @@ public final class SampleHttpClient { Set the `EXTERNAL_API_ENDPOINT` environment variable to specify the external API endpoint. By default, it points to `http://localhost:8080/rolldice`, where -[example dice app](/docs/languages/java/getting-started/#example-application) is -running. +[example dice app](../getting-started/#example-application) is running. To check your code, run the app: @@ -166,8 +164,8 @@ When you run the app, the instrumentation libraries do the following: - Start a new trace. - Generate a span that represents the request made to the external API endpoint. - If you use an instrumented HTTP server, as in the - [dice app](/docs/languages/java/getting-started/#example-application), more - trace spans are generated with the same trace ID. + [dice app](../getting-started/#example-application), more trace spans are + generated with the same trace ID. ## Available instrumentation libraries @@ -177,12 +175,11 @@ For a full list of instrumentation libraries, see ## Next steps After you've set up instrumentation libraries, you might want to add -[additional instrumentation](/docs/languages/java/instrumentation) to collect -custom telemetry data. +[additional instrumentation](../instrumentation) to collect custom telemetry +data. -You might also want to configure an appropriate exporter to -[export your telemetry data](/docs/languages/java/exporters) to one or more -telemetry backends. +You might also want to [configure the SDK](../configuration/) to export to one +or more telemetry backends. For existing library instrumentations, also see [Java agent](/docs/zero-code/java/agent/). diff --git a/content/en/docs/languages/java/performance.md b/content/en/docs/languages/java/performance.md index cf290a190209..1c93542accf0 100644 --- a/content/en/docs/languages/java/performance.md +++ b/content/en/docs/languages/java/performance.md @@ -40,7 +40,7 @@ the Java agent. The volume of spans processed by the instrumentation might impact agent overhead. You can configure trace sampling to adjust the span volume and reduce -resource usage. See [Sampling](/docs/languages/java/sampling). +resource usage. See [Sampling](../sdk/#sampler). ### Turn off specific instrumentations @@ -99,7 +99,7 @@ instrumentations, see When troubleshooting agent overhead issues, do the following: - Check minimum requirements. See - [Prerequisites](/docs/languages/java/getting-started/#prerequisites). + [Prerequisites](../getting-started/#prerequisites). - Use the latest compatible version of the Java agent. - Use the latest compatible version of your JVM. diff --git a/content/en/docs/languages/java/resources.md b/content/en/docs/languages/java/resources.md deleted file mode 100644 index bf477a8683f6..000000000000 --- a/content/en/docs/languages/java/resources.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Resources -weight: 70 -cSpell:ignore: getenv myhost SIGINT uuidgen WORKDIR ---- - -{{% docs/languages/resources-intro %}} - -If you use the Java agent for -[zero-code instrumentation](/docs/zero-code/java/agent/) you can setup resource -detection through -[agent configuration](/docs/zero-code/java/agent/configuration). - -For manual instrumentation, you will find some introductions on how to set up -resource detection below. - -## Detecting resources from common environments - -You can use `ResourceProvider`s for filling in attributes related to common -environments, like [Container](/docs/specs/semconv/resource/container/), -[Host](/docs/specs/semconv/resource/host/) or -[Operating System](/docs/specs/semconv/resource/os/). These can be used with or -without -[autoconfiguration](/docs/languages/java/instrumentation/#automatic-configuration). - -To use those providers, add the following dependency: - -{{< tabpane text=true >}} {{% tab Gradle %}} - -```kotlin -dependencies { - implementation("io.opentelemetry.instrumentation:opentelemetry-resources:{{% param vers.otel %}}-alpha"); -} -``` - -{{% /tab %}} {{% tab Maven %}} - -```xml - - - - io.opentelemetry.instrumentation - opentelemetry-resources - - - -``` - -{{< /tab >}} {{< /tabpane>}} - -Next you can use them like the following in your code: - -```java -import io.opentelemetry.instrumentation.resources.ContainerResource; -import io.opentelemetry.instrumentation.resources.HostResource; -import io.opentelemetry.instrumentation.resources.OsResource; -import io.opentelemetry.instrumentation.resources.ProcessResource; -import io.opentelemetry.instrumentation.resources.ProcessRuntimeResource; - -... - Resource resource = Resource.getDefault() - .merge(ContainerResource.get()) - .merge(HostResource.get()) - .merge(OsResource.get()) - .merge(ProcessResource.get()) - .merge(ProcessRuntimeResource.get()) - .merge(Resource.create(Attributes.builder() - .put(ResourceAttributes.SERVICE_NAME, "dice-service") - ... - .build())); -... -``` - -## Adding resources in code - -Custom resources can be configured in your code like the following: - -```java -Resource resource = Resource.getDefault() - .merge(Resource.create(Attributes.builder() - .put(ResourceAttributes.SERVICE_NAME, "dice-service") - .put(ResourceAttributes.SERVICE_VERSION, "0.1.0") - .put(ResourceAttributes.SERVICE_INSTANCE_ID, "dice-service-1") - .put(ResourceAttributes.HOST_NAME, System.getenv("HOSTNAME")) - .put(ResourceAttributes.PROCESS_PID, ProcessHandle.current().pid()) - .build())); - -SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() - .setResource(resource) - ... - .build(); - -SdkMeterProvider sdkMeterProvider = SdkMeterProvider.builder() - .setResource(resource) - ... - .build(); - -SdkLoggerProvider sdkLoggerProvider = SdkLoggerProvider.builder() - .setResource(resource) - ... - .build(); -``` - -## Next steps - -Besides the -[Standard OpenTelemetry Resource Providers](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/resources/library) -shown in the samples above, there are more resource providers that you can add -to your configuration. These include: - -- [AWS Resource Provider](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources) -- [GCP Resource Provider](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/gcp-resources) -- [OpenTelemetry Contributed Resource Providers](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/resource-providers) -- [Spring-Boot Resource Provider](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/spring/spring-boot-resources) diff --git a/content/en/docs/languages/java/sampling.md b/content/en/docs/languages/java/sampling.md deleted file mode 100644 index 1580e838d110..000000000000 --- a/content/en/docs/languages/java/sampling.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Sampling -weight: 80 ---- - -[Sampling](/docs/concepts/sampling/) is a process that restricts the amount of -spans that are generated by a system. Which sampler to use depends on your -needs. In general, decide which sampler to use at the start of a trace and allow -the sampling decision to propagate to other services. - -## Default behavior - -By default, all spans are sampled, resulting in 100% of traces being sampled. If -your observability backend has constraints or budgetary restrictions on the -amount of data ingested, you can introduce a sampler and adjust the sample rates -accordingly. If you do not need to manage data volume, you don't need to set a -sampler and can use the default. - -## Environment variables - -You can configure the sampler with environment variables or system properties. -Reference the [configuration](/docs/languages/java/configuration/) documentation -for the available options. - -For example, to configure the SDK to sample spans such that only 10% of traces -get created: - -```shell -export OTEL_TRACES_SAMPLER="traceidratio" -export OTEL_TRACES_SAMPLER_ARG="0.1" -``` - -## Samplers - -### ParentBasedSampler - -When sampling, the ParentBasedSampler is most often used for -[head sampling](/docs/concepts/sampling/#head-sampling). It uses the sampling -decision of the Span’s parent, or the fact that there is no parent, to know -which secondary sampler to use. - -If the parent span is sampled, the child span will also be sampled. Conversely, -if the parent span is not sampled, the child span will not be sampled either. -This ensures consistency in sampling decisions within a trace. - -### TraceIDRatioBasedSampler - -The TraceIdRatioBasedSampler deterministically samples a percentage of traces -that you pass in as a parameter. - -This sampler is useful when you want to control the overall sampling rate across -all traces, regardless of their parent spans. It provides a consistent rate of -sampling for all traces initiated. - -## Configuration in code - -{{% alert title="Note" %}} The use of the -[Java agent](/docs/zero-code/java/agent/), -[Spring Boot Starter](/docs/zero-code/java/spring-boot-starter/), or -[SDK autoconfigure](/docs/languages/java/instrumentation/#autoconfiguration) is -generally recommended for controlling sampling, rather than setting it directly -in the code. Most users should find the default settings sufficient for their -needs. {{% /alert %}} - -A sampler can be set on the tracer provider using the `setSampler` method, as -follows: - -```java -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.samplers.Sampler; - -public class Example { - public static void main(String[] args) { - // Configure the tracer provider with the desired sampler - SdkTracerProvider tracerProvider = SdkTracerProvider.builder() - .setSampler(Sampler.alwaysOn()) // Set to always sample traces - // or - .setSampler(Sampler.alwaysOff()) // Set to never sample traces - // or - .setSampler(Sampler.traceIdRatioBased(0.5)) // Set to sample a fraction of traces - .build(); - } -} -``` - -The `alwaysOn` value means that every span is sampled, while `alwaysOff` means -that no span is sampled. When you’re getting started, or in a development -environment, use `alwaysOn`. - -Other samplers include: - -- `traceIdRatioBased`, which samples a fraction of spans, based on the fraction - given to the sampler. If you set `0.5`, half of all the spans are sampled. - Currently, only the ratio of traces that are sampled can be relied on, not how - the sampled traces are determined. Only use this sampler for root spans that - use `parentBased`. -- `parentBased`, which uses the parent span to make sampling decisions, if - present. By default, the tracer provider uses a parentBased sampler with the - `alwaysOn` sampler. diff --git a/content/en/docs/languages/java/sdk.md b/content/en/docs/languages/java/sdk.md new file mode 100644 index 000000000000..8e6ff433d8c3 --- /dev/null +++ b/content/en/docs/languages/java/sdk.md @@ -0,0 +1,1382 @@ +--- +title: Manage Telemetry with SDK +linkTitle: Manage Telemetry with SDK +weight: 11 +aliases: [sdk-concepts] +cSpell:ignore: autoconfigured FQCNs Interceptable Logback okhttp +--- + + + + +The SDK is the built-in reference implementation of the +[API](../instrumentation/), processing and exporting telemetry produced by +instrumentation API calls. This page is a conceptual overview of the SDK, +including descriptions, links to relevant Javadocs, artifact coordinates, sample +programmatic configurations and more. See +**[Configure the SDK](../configuration/)** for details on SDK configuration, +including +[zero-code SDK autoconfigure](../configuration/#zero-code-sdk-autoconfigure). + +The SDK consists of the following top level components: + +- [SdkTracerProvider](#sdktracerprovider): The SDK implementation of + `TracerProvider`, including tools for sampling, processing, and exporting + spans. +- [SdkMeterProvider](#sdkmeterprovider): The SDK implementation of + `MeterProvider`, including tools for configuring metric streams and reading / + exporting metrics. +- [SdkLoggerProvider](#sdkloggerprovider): The SDK implementation of + `LoggerProvider`, including tools for processing and exporting logs. +- [TextMapPropagator](#textmappropagator): Propagates context across process + boundaries. + +These are combined into [OpenTelemetrySdk](#opentelemetrysdk), a carrier object +which makes it convenient to pass fully-configured +[SDK components](#sdk-components) to instrumentation. + +The SDK comes packaged with a variety of built-in components which are +sufficient for many use cases, and supports +[plugin interfaces](#sdk-plugin-extension-interfaces) for extensibility. + +## SDK plugin extension interfaces + +When built-in components are insufficient, the SDK can be extended by +implementing various plugin extension interfaces: + +- [Sampler](#sampler): Configures which spans are recorded and sampled. +- [SpanProcessor](#spanprocessor): Processes spans when they start and end. +- [SpanExporter](#spanexporter): Exports spans out of process. +- [MetricReader](#metricreader): Reads aggregated metrics. +- [MetricExporter](#metricexporter): Exports metrics out of process. +- [LogRecordProcessor](#logrecordprocessor): Processes log records when they are + emitted. +- [LogRecordExporter](#logrecordexporter): Exports log records out of process. +- [TextMapPropagator](#textmappropagator): Propagates context across process + boundaries. + +## SDK components + +The following sections describe the core user-facing components of the SDK. Each +component section includes: + +- A brief description, including a link to the Javadoc type reference. +- If the component is a + [plugin extension interface](#sdk-plugin-extension-interfaces), a table of + available built-in and `opentelemetry-java-contrib` implementations. +- A simple demonstration of + [programmatic-configuration](../configuration/#programmatic-configuration). +- If the component is a + [plugin extension interface](#sdk-plugin-extension-interfaces), a simple + demonstration of a custom implementation. + +### OpenTelemetrySdk + +[OpenTelemetrySdk](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk/latest/io/opentelemetry/sdk/OpenTelemetrySdk.html) +is the SDK implementation of +[OpenTelemetry](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/OpenTelemetry.html). +It is a holder for top-level SDK components which makes it convenient to pass +fully-configured SDK components to instrumentation. + +`OpenTelemetrySdk` is configured by the application owner, and consists of: + +- [SdkTracerProvider](#sdktracerprovider): The SDK implementation of + `TracerProvider`. +- [SdkMeterProvider](#sdkmeterprovider): The SDK implementation of + `MeterProvider`. +- [SdkLoggerProvider](#sdkloggerprovider): The SDK implementation of + `LoggerProvider`. +- [ContextPropagators](#textmappropagator): Propagates context across process + boundaries. + +The following code snippet demonstrates `OpenTelemetrySdk` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.resources.Resource; + +public class OpenTelemetrySdkConfig { + public static OpenTelemetrySdk create() { + Resource resource = ResourceConfig.create(); + return OpenTelemetrySdk.builder() + .setTracerProvider(SdkTracerProviderConfig.create(resource)) + .setMeterProvider(SdkMeterProviderConfig.create(resource)) + .setLoggerProvider(SdkLoggerProviderConfig.create(resource)) + .setPropagators(ContextPropagatorsConfig.create()) + .build(); + } +} +``` + + +### Resource + +[Resource](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-common/latest/io/opentelemetry/sdk/resources/Resource.html) +is a set of attributes defining the telemetry source. An application should +associate the same resource with [SdkTracerProvider](#sdktracerprovider), +[SdkMeterProvider](#sdkmeterprovider), [SdkLoggerProvider](#sdkloggerprovider). + +{{% alert color="info" %}} +[ResourceProviders](../configuration/#resourceprovider) contribute contextual +information to the +[autoconfigured](../configuration/#zero-code-sdk-autoconfigure) resource based +on the environment. See documentation for list of available `ResourceProvider`s. +{{% /alert %}} + +The following code snippet demonstrates `Resource` programmatic configuration: + + + +```java +package otel; + +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.semconv.ServiceAttributes; + +public class ResourceConfig { + public static Resource create() { + return Resource.getDefault().toBuilder() + .put(ServiceAttributes.SERVICE_NAME, "my-service") + .build(); + } +} +``` + + +### SdkTracerProvider + +[SdkTracerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/SdkTracerProvider.html) +is the SDK implementation of +[TracerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/TracerProvider.html), +and is responsible for handling trace telemetry produced by the API. + +`SdkTracerProvider` is configured by the application owner, and consists of: + +- [Resource](#resource): The resource spans are associated with. +- [Sampler](#sampler): Configures which spans are recorded and sampled. +- [SpanProcessors](#spanprocessor): Processes spans when they start and end. +- [SpanExporters](#spanexporter): Exports spans out of process (in conjunction + with associated with `SpanProcessor`s). +- [SpanLimits](#spanlimits): Controls the limits of data associated with spans. + +The following code snippet demonstrates `SdkTracerProvider` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.trace.SdkTracerProvider; + +public class SdkTracerProviderConfig { + public static SdkTracerProvider create(Resource resource) { + return SdkTracerProvider.builder() + .setResource(resource) + .addSpanProcessor( + SpanProcessorConfig.batchSpanProcessor( + SpanExporterConfig.otlpHttpSpanExporter("http://localhost:4318/v1/spans"))) + .setSampler(SamplerConfig.parentBasedSampler(SamplerConfig.traceIdRatioBased(.25))) + .setSpanLimits(SpanLimitsConfig::spanLimits) + .build(); + } +} +``` + + +#### Sampler + +A +[Sampler](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/samplers/Sampler.html) +is a [plugin extension interface](#sdk-plugin-extension-interfaces) responsible +for determining which spans are recorded and sampled. + +{{% alert color="info" %}} By default `SdkTracerProvider` is configured with the +`ParentBased(root=AlwaysOn)` sampler. This results in 100% of spans being +sampled if unless a calling application performs sampling. If this is too noisy +/ expensive, change the sampler. {{% /alert %}} + +Samplers built-in to the SDK and maintained by the community in +`opentelemetry-java-contrib`: + +| Class | Artifact | Description | +| ------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| `ParentBased` | `io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}` | Samples spans based on sampling status of the span's parent. | +| `AlwaysOn` | `io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}` | Samples all spans. | +| `AlwaysOff` | `io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}` | Drops all spans. | +| `TraceIdRatioBased` | `io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}` | Samples spans based on a configurable ratio. | +| `JaegerRemoteSampler` | `io.opentelemetry:opentelemetry-sdk-extension-jaeger-remote-sampler:{{% param vers.otel %}}` | Samples spans based on configuration from a remote server. | +| `LinksBasedSampler` | `io.opentelemetry.contrib:opentelemetry-samplers:{{% param vers.contrib %}}-alpha` | Samples spans based on sampling status of the span's links. | +| `RuleBasedRoutingSampler` | `io.opentelemetry.contrib:opentelemetry-samplers:{{% param vers.contrib %}}-alpha` | Samples spans based on configurable rules. | +| `ConsistentSamplers` | `io.opentelemetry.contrib:opentelemetry-consistent-sampling:{{% param vers.contrib %}}-alpha` | Various consistent sampler implementations as defined by [probability sampling](/docs/specs/otel/trace/tracestate-probability-sampling/). | + +The following code snippet demonstrates `Sampler` programmatic configuration: + + + +```java +package otel; + +import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.time.Duration; + +public class SamplerConfig { + public static Sampler parentBasedSampler(Sampler root) { + return Sampler.parentBasedBuilder(root) + .setLocalParentNotSampled(Sampler.alwaysOff()) + .setLocalParentSampled(Sampler.alwaysOn()) + .setRemoteParentNotSampled(Sampler.alwaysOff()) + .setRemoteParentSampled(Sampler.alwaysOn()) + .build(); + } + + public static Sampler alwaysOn() { + return Sampler.alwaysOn(); + } + + public static Sampler alwaysOff() { + return Sampler.alwaysOff(); + } + + public static Sampler traceIdRatioBased(double ratio) { + return Sampler.traceIdRatioBased(ratio); + } + + public static Sampler jaegerRemoteSampler() { + return JaegerRemoteSampler.builder() + .setInitialSampler(Sampler.alwaysOn()) + .setEndpoint("http://endpoint") + .setPollingInterval(Duration.ofSeconds(60)) + .setServiceName("my-service-name") + .build(); + } +} +``` + + +Implement the `Sampler` interface to provide your own custom sampling logic. For +example: + + + +```java +package otel; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import io.opentelemetry.sdk.trace.samplers.SamplingResult; +import java.util.List; + +public class CustomSampler implements Sampler { + @Override + public SamplingResult shouldSample( + Context parentContext, + String traceId, + String name, + SpanKind spanKind, + Attributes attributes, + List parentLinks) { + // Callback invoked when span is started, before any SpanProcessor is called. + // If the SamplingDecision is: + // - DROP: the span is dropped. A valid span context is created and SpanProcessor#onStart is + // still called, but no data is recorded and SpanProcessor#onEnd is not called. + // - RECORD_ONLY: the span is recorded but not sampled. Data is recorded to the span, + // SpanProcessor#onStart and SpanProcessor#onEnd are called, but the span's sampled status + // indicates it should not be exported out of process. + // - RECORD_AND_SAMPLE: the span is recorded and sampled. Data is recorded to the span, + // SpanProcessor#onStart and SpanProcessor#onEnd are called, and the span's sampled status + // indicates it should be exported out of process. + return SpanKind.SERVER == spanKind ? SamplingResult.recordAndSample() : SamplingResult.drop(); + } + + @Override + public String getDescription() { + // Return a description of the sampler. + return this.getClass().getSimpleName(); + } +} +``` + + +#### SpanProcessor + +A +[SpanProcessor](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/SpanProcessor.html) +is a [plugin extension interface](#sdk-plugin-extension-interfaces) with +callbacks invoked when a span is started and ended. They are often paired with +[SpanExporters](#spanexporter) to export spans out of process, but have other +applications such as data enrichment. + +Span processors built-in to the SDK and maintained by the community in +`opentelemetry-java-contrib`: + +| Class | Artifact | Description | +| ------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| `BatchSpanProcessor` | `io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}` | Batches sampled spans and exports them via a configurable `SpanExporter`. | +| `SimpleSpanProcessor` | `io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}` | Exports each sampled span via a configurable `SpanExporter`. | +| `BaggageSpanProcessor` | `io.opentelemetry.contrib:opentelemetry-baggage-processor:{{% param vers.contrib %}}-alpha` | Enriches spans with baggage. | +| `JfrSpanProcessor` | `io.opentelemetry.contrib:opentelemetry-jfr-events:{{% param vers.contrib %}}-alpha` | Creates JFR events from spans. | +| `StackTraceSpanProcessor` | `io.opentelemetry.contrib:opentelemetry-span-stacktrace:{{% param vers.contrib %}}-alpha` | Enriches select spans with stack trace data. | + +The following code snippet demonstrates `SpanProcessor` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.sdk.trace.SpanProcessor; +import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import java.time.Duration; + +public class SpanProcessorConfig { + public static SpanProcessor batchSpanProcessor(SpanExporter spanExporter) { + return BatchSpanProcessor.builder(spanExporter) + .setMaxQueueSize(2048) + .setExporterTimeout(Duration.ofSeconds(30)) + .setScheduleDelay(Duration.ofSeconds(5)) + .build(); + } + + public static SpanProcessor simpleSpanProcessor(SpanExporter spanExporter) { + return SimpleSpanProcessor.builder(spanExporter).build(); + } +} +``` + + +Implement the `SpanProcessor` interface to provide your own custom span +processing logic. For example: + + + +```java +package otel; + +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.trace.ReadWriteSpan; +import io.opentelemetry.sdk.trace.ReadableSpan; +import io.opentelemetry.sdk.trace.SpanProcessor; + +public class CustomSpanProcessor implements SpanProcessor { + + @Override + public void onStart(Context parentContext, ReadWriteSpan span) { + // Callback invoked when span is started. + // Enrich the record with a custom attribute. + span.setAttribute("my.custom.attribute", "hello world"); + } + + @Override + public boolean isStartRequired() { + // Indicate if onStart should be called. + return true; + } + + @Override + public void onEnd(ReadableSpan span) { + // Callback invoked when span is ended. + } + + @Override + public boolean isEndRequired() { + // Indicate if onEnd should be called. + return false; + } + + @Override + public CompletableResultCode shutdown() { + // Optionally shutdown the processor and cleanup any resources. + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode forceFlush() { + // Optionally process any records which have been queued up but not yet processed. + return CompletableResultCode.ofSuccess(); + } +} +``` + + +#### SpanExporter + +A +[SpanExporter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/export/SpanExporter.html) +is a [plugin extension interface](#sdk-plugin-extension-interfaces) responsible +for exporting spans out of process. Rather than directly registering with +`SdkTracerProvider`, they are paired with [SpanProcessors](#spanprocessor) +(typically `BatchSpanProcessor`). + +Span exporters built-in to the SDK and maintained by the community in +`opentelemetry-java-contrib`: + +| Class | Artifact | Description | +| ------------------------------ | ---------------------------------------------------------------------------------------- | -------------------------------------------------------- | +| `OtlpHttpSpanExporter` **[1]** | `io.opentelemetry:opentelemetry-exporter-otlp:{{% param vers.otel %}}` | Exports spans via OTLP `http/protobuf`. | +| `OtlpGrpcSpanExporter` **[1]** | `io.opentelemetry:opentelemetry-exporter-otlp:{{% param vers.otel %}}` | Exports spans via OTLP `grpc`. | +| `LoggingSpanExporter` | `io.opentelemetry:opentelemetry-exporter-logging:{{% param vers.otel %}}` | Logs spans to JUL in a debugging format. | +| `OtlpJsonLoggingSpanExporter` | `io.opentelemetry:opentelemetry-exporter-logging-otlp:{{% param vers.otel %}}` | Logs spans to JUL in the OTLP JSON encoding. | +| `ZipkinSpanExporter` | `io.opentelemetry:opentelemetry-exporter-zipkin:{{% param vers.otel %}}` | Export spans to Zipkin. | +| `InterceptableSpanExporter` | `io.opentelemetry.contrib:opentelemetry-processors:{{% param vers.contrib %}}-alpha` | Passes spans to a flexible interceptor before exporting. | +| `KafkaSpanExporter` | `io.opentelemetry.contrib:opentelemetry-kafka-exporter:{{% param vers.contrib %}}-alpha` | Exports spans by writing to a Kafka topic. | + +**[1]**: See [OTLP exporter sender](#otlp-exporter-senders) for implementation +details. + +The following code snippet demonstrates `SpanExporter` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.exporter.logging.LoggingSpanExporter; +import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingSpanExporter; +import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; +import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import java.time.Duration; + +public class SpanExporterConfig { + public static SpanExporter otlpHttpSpanExporter(String endpoint) { + return OtlpHttpSpanExporter.builder() + .setEndpoint(endpoint) + .addHeader("api-key", "value") + .setTimeout(Duration.ofSeconds(10)) + .build(); + } + + public static SpanExporter otlpGrpcSpanExporter(String endpoint) { + return OtlpGrpcSpanExporter.builder() + .setEndpoint(endpoint) + .addHeader("api-key", "value") + .setTimeout(Duration.ofSeconds(10)) + .build(); + } + + public static SpanExporter logginSpanExporter() { + return LoggingSpanExporter.create(); + } + + public static SpanExporter otlpJsonLoggingSpanExporter() { + return OtlpJsonLoggingSpanExporter.create(); + } +} +``` + + +Implement the `SpanExporter` interface to provide your own custom span export +logic. For example: + + + +```java +package otel; + +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class CustomSpanExporter implements SpanExporter { + + private static final Logger logger = Logger.getLogger(CustomSpanExporter.class.getName()); + + @Override + public CompletableResultCode export(Collection spans) { + // Export the records. Typically, records are sent out of process via some network protocol, but + // we simply log for illustrative purposes. + logger.log(Level.INFO, "Exporting spans"); + spans.forEach(span -> logger.log(Level.INFO, "Span: " + span)); + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode flush() { + // Export any records which have been queued up but not yet exported. + logger.log(Level.INFO, "flushing"); + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode shutdown() { + // Shutdown the exporter and cleanup any resources. + logger.log(Level.INFO, "shutting down"); + return CompletableResultCode.ofSuccess(); + } +} +``` + + +#### SpanLimits + +[SpanLimits](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/SpanLimits.html) +defines constraints for the data captured by spans, including max attribute +length, max number of attributes, and more. + +The following code snippet demonstrates `SpanLimits` programmatic configuration: + + + +```java +package otel; + +import io.opentelemetry.sdk.trace.SpanLimits; + +public class SpanLimitsConfig { + public static SpanLimits spanLimits() { + return SpanLimits.builder() + .setMaxNumberOfAttributes(128) + .setMaxAttributeValueLength(1024) + .setMaxNumberOfLinks(128) + .setMaxNumberOfAttributesPerLink(128) + .setMaxNumberOfEvents(128) + .setMaxNumberOfAttributesPerEvent(128) + .build(); + } +} +``` + + +### SdkMeterProvider + +[SdkMeterProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-metrics/latest/io/opentelemetry/sdk/metrics/SdkMeterProvider.html) +is the SDK implementation of +[MeterProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/MeterProvider.html), +and is responsible for handling metric telemetry produced by the API. + +`SdkMeterProvider` is configured by the application owner, and consists of: + +- [Resource](#resource): The resource metrics are associated with. +- [MetricReader](#metricreader): Reads the aggregated state of metrics. +- [MetricExporter](#metricexporter): Exports metrics out of process (in + conjunction with associated `MetricReader`). +- [Views](#views): Configures metric streams, including dropping unused metrics. + +The following code snippet demonstrates `SdkMeterProvider` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; +import io.opentelemetry.sdk.resources.Resource; +import java.util.List; +import java.util.Set; + +public class SdkMeterProviderConfig { + public static SdkMeterProvider create(Resource resource) { + SdkMeterProviderBuilder builder = + SdkMeterProvider.builder() + .setResource(resource) + .registerMetricReader( + MetricReaderConfig.periodicMetricReader( + MetricExporterConfig.otlpHttpMetricExporter( + "http://localhost:4318/v1/metrics"))); + ViewConfig.dropMetricView(builder, "some.custom.metric"); + ViewConfig.histogramBucketBoundariesView( + builder, "http.server.request.duration", List.of(1.0, 5.0, 10.0)); + ViewConfig.attributeFilterView( + builder, "http.client.request.duration", Set.of("http.request.method")); + return builder.build(); + } +} +``` + + +#### MetricReader + +A +[MetricReader](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-metrics/latest/io/opentelemetry/sdk/metrics/export/MetricReader.html) +is a [plugin extension interface](#sdk-plugin-extension-interfaces) which is +responsible for reading aggregated metrics. They are often paired with +[MetricExporters](#metricexporter) to export metrics out of process, but may +also be used to serve the metrics to external scrapers in pull-based protocols. + +Metric readers built-in to the SDK and maintained by the community in +`opentelemetry-java-contrib`: + +| Class | Artifact | Description | +| ---------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| `PeriodicMetricReader` | `io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}` | Reads metrics on a periodic basis and exports them via a configurable `MetricExporter`. | +| `PrometheusHttpServer` | `io.opentelemetry:opentelemetry-exporter-prometheus:{{% param vers.otel %}}-alpha` | Serves metrics on an HTTP server in various prometheus formats. | + +The following code snippet demonstrates `MetricReader` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.exporter.prometheus.PrometheusHttpServer; +import io.opentelemetry.sdk.metrics.export.MetricExporter; +import io.opentelemetry.sdk.metrics.export.MetricReader; +import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; +import java.time.Duration; + +public class MetricReaderConfig { + public static MetricReader periodicMetricReader(MetricExporter metricExporter) { + return PeriodicMetricReader.builder(metricExporter).setInterval(Duration.ofSeconds(60)).build(); + } + + public static MetricReader prometheusMetricReader() { + return PrometheusHttpServer.builder().setHost("localhost").setPort(9464).build(); + } +} +``` + + +Implement the `MetricReader` interface to provide your own custom metric reader +logic. For example: + + + +```java +package otel; + +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.common.export.MemoryMode; +import io.opentelemetry.sdk.metrics.Aggregation; +import io.opentelemetry.sdk.metrics.InstrumentType; +import io.opentelemetry.sdk.metrics.data.AggregationTemporality; +import io.opentelemetry.sdk.metrics.export.AggregationTemporalitySelector; +import io.opentelemetry.sdk.metrics.export.CollectionRegistration; +import io.opentelemetry.sdk.metrics.export.MetricReader; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class CustomMetricReader implements MetricReader { + + private static final Logger logger = Logger.getLogger(CustomMetricExporter.class.getName()); + + private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); + private final AtomicReference collectionRef = + new AtomicReference<>(CollectionRegistration.noop()); + + @Override + public void register(CollectionRegistration collectionRegistration) { + // Callback invoked when SdkMeterProvider is initialized, providing a handle to collect metrics. + collectionRef.set(collectionRegistration); + executorService.scheduleWithFixedDelay(this::collectMetrics, 0, 60, TimeUnit.SECONDS); + } + + private void collectMetrics() { + // Collect metrics. Typically, records are sent out of process via some network protocol, but we + // simply log for illustrative purposes. + logger.log(Level.INFO, "Collecting metrics"); + collectionRef + .get() + .collectAllMetrics() + .forEach(metric -> logger.log(Level.INFO, "Metric: " + metric)); + } + + @Override + public CompletableResultCode forceFlush() { + // Export any records which have been queued up but not yet exported. + logger.log(Level.INFO, "flushing"); + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode shutdown() { + // Shutdown the exporter and cleanup any resources. + logger.log(Level.INFO, "shutting down"); + return CompletableResultCode.ofSuccess(); + } + + @Override + public AggregationTemporality getAggregationTemporality(InstrumentType instrumentType) { + // Specify the required aggregation temporality as a function of instrument type + return AggregationTemporalitySelector.deltaPreferred() + .getAggregationTemporality(instrumentType); + } + + @Override + public MemoryMode getMemoryMode() { + // Optionally specify the memory mode, indicating whether metric records can be reused or must + // be immutable + return MemoryMode.REUSABLE_DATA; + } + + @Override + public Aggregation getDefaultAggregation(InstrumentType instrumentType) { + // Optionally specify the default aggregation as a function of instrument kind + return Aggregation.defaultAggregation(); + } +} +``` + + +#### MetricExporter + +A +[MetricExporter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-metrics/latest/io/opentelemetry/sdk/metrics/export/MetricExporter.html) +is a [plugin extension interface](#sdk-plugin-extension-interfaces) responsible +for exporting metrics out of process. Rather than directly registering with +`SdkMeterProvider`, they are paired with [PeriodicMetricReader](#metricreader). + +Metric exporters built-in to the SDK and maintained by the community in +`opentelemetry-java-contrib`: + +| Class | Artifact | Description | +| -------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------- | +| `OtlpHttpMetricExporter` **[1]** | `io.opentelemetry:opentelemetry-exporter-otlp:{{% param vers.otel %}}` | Exports metrics via OTLP `http/protobuf`. | +| `OtlpGrpcMetricExporter` **[1]** | `io.opentelemetry:opentelemetry-exporter-otlp:{{% param vers.otel %}}` | Exports metrics via OTLP `grpc`. | +| `LoggingMetricExporter` | `io.opentelemetry:opentelemetry-exporter-logging:{{% param vers.otel %}}` | Logs metrics to JUL in a debugging format. | +| `OtlpJsonLoggingMetricExporter` | `io.opentelemetry:opentelemetry-exporter-logging-otlp:{{% param vers.otel %}}` | Logs metrics to JUL in the OTLP JSON encoding. | +| `InterceptableMetricExporter` | `io.opentelemetry.contrib:opentelemetry-processors:{{% param vers.contrib %}}-alpha` | Passes metrics to a flexible interceptor before exporting. | + +**[1]**: See [OTLP exporter sender](#otlp-exporter-senders) for implementation +details. + +The following code snippet demonstrates `MetricExporter` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.exporter.logging.LoggingMetricExporter; +import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingMetricExporter; +import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter; +import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter; +import io.opentelemetry.sdk.metrics.export.MetricExporter; +import java.time.Duration; + +public class MetricExporterConfig { + public static MetricExporter otlpHttpMetricExporter(String endpoint) { + return OtlpHttpMetricExporter.builder() + .setEndpoint(endpoint) + .addHeader("api-key", "value") + .setTimeout(Duration.ofSeconds(10)) + .build(); + } + + public static MetricExporter otlpGrpcMetricExporter(String endpoint) { + return OtlpGrpcMetricExporter.builder() + .setEndpoint(endpoint) + .addHeader("api-key", "value") + .setTimeout(Duration.ofSeconds(10)) + .build(); + } + + public static MetricExporter logginMetricExporter() { + return LoggingMetricExporter.create(); + } + + public static MetricExporter otlpJsonLoggingMetricExporter() { + return OtlpJsonLoggingMetricExporter.create(); + } +} +``` + + +Implement the `MetricExporter` interface to provide your own custom metric +export logic. For example: + + + +```java +package otel; + +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.common.export.MemoryMode; +import io.opentelemetry.sdk.metrics.Aggregation; +import io.opentelemetry.sdk.metrics.InstrumentType; +import io.opentelemetry.sdk.metrics.data.AggregationTemporality; +import io.opentelemetry.sdk.metrics.data.MetricData; +import io.opentelemetry.sdk.metrics.export.AggregationTemporalitySelector; +import io.opentelemetry.sdk.metrics.export.MetricExporter; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class CustomMetricExporter implements MetricExporter { + + private static final Logger logger = Logger.getLogger(CustomMetricExporter.class.getName()); + + @Override + public CompletableResultCode export(Collection metrics) { + // Export the records. Typically, records are sent out of process via some network protocol, but + // we simply log for illustrative purposes. + logger.log(Level.INFO, "Exporting metrics"); + metrics.forEach(metric -> logger.log(Level.INFO, "Metric: " + metric)); + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode flush() { + // Export any records which have been queued up but not yet exported. + logger.log(Level.INFO, "flushing"); + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode shutdown() { + // Shutdown the exporter and cleanup any resources. + logger.log(Level.INFO, "shutting down"); + return CompletableResultCode.ofSuccess(); + } + + @Override + public AggregationTemporality getAggregationTemporality(InstrumentType instrumentType) { + // Specify the required aggregation temporality as a function of instrument type + return AggregationTemporalitySelector.deltaPreferred() + .getAggregationTemporality(instrumentType); + } + + @Override + public MemoryMode getMemoryMode() { + // Optionally specify the memory mode, indicating whether metric records can be reused or must + // be immutable + return MemoryMode.REUSABLE_DATA; + } + + @Override + public Aggregation getDefaultAggregation(InstrumentType instrumentType) { + // Optionally specify the default aggregation as a function of instrument kind + return Aggregation.defaultAggregation(); + } +} +``` + + +#### Views + +[Views](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-metrics/latest/io/opentelemetry/sdk/metrics/View.html) +allow metric streams to be customized, including changing metric names, metric +descriptions, metric aggregations (i.e. histogram bucket boundaries), the set of +attribute keys to retain, etc. + +{{% alert %}} Views have somewhat unintuitive behavior when multiple match a +particular instrument. If one matching view changes the metric name and another +changes the metric aggregation, you might expect the name and aggregation are +changed, but this is not the case. Instead, two metric streams are produced: one +with the configured metric name and the default aggregation, and another with +the original metric name and the configured aggregation. In other words, +matching views _do not merge_. For best results, configure views with narrow +selection criteria (i.e. select a single specific instrument). {{% /alert %}} + +The following code snippet demonstrates `View` programmatic configuration: + + + +```java +package otel; + +import io.opentelemetry.sdk.metrics.Aggregation; +import io.opentelemetry.sdk.metrics.InstrumentSelector; +import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; +import io.opentelemetry.sdk.metrics.View; +import java.util.List; +import java.util.Set; + +public class ViewConfig { + public static SdkMeterProviderBuilder dropMetricView( + SdkMeterProviderBuilder builder, String metricName) { + return builder.registerView( + InstrumentSelector.builder().setName(metricName).build(), + View.builder().setAggregation(Aggregation.drop()).build()); + } + + public static SdkMeterProviderBuilder histogramBucketBoundariesView( + SdkMeterProviderBuilder builder, String metricName, List bucketBoundaries) { + return builder.registerView( + InstrumentSelector.builder().setName(metricName).build(), + View.builder() + .setAggregation(Aggregation.explicitBucketHistogram(bucketBoundaries)) + .build()); + } + + public static SdkMeterProviderBuilder attributeFilterView( + SdkMeterProviderBuilder builder, String metricName, Set keysToRetain) { + return builder.registerView( + InstrumentSelector.builder().setName(metricName).build(), + View.builder().setAttributeFilter(keysToRetain).build()); + } +} +``` + + +### SdkLoggerProvider + +[SdkLoggerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-logs/latest/io/opentelemetry/sdk/logs/SdkLoggerProvider.html) +is the SDK implementation of +[LoggerProvider](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/logs/LoggerProvider.html), +and is responsible for handling log telemetry produced by the log bridge API. + +`SdkLoggerProvider` is configured by the application owner, and consists of: + +- [Resource](#resource): The resource logs are associated with. +- [LogRecordProcessor](#logrecordprocessor): Processes logs when they are + emitted. +- [LogRecordExporter](#logrecordexporter): Exports logs out of process (in + conjunction with associated `LogRecordProcessor`). +- [LogLimits](#loglimits): Controls the limits of data associated with logs. + +The following code snippet demonstrates `SdkLoggerProvider` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.sdk.logs.SdkLoggerProvider; +import io.opentelemetry.sdk.resources.Resource; + +public class SdkLoggerProviderConfig { + public static SdkLoggerProvider create(Resource resource) { + return SdkLoggerProvider.builder() + .setResource(resource) + .addLogRecordProcessor( + LogRecordProcessorConfig.batchLogRecordProcessor( + LogRecordExporterConfig.otlpHttpLogRecordExporter("http://localhost:4318/v1/logs"))) + .setLogLimits(LogLimitsConfig::logLimits) + .build(); + } +} +``` + + +#### LogRecordProcessor + +A +[LogRecordProcessor](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-logs/latest/io/opentelemetry/sdk/logs/LogRecordProcessor.html) +is a [plugin extension interface](#sdk-plugin-extension-interfaces) with a +callback invoked when a log is emitted. They are often paired with +[LogRecordExporters](#logrecordexporter) to export logs out of process, but have +other applications such as data enrichment. + +Log record processors built-in to the SDK and maintained by the community in +`opentelemetry-java-contrib`: + +| Class | Artifact | Description | +| -------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------- | +| `BatchLogRecordProcessor` | `io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}` | Batches log records and exports them via a configurable `LogRecordExporter`. | +| `SimpleLogRecordProcessor` | `io.opentelemetry:opentelemetry-sdk:{{% param vers.otel %}}` | Exports each log record a via a configurable `LogRecordExporter`. | + +The following code snippet demonstrates `LogRecordProcessor` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.sdk.logs.LogRecordProcessor; +import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor; +import io.opentelemetry.sdk.logs.export.LogRecordExporter; +import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor; +import java.time.Duration; + +public class LogRecordProcessorConfig { + public static LogRecordProcessor batchLogRecordProcessor(LogRecordExporter logRecordExporter) { + return BatchLogRecordProcessor.builder(logRecordExporter) + .setMaxQueueSize(2048) + .setExporterTimeout(Duration.ofSeconds(30)) + .setScheduleDelay(Duration.ofSeconds(1)) + .build(); + } + + public static LogRecordProcessor simpleLogRecordProcessor(LogRecordExporter logRecordExporter) { + return SimpleLogRecordProcessor.create(logRecordExporter); + } +} +``` + + +Implement the `LogRecordProcessor` interface to provide your own custom log +processing logic. For example: + + + +```java +package otel; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.logs.LogRecordProcessor; +import io.opentelemetry.sdk.logs.ReadWriteLogRecord; + +public class CustomLogRecordProcessor implements LogRecordProcessor { + + @Override + public void onEmit(Context context, ReadWriteLogRecord logRecord) { + // Callback invoked when log record is emitted. + // Enrich the record with a custom attribute. + logRecord.setAttribute(AttributeKey.stringKey("my.custom.attribute"), "hello world"); + } + + @Override + public CompletableResultCode shutdown() { + // Optionally shutdown the processor and cleanup any resources. + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode forceFlush() { + // Optionally process any records which have been queued up but not yet processed. + return CompletableResultCode.ofSuccess(); + } +} +``` + + +#### LogRecordExporter + +A +[LogRecordExporter](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-logs/latest/io/opentelemetry/sdk/logs/export/LogRecordExporter.html) +is a [plugin extension interface](#sdk-plugin-extension-interfaces) responsible +for exporting log records out of process. Rather than directly registering with +`SdkLoggerProvider`, they are paired with +[LogRecordProcessors](#logrecordprocessor) (typically +`BatchLogRecordProcessor`). + +Span exporters built-in to the SDK and maintained by the community in +`opentelemetry-java-contrib`: + +| Class | Artifact | Description | +| ------------------------------------------ | ------------------------------------------------------------------------------------ | -------------------------------------------------------------- | +| `OtlpHttpLogRecordExporter` **[1]** | `io.opentelemetry:opentelemetry-exporter-otlp:{{% param vers.otel %}}` | Exports log records via OTLP `http/protobuf`. | +| `OtlpGrpcLogRecordExporter` **[1]** | `io.opentelemetry:opentelemetry-exporter-otlp:{{% param vers.otel %}}` | Exports log records via OTLP `grpc`. | +| `SystemOutLogRecordExporter` | `io.opentelemetry:opentelemetry-exporter-logging:{{% param vers.otel %}}` | Logs log records to system out in a debugging format. | +| `OtlpJsonLoggingLogRecordExporter` **[2]** | `io.opentelemetry:opentelemetry-exporter-logging-otlp:{{% param vers.otel %}}` | Logs log records to JUL in the OTLP JSON encoding. | +| `InterceptableLogRecordExporter` | `io.opentelemetry.contrib:opentelemetry-processors:{{% param vers.contrib %}}-alpha` | Passes log records to a flexible interceptor before exporting. | + +**[1]**: See [OTLP exporter sender](#otlp-exporter-senders) for implementation +details. + +**[2]**: `OtlpJsonLoggingLogRecordExporter` logs to JUL, and may cause infinite +loops (i.e. JUL -> SLF4J -> Logback -> OpenTelemetry Appender -> OpenTelemetry +Log SDK -> JUL) if not carefully configured. + +The following code snippet demonstrates `LogRecordProcessor` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.exporter.logging.SystemOutLogRecordExporter; +import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingLogRecordExporter; +import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter; +import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter; +import io.opentelemetry.sdk.logs.export.LogRecordExporter; +import java.time.Duration; + +public class LogRecordExporterConfig { + public static LogRecordExporter otlpHttpLogRecordExporter(String endpoint) { + return OtlpHttpLogRecordExporter.builder() + .setEndpoint(endpoint) + .addHeader("api-key", "value") + .setTimeout(Duration.ofSeconds(10)) + .build(); + } + + public static LogRecordExporter otlpGrpcLogRecordExporter(String endpoint) { + return OtlpGrpcLogRecordExporter.builder() + .setEndpoint(endpoint) + .addHeader("api-key", "value") + .setTimeout(Duration.ofSeconds(10)) + .build(); + } + + public static LogRecordExporter systemOutLogRecordExporter() { + return SystemOutLogRecordExporter.create(); + } + + public static LogRecordExporter otlpJsonLoggingLogRecordExporter() { + return OtlpJsonLoggingLogRecordExporter.create(); + } +} +``` + + +Implement the `LogRecordExporter` interface to provide your own custom log +record export logic. For example: + + + +```java +package otel; + +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import io.opentelemetry.sdk.logs.export.LogRecordExporter; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class CustomLogRecordExporter implements LogRecordExporter { + + private static final Logger logger = Logger.getLogger(CustomLogRecordExporter.class.getName()); + + @Override + public CompletableResultCode export(Collection logs) { + // Export the records. Typically, records are sent out of process via some network protocol, but + // we simply log for illustrative purposes. + System.out.println("Exporting logs"); + logs.forEach(log -> System.out.println("log record: " + log)); + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode flush() { + // Export any records which have been queued up but not yet exported. + logger.log(Level.INFO, "flushing"); + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode shutdown() { + // Shutdown the exporter and cleanup any resources. + logger.log(Level.INFO, "shutting down"); + return CompletableResultCode.ofSuccess(); + } +} +``` + + +#### LogLimits + +[LogLimits](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-logs/latest/io/opentelemetry/sdk/logs/LogLimits.html) +defines constraints for the data captured by log records, including max +attribute length, and max number of attributes. + +The following code snippet demonstrates `LogRecordProcessor` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.sdk.logs.LogLimits; + +public class LogLimitsConfig { + public static LogLimits logLimits() { + return LogLimits.builder() + .setMaxNumberOfAttributes(128) + .setMaxAttributeValueLength(1024) + .build(); + } +} +``` + + +### TextMapPropagator + +[TextMapPropagator](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-context/latest/io/opentelemetry/context/propagation/TextMapPropagator.html) +is a [plugin extension interface](#sdk-plugin-extension-interfaces) responsible +for propagating context across process boundaries in a text format. + +| Class | Artifact | Description | +| --------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| `W3CTraceContextPropagator` | `io.opentelemetry:opentelemetry-api:{{% param vers.otel %}}` | Propagate trace context using W3C trace context propagation protocol. | +| `W3CBaggagePropagator` | `io.opentelemetry:opentelemetry-api:{{% param vers.otel %}}` | Propagate baggage using W3C baggage propagation protocol. | +| `MultiTextMapPropagator` | `io.opentelemetry:opentelemetry-context:{{% param vers.otel %}}` | Compose multiple propagators. | +| `JaegerPropagator` | `io.opentelemetry:opentelemetry-extension-trace-propagators:{{% param vers.otel %}}` | Propagator trace context using the Jaeger propagation protocol. | +| `B3Propagator` | `io.opentelemetry:opentelemetry-extension-trace-propagators:{{% param vers.otel %}}` | Propagator trace context using the B3 propagation protocol. | +| `OtTracePropagator` | `io.opentelemetry:opentelemetry-extension-trace-propagators:{{% param vers.otel %}}` | Propagator trace context using the OpenTracing propagation protocol. | +| `PassThroughPropagator` | `io.opentelemetry:opentelemetry-api-incubator:{{% param vers.otel %}}-alpha` | Propagate a configurable set fields without participating in telemetry. | +| `AwsXrayPropagator` | `io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:{{% param vers.contrib %}}-alpha` | Propagate trace context using AWS X-Ray propagation protocol. | +| `AwsXrayLambdaPropagator` | `io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:{{% param vers.contrib %}}-alpha` | Propagate trace context using environment variables and AWS X-Ray propagation protocol. | + +The following code snippet demonstrates `TextMapPropagator` programmatic +configuration: + + + +```java +package otel; + +import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator; +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.TextMapPropagator; + +public class ContextPropagatorsConfig { + public static ContextPropagators create() { + return ContextPropagators.create( + TextMapPropagator.composite( + W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance())); + } +} +``` + + +Implement the `TextMapPropagator` interface to provide your own custom +propagator logic. For example: + + + +```java +package otel; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.context.propagation.TextMapSetter; +import java.util.Collection; +import java.util.Collections; + +public class CustomTextMapPropagator implements TextMapPropagator { + + @Override + public Collection fields() { + // Return fields used for propagation. See W3CTraceContextPropagator for reference + // implementation. + return Collections.emptyList(); + } + + @Override + public void inject(Context context, C carrier, TextMapSetter setter) { + // Inject context. See W3CTraceContextPropagator for reference implementation. + } + + @Override + public Context extract(Context context, C carrier, TextMapGetter getter) { + // Extract context. See W3CTraceContextPropagator for reference implementation. + return context; + } +} +``` + + +## Appendix + +### Internal logging + +SDK components log a variety of information to +[java.util.logging](https://docs.oracle.com/javase/7/docs/api/java/util/logging/package-summary.html), +at different log levels and using logger names based on the fully qualified +class name of the relevant component. + +By default, log messages are handled by the root handler in your application. If +you have not installed a custom root handler for your application, logs of level +`INFO` or higher are sent to the console by default. + +You may want to change the behavior of the logger for OpenTelemetry. For +example, you can reduce the logging level to output additional information when +debugging, increase the level for a particular class to ignore errors coming +from the class, or install a custom handler or filter to run custom code +whenever OpenTelemetry logs a particular message. No detailed list of logger +names and log information is maintained. However, all OpenTelemetry API, SDK, +contrib and instrumentation components share the same `io.opentelemetry.*` +package prefix. It can be useful to enable finer grain logs for all +`io.opentelemetry.*`, inspect the output, and narrow down to packages or FQCNs +of interest. + +For example: + +```properties +## Turn off all OpenTelemetry logging +io.opentelemetry.level = OFF +``` + +```properties +## Turn off logging for just the BatchSpanProcessor +io.opentelemetry.sdk.trace.export.BatchSpanProcessor.level = OFF +``` + +```properties +## Log "FINE" messages for help in debugging +io.opentelemetry.level = FINE + +## Sets the default ConsoleHandler's logger's level +## Note this impacts the logging outside of OpenTelemetry as well +java.util.logging.ConsoleHandler.level = FINE +``` + +For more fine-grained control and special case handling, custom handlers and +filters can be specified with code. + +```java +// Custom filter which does not log errors which come from the export +public class IgnoreExportErrorsFilter implements java.util.logging.Filter { + + public boolean isLoggable(LogRecord record) { + return !record.getMessage().contains("Exception thrown by the export"); + } +} +``` + +```properties +## Registering the custom filter on the BatchSpanProcessor +io.opentelemetry.sdk.trace.export.BatchSpanProcessor = io.opentelemetry.extension.logging.IgnoreExportErrorsFilter +``` + +### OTLP exporter senders + +The [span exporter](#spanexporter), [metric exporter](#metricexporter), and +[log exporter](#logrecordexporter) discuss OTLP exporters of the form: + +- `OtlpHttp{Signal}Exporter`s export data via OTLP `http/protobuf`. +- `OtlpGrpc{Signal}Exporter`s export data via OTLP `grpc`. + +The exporters for all signals are available via +`io.opentelemetry:opentelemetry-exporter-otlp:{{% param vers.otel %}}`. + +Internally, these exporters depend on various client libraries to execute HTTP +and gRPC requests. There is no single HTTP / gRPC client library which satisfies +all use cases in the Java ecosystem: + +- Java 11+ brings the built-in `java.net.http.HttpClient`, but + `opentelemetry-java` needs to support Java 8+ users, and this can't be used to + export via `gRPC` because there is no support for trailer headers. +- [OkHttp](https://square.github.io/okhttp/) provides a powerful HTTP client + with support for trailer headers, but depends on the kotlin standard library. +- [grpc-java](https://github.com/grpc/grpc-java) provides its own + `ManagedChannel` abstraction with various + [transport implementations](https://github.com/grpc/grpc-java#transport), but + is not suitable for `http/protobuf`. + +In order to accommodate various use cases, `opentelemetry-exporter-otlp` uses an +internal "sender" abstraction, with a variety of implementations to reflect +application constraints. To choose another implementation, exclude the +`io.opentelemetry:opentelemetry-exporter-sender-okhttp` default dependency, and +add a dependency on the alternative. + +| Artifact | Description | OTLP Protocols | Default | +| ----------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ----------------------- | ------- | +| `io.opentelemetry:opentelemetry-exporter-sender-okhttp:{{% param vers.otel %}}` | OkHttp based implementation. | `grpc`, `http/protobuf` | Yes | +| `io.opentelemetry:opentelemetry-exporter-sender-jdk:{{% param vers.otel %}}` | Java 11+ `java.net.http.HttpClient` based implementation. | `http/protobuf` | No | +| `io.opentelemetry:opentelemetry-exporter-sender-grpc-managed-channel:{{% param vers.otel %}}` **[1]** | `grpc-java` `ManagedChannel` based implementation. | `grpc` | No | + +**[1]**: In order to use `opentelemetry-exporter-sender-grpc-managed-channel`, +you must also add a dependency on a +[gRPC transport implementations](https://github.com/grpc/grpc-java#transport). + +### Testing + +TODO: document tools available for testing the SDK diff --git a/content/zh/docs/languages/java/_index.md b/content/zh/docs/languages/java/_index.md index e6c543180708..545aab542a50 100644 --- a/content/zh/docs/languages/java/_index.md +++ b/content/zh/docs/languages/java/_index.md @@ -7,8 +7,9 @@ aliases: [/java, /java/metrics, /java/tracing] cascade: vers: instrumentation: 2.7.0 - otel: 1.41.0 - semconv: 1.26.0 + otel: 1.42.1 + contrib: 1.38.0 + semconv: 1.27.0 weight: 18 default_lang_commit: 20c51c53 --- diff --git a/static/refcache.json b/static/refcache.json index c6e2b5091a74..f72f91d4cc4e 100644 --- a/static/refcache.json +++ b/static/refcache.json @@ -12611,6 +12611,114 @@ "StatusCode": 200, "LastSeen": "2024-01-18T19:55:46.525923-05:00" }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/OpenTelemetry.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:48.24217-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/logs/LoggerProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:59:36.584528-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/MeterProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:59:35.353354-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/trace/TracerProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:51.603241-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-context/latest/io/opentelemetry/context/propagation/TextMapPropagator.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:20:15.97313-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-common/latest/io/opentelemetry/sdk/resources/Resource.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:48.789766-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizerProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:47.350858-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/ConfigurablePropagatorProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:52.021638-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/ResourceProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:46.613025-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/logs/ConfigurableLogRecordExporterProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:49.681449-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/metrics/ConfigurableMetricExporterProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:49.282113-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/traces/ConfigurableSamplerProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:50.375824-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/latest/io/opentelemetry/sdk/autoconfigure/spi/traces/ConfigurableSpanExporterProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:48.764972-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-logs/latest/io/opentelemetry/sdk/logs/LogLimits.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:20:13.206672-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-logs/latest/io/opentelemetry/sdk/logs/LogRecordProcessor.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:20:10.807547-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-logs/latest/io/opentelemetry/sdk/logs/SdkLoggerProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:20:11.11031-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-logs/latest/io/opentelemetry/sdk/logs/export/LogRecordExporter.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:20:12.3063-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-metrics/latest/io/opentelemetry/sdk/metrics/SdkMeterProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:20:03.650649-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-metrics/latest/io/opentelemetry/sdk/metrics/View.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:20:09.004763-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-metrics/latest/io/opentelemetry/sdk/metrics/export/MetricExporter.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:20:07.498447-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-metrics/latest/io/opentelemetry/sdk/metrics/export/MetricReader.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:20:07.128256-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/SdkTracerProvider.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:51.223697-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/SpanLimits.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:20:00.974651-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/SpanProcessor.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:56.651306-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/export/SpanExporter.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:59.28131-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-trace/latest/io/opentelemetry/sdk/trace/samplers/Sampler.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:52.123293-05:00" + }, + "https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk/latest/io/opentelemetry/sdk/OpenTelemetrySdk.html": { + "StatusCode": 200, + "LastSeen": "2024-08-05T15:19:47.672179-05:00" + }, "https://www.jenkins.io": { "StatusCode": 206, "LastSeen": "2024-01-30T05:18:35.317496-05:00"