diff --git a/.gitmodules b/.gitmodules index 1cde6cc00d6e..7f0eda728cc5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "content-modules/opentelemetry-specification"] path = content-modules/opentelemetry-specification url = https://github.com/open-telemetry/opentelemetry-specification.git +[submodule "content-modules/opentelemetry-java"] + path = content-modules/opentelemetry-java + url = https://github.com/open-telemetry/opentelemetry-java diff --git a/content-modules/opentelemetry-java b/content-modules/opentelemetry-java new file mode 160000 index 000000000000..fca5bbe36b2f --- /dev/null +++ b/content-modules/opentelemetry-java @@ -0,0 +1 @@ +Subproject commit fca5bbe36b2f1e378eb6b5fdb3ce6e448db44119 diff --git a/content/en/docs/java b/content/en/docs/java new file mode 120000 index 000000000000..97ac4f22f3d2 --- /dev/null +++ b/content/en/docs/java @@ -0,0 +1 @@ +../../../content-modules/opentelemetry-java/website_docs \ No newline at end of file diff --git a/content/en/docs/java/_index.md b/content/en/docs/java/_index.md deleted file mode 100644 index d9a46c04a349..000000000000 --- a/content/en/docs/java/_index.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Java -weight: 18 -description: >- - - A language-specific implementation of OpenTelemetry in Java. -cascade: - github_repo: &repo https://github.com/open-telemetry/opentelemetry-java - github_subdir: website_docs - path_base_for_github_subdir: content/en/docs/java/ - github_project_repo: *repo ---- - -OpenTelemetry Java consists of the following repositories: - -- [opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java): - Components for manual instrumentation including API and SDK as well as - extensions, the OpenTracing shim and examples. -- [opentelemetry-java-instrumentation](https://github.com/open-telemetry/opentelemetry-java-instrumentation): - Built on top of opentelemetry-java and provides a Java agent JAR that can be - attached to any Java 8+ application and dynamically injects bytecode to - capture telemetry from a number of popular libraries and frameworks. -- [opentelemetry-java-contrib](https://github.com/open-telemetry/opentelemetry-java-contrib): - Provides helpful libraries and standalone OpenTelemetry-based utilities that - don't fit the express scope of the OpenTelemetry Java or Java Instrumentation - projects. For example, JMX metric gathering. - -## opentelemetry-java - -| Traces | Metrics | Logs | -| ------ | ------- | ------------ | -| Stable | Alpha | Experimental | - -### Components - -- Tracing API -- Tracing SDK -- Metrics API -- Metrics SDK -- OTLP Exporter -- Jaeger Trace Exporter -- Zipkin Trace Exporter -- Prometheus Metric Exporter -- Context Propagation -- OpenTracing Bridge -- OpenCensus Bridge - -### Releases - -Published releases are available on maven central. We strongly recommend using our BOM to keep the -versions of the various components in sync. - -#### Maven - -```xml - - - - - io.opentelemetry - opentelemetry-bom - 1.6.0 - pom - import - - - - - - io.opentelemetry - opentelemetry-api - - - -``` - -#### Gradle - -```kotlin -dependencies { - implementation(platform("io.opentelemetry:opentelemetry-bom:1.6.0")) - implementation("io.opentelemetry:opentelemetry-api") -} -``` - -#### Other - - - [releases](https://github.com/open-telemetry/opentelemetry-java/releases) - - [maven](https://mvnrepository.com/artifact/io.opentelemetry) - -### Additional Information - -- [Javadoc](https://www.javadoc.io/doc/io.opentelemetry) -- [Example code](https://github.com/open-telemetry/opentelemetry-java/tree/main/examples) diff --git a/content/en/docs/java/instrumentation_examples.md b/content/en/docs/java/instrumentation_examples.md deleted file mode 100644 index 994a39186b21..000000000000 --- a/content/en/docs/java/instrumentation_examples.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: "Instrumentation Examples" -weight: 4 ---- - -Here are Some of the resources for Opentelemetry Instrumentation Examples - -## Community Resources - -### boot-opentelemetry-tempo - -Project demonstrating Complete Observability Stack utilizing [Prometheus](https://prometheus.io/), [Loki](https://grafana.com/oss/loki/) (_For distributed logging_), [Tempo](https://grafana.com/oss/tempo/) (_For Distributed tracing, this basically uses Jaeger Internally_), [Grafana](https://grafana.com/grafana/) for **Java/spring** based applications (_With OpenTelemetry auto / manual Instrumentation_) involving multiple microservices with DB interactions - -Checkout [boot-opentelemetry-tempo](https://github.com/mnadeem/boot-opentelemetry-tempo) and get started - -````bash -mvn clean package docker:build -```` - -````bash -docker-compose up -```` - - diff --git a/content/en/docs/java/manual_instrumentation.md b/content/en/docs/java/manual_instrumentation.md deleted file mode 100644 index b26f3744dc53..000000000000 --- a/content/en/docs/java/manual_instrumentation.md +++ /dev/null @@ -1,503 +0,0 @@ ---- -Title: "Manual Instrumentation" -Weight: 3 ---- - - - - -- [Set up](#set-up) -- [Tracing](#tracing) - * [Create basic Span](#create-a-basic-span) - * [Create nested Spans](#create-nested-spans) - * [Span Attributes](#span-attributes) - * [Create Spans with events](#create-spans-with-events) - * [Create Spans with links](#create-spans-with-links) - * [Context Propagation](#context-propagation) -- [Metrics](#metrics-alpha-only) -- [Tracing SDK Configuration](#tracing-sdk-configuration) - * [Sampler](#sampler) - * [Span Processor](#span-processor) - * [Exporter](#exporter) -- [Auto Configuration](#auto-configuration) -- [Logging And Error Handling](#logging-and-error-handling) - * [Examples](#examples) - - -**Libraries** that want to export telemetry data using OpenTelemetry MUST only depend on the -`opentelemetry-api` package and should never configure or depend on the OpenTelemetry SDK. The SDK -configuration must be provided by **Applications** which should also depend on the -`opentelemetry-sdk` package, or any other implementation of the OpenTelemetry API. This way, -libraries will obtain a real implementation only if the user application is configured for it. For -more details, check out the [Library Guidelines]. - -## Set up - -The first step is to get a handle to an instance of the `OpenTelemetry` interface. - -If you are an application developer, you need to configure an instance of the `OpenTelemetrySdk` as -early as possible in your application. This can be done using the `OpenTelemetrySdk.builder()` method. - -For example: - -```java - SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() - .addSpanProcessor(BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder().build()).build()) - .build(); - - OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() - .setTracerProvider(sdkTracerProvider) - .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) - .buildAndRegisterGlobal(); -``` - -As an aside, if you are writing library instrumentation, it is strongly recommended that you provide your users -the ability to inject an instance of `OpenTelemetry` into your instrumentation code. If this is -not possible for some reason, you can fall back to using an instance from the `GlobalOpenTelemetry` -class. Note that you can't force end-users to configure the global, so this is the most brittle -option for library instrumentation. - -## Tracing - -In the following, we present how to trace code using the OpenTelemetry API. **Note:** Methods of the -OpenTelemetry SDK should never be called. - -First, a `Tracer` must be acquired, which is responsible for creating spans and interacting with the -[Context](#context-propagation). A tracer is acquired by using the OpenTelemetry API specifying the -name and version of the [library instrumenting][Instrumentation Library] the [instrumented library] or application to be -monitored. More information is available in the specification chapter [Obtaining a Tracer]. - -```java -Tracer tracer = - openTelemetry.getTracer("instrumentation-library-name", "1.0.0"); -``` - -Important: the "name" and optional version of the tracer are purely informational. -All `Tracer`s that are created by a single `OpenTelemetry` instance will interoperate, regardless of name. - -### Create a basic Span -To create a basic span, you only need to specify the name of the span. -The start and end time of the span is automatically set by the OpenTelemetry SDK. -```java -Span span = tracer.spanBuilder("my span").startSpan(); -// put the span into the current Context -try (Scope scope = span.makeCurrent()) { - // your use case - ... -} catch (Throwable t) { - span.setStatus(StatusCode.ERROR, "Change it to your error message"); -} finally { - span.end(); // closing the scope does not end the span, this has to be done manually -} -``` - -### Create nested Spans - -Most of the time, we want to correlate spans for nested operations. OpenTelemetry supports tracing -within processes and across remote processes. For more details how to share context between remote -processes, see [Context Propagation](#context-propagation). - -For a method `a` calling a method `b`, the spans could be manually linked in the following way: -```java -void parentOne() { - Span parentSpan = tracer.spanBuilder("parent").startSpan(); - try { - childOne(parentSpan); - } finally { - parentSpan.end(); - } -} - -void childOne(Span parentSpan) { - Span childSpan = tracer.spanBuilder("child") - .setParent(Context.current().with(parentSpan)) - .startSpan(); - // do stuff - childSpan.end(); -} -``` -The OpenTelemetry API offers also an automated way to propagate the parent span on the current thread: -```java -void parentTwo() { - Span parentSpan = tracer.spanBuilder("parent").startSpan(); - try(Scope scope = parentSpan.makeCurrent()) { - childTwo(); - } finally { - parentSpan.end(); - } -} -void childTwo() { - Span childSpan = tracer.spanBuilder("child") - // NOTE: setParent(...) is not required; - // `Span.current()` is automatically added as the parent - .startSpan(); - try(Scope scope = childSpan.makeCurrent()) { - // do stuff - } finally { - childSpan.end(); - } -} -``` - -To link spans from remote processes, it is sufficient to set the -[Remote Context](#context-propagation) as parent. - -```java -Span childRemoteParent = tracer.spanBuilder("Child").setParent(remoteContext).startSpan(); -``` - -### Span Attributes -In OpenTelemetry spans can be created freely and it's up to the implementor to annotate them with -attributes specific to the represented operation. Attributes provide additional context on a span -about the specific operation it tracks, such as results or operation properties. - -```java -Span span = tracer.spanBuilder("/resource/path").setSpanKind(SpanKind.CLIENT).startSpan(); -span.setAttribute("http.method", "GET"); -span.setAttribute("http.url", url.toString()); -``` - -Some of these operations represent calls that use well-known protocols like HTTP or database calls. -For these, OpenTelemetry requires specific attributes to be set. The full attribute list is -available in the [Semantic Conventions](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/README.md) in the cross-language specification. - -### Create Spans with events - -Spans can be annotated with named events that can carry zero or more -[Span Attributes](#span-attributes), each of which is itself a key:value map paired automatically -with a timestamp. - -```java -span.addEvent("Init"); -... -span.addEvent("End"); -``` - -```java -Attributes eventAttributes = Attributes.of( - AttributeKey.stringKey("key"), "value", - AttributeKey.longKey("result"), 0L); - -span.addEvent("End Computation", eventAttributes); -``` - -### Create Spans with links -A Span may be linked to zero or more other Spans that are causally related. Links can be used to -represent batched operations where a Span was initiated by multiple initiating Spans, each -representing a single incoming item being processed in the batch. - -```java -Span child = tracer.spanBuilder("childWithLink") - .addLink(parentSpan1.getSpanContext()) - .addLink(parentSpan2.getSpanContext()) - .addLink(parentSpan3.getSpanContext()) - .addLink(remoteSpanContext) - .startSpan(); -``` - -For more details how to read context from remote processes, see -[Context Propagation](#context-propagation). - -### Context Propagation - -OpenTelemetry provides a text-based approach to propagate context to remote services using the -[W3C Trace Context](https://www.w3.org/TR/trace-context/) HTTP headers. - -The following presents an example of an outgoing HTTP request using `HttpURLConnection`. - -```java -// Tell OpenTelemetry to inject the context in the HTTP headers -TextMapSetter setter = - new TextMapSetter() { - @Override - public void set(HttpURLConnection carrier, String key, String value) { - // Insert the context as Header - carrier.setRequestProperty(key, value); - } -}; - -URL url = new URL("http://127.0.0.1:8080/resource"); -Span outGoing = tracer.spanBuilder("/resource").setSpanKind(SpanKind.CLIENT).startSpan(); -try (Scope scope = outGoing.makeCurrent()) { - // Use the Semantic Conventions. - // (Note that to set these, Span does not *need* to be the current instance in Context or Scope.) - outGoing.setAttribute(SemanticAttributes.HTTP_METHOD, "GET"); - outGoing.setAttribute(SemanticAttributes.HTTP_URL, url.toString()); - HttpURLConnection transportLayer = (HttpURLConnection) url.openConnection(); - // Inject the request with the *current* Context, which contains our current Span. - openTelemetry.getPropagators().getTextMapPropagator().inject(Context.current(), transportLayer, setter); - // Make outgoing call -} finally { - outGoing.end(); -} -... -``` - -Similarly, the text-based approach can be used to read the W3C Trace Context from incoming requests. -The following presents an example of processing an incoming HTTP request using -[HttpExchange](https://docs.oracle.com/javase/8/docs/jre/api/net/httpserver/spec/com/sun/net/httpserver/HttpExchange.html). - -```java -TextMapGetter getter = - new TextMapGetter<>() { - @Override - public String get(HttpExchange carrier, String key) { - if (carrier.getRequestHeaders().containsKey(key)) { - return carrier.getRequestHeaders().get(key).get(0); - } - return null; - } - - @Override - public Iterable keys(HttpExchange carrier) { - return carrier.getRequestHeaders().keySet(); - } -}; -... -public void handle(HttpExchange httpExchange) { - // Extract the SpanContext and other elements from the request. - Context extractedContext = openTelemetry.getPropagators().getTextMapPropagator() - .extract(Context.current(), httpExchange, getter); - try (Scope scope = extractedContext.makeCurrent()) { - // Automatically use the extracted SpanContext as parent. - Span serverSpan = tracer.spanBuilder("GET /resource") - .setSpanKind(SpanKind.SERVER) - .startSpan(); - try { - // Add the attributes defined in the Semantic Conventions - serverSpan.setAttribute(SemanticAttributes.HTTP_METHOD, "GET"); - serverSpan.setAttribute(SemanticAttributes.HTTP_SCHEME, "http"); - serverSpan.setAttribute(SemanticAttributes.HTTP_HOST, "localhost:8080"); - serverSpan.setAttribute(SemanticAttributes.HTTP_TARGET, "/resource"); - // Serve the request - ... - } finally { - serverSpan.end(); - } - } -} -``` - -## Metrics (alpha only!) - -Spans are a great way to get detailed information about what your application is doing, but -what about a more aggregated perspective? OpenTelemetry provides supports for metrics, a time series -of numbers that might express things such as CPU utilization, request count for an HTTP server, or a -business metric such as transactions. - -In order to access the alpha metrics library, you will need to explicitly depend on the `opentelemetry-api-metrics` -and `opentelemetry-sdk-metrics` modules, which are not included in the opentelemetry-bom until they are -stable and ready for long-term-support. - -All metrics can be annotated with labels: additional qualifiers that help describe what -subdivision of the measurements the metric represents. - -First, you'll need to get access to a `MeterProvider`. Note the APIs for this are in flux, so no -example code is provided here for that. - -The following is an example of counter usage: - -```java -// Gets or creates a named meter instance - Meter meter = meterProvider.meterBuilder("instrumentation-library-name") - .setInstrumentationVersion("1.0.0") - .build(); - -// Build counter e.g. LongCounter - LongCounter counter = meter - .counterBuilder("processed_jobs") - .setDescription("Processed jobs") - .setUnit("1") - .build(); - -// It is recommended that the API user keep a reference to a Bound Counter for the entire time or -// call unbind when no-longer needed. - BoundLongCounter someWorkCounter = counter.bind(Attributes.of(stringKey("Key"), "SomeWork")); - - -// Record data - someWorkCounter.add(123); - -// Alternatively, the user can use the unbounded counter and explicitly -// specify the labels set at call-time: - counter.add(123, Attributes.of(stringKey("Key"), "SomeWork")); -``` - -An `Observer` is an additional type of instrument supporting an asynchronous API and -collecting metric data on demand, once per collection interval. - -The following is an example of usage of an observer: - -```java -// Build an "observer" instrument, e.g. Gauge - meter - .gaugeBuilder("cpu_usage") - .setDescription("CPU Usage") - .setUnit("ms") - .buildWithCallback(result -> { - result.observe(getCpuUsage(), Attributes.of(stringKey("Key"), "SomeWork")); - }); -``` - -## Tracing 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. - -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(new LoggingSpanExporter()).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(new LoggingSpanExporter())) - .addSpanProcessor(BatchSpanProcessor.builder(new LoggingSpanExporter()).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: -- In-Memory Exporter: keeps the data in memory, useful for debugging. -- Jaeger Exporter: prepares and sends the collected telemetry data to a Jaeger backend via gRPC. -- Zipkin Exporter: prepares and sends the collected telemetry data to a Zipkin backend via the Zipkin APIs. -- Logging Exporter: saves the telemetry data into log streams. -- OpenTelemetry Exporter: sends the data to the [OpenTelemetry Collector]. - -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(); -``` - -### Auto Configuration - -To configure the OpenTelemetry SDK based on the standard set of environment variables and system -properties, you can use the `opentelemetry-sdk-extension-autoconfigure` module. - -```java - OpenTelemetrySdk sdk = OpenTelemetrySdkAutoConfiguration.initialize(); -``` - -See the supported configuration options in the module's [README](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure). - -[AlwaysOnSampler]: https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk/tracing/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java#L29 -[AlwaysOffSampler]:https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk/tracing/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java#L40 -[ParentBased]:https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk/tracing/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java#L54 -[TraceIdRatioBased]:https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk/tracing/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java#L78 -[Library Guidelines]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/library-guidelines.md -[OpenTelemetry Collector]: https://github.com/open-telemetry/opentelemetry-collector -[OpenTelemetry Registry]: https://opentelemetry.io/registry/?s=exporter -[OpenTelemetry Website]: https://opentelemetry.io/ -[Obtaining a Tracer]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#get-a-tracer -[Semantic Conventions]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions -[Instrumentation Library]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/glossary.md#instrumentation-library -[instrumented library]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/glossary.md#instrumented-library - -## 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 -```