diff --git a/doc-snippets/configuration/build.gradle.kts b/doc-snippets/configuration/build.gradle.kts new file mode 100644 index 0000000000..4d568ec4a9 --- /dev/null +++ b/doc-snippets/configuration/build.gradle.kts @@ -0,0 +1,20 @@ +plugins { + id("java") +} + +val moduleName by extra { "io.opentelemetry.examples.docs.configuration" } + +dependencies { + implementation("io.opentelemetry:opentelemetry-sdk") + implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + + implementation("io.opentelemetry:opentelemetry-exporter-otlp") + implementation("io.opentelemetry:opentelemetry-exporter-logging") + implementation("io.opentelemetry:opentelemetry-exporter-logging-otlp") + implementation("io.opentelemetry:opentelemetry-exporter-zipkin") + implementation("io.opentelemetry:opentelemetry-exporter-prometheus") + implementation("io.opentelemetry:opentelemetry-sdk-extension-jaeger-remote-sampler") + + implementation("io.opentelemetry.semconv:opentelemetry-semconv") + implementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating:1.26.0-alpha") +} diff --git a/doc-snippets/configuration/src/main/java/otel/AutoConfiguredSdk.java b/doc-snippets/configuration/src/main/java/otel/AutoConfiguredSdk.java new file mode 100644 index 0000000000..8120a1359d --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/AutoConfiguredSdk.java @@ -0,0 +1,10 @@ +package otel; + +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; + +public class AutoConfiguredSdk { + public static OpenTelemetrySdk autoconfiguredSdk() { + return AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/ContextPropagatorsConfig.java b/doc-snippets/configuration/src/main/java/otel/ContextPropagatorsConfig.java new file mode 100644 index 0000000000..cb32324b9e --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/ContextPropagatorsConfig.java @@ -0,0 +1,14 @@ +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())); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomLogRecordExporter.java b/doc-snippets/configuration/src/main/java/otel/CustomLogRecordExporter.java new file mode 100644 index 0000000000..8f5d37ad97 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomLogRecordExporter.java @@ -0,0 +1,36 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomLogRecordExporterProvider.java b/doc-snippets/configuration/src/main/java/otel/CustomLogRecordExporterProvider.java new file mode 100644 index 0000000000..03bb4b3a5b --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomLogRecordExporterProvider.java @@ -0,0 +1,19 @@ +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"; + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomLogRecordProcessor.java b/doc-snippets/configuration/src/main/java/otel/CustomLogRecordProcessor.java new file mode 100644 index 0000000000..ccbb761368 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomLogRecordProcessor.java @@ -0,0 +1,29 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomMetricExporter.java b/doc-snippets/configuration/src/main/java/otel/CustomMetricExporter.java new file mode 100644 index 0000000000..efcf254b54 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomMetricExporter.java @@ -0,0 +1,61 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomMetricExporterProvider.java b/doc-snippets/configuration/src/main/java/otel/CustomMetricExporterProvider.java new file mode 100644 index 0000000000..2413d48331 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomMetricExporterProvider.java @@ -0,0 +1,19 @@ +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"; + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomMetricReader.java b/doc-snippets/configuration/src/main/java/otel/CustomMetricReader.java new file mode 100644 index 0000000000..a5c4507816 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomMetricReader.java @@ -0,0 +1,76 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomResourceProvider.java b/doc-snippets/configuration/src/main/java/otel/CustomResourceProvider.java new file mode 100644 index 0000000000..20f04f268d --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomResourceProvider.java @@ -0,0 +1,20 @@ +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; + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomSampler.java b/doc-snippets/configuration/src/main/java/otel/CustomSampler.java new file mode 100644 index 0000000000..a4b8a9df47 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomSampler.java @@ -0,0 +1,38 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomSamplerProvider.java b/doc-snippets/configuration/src/main/java/otel/CustomSamplerProvider.java new file mode 100644 index 0000000000..39c9e50a93 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomSamplerProvider.java @@ -0,0 +1,19 @@ +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"; + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomSpanExporter.java b/doc-snippets/configuration/src/main/java/otel/CustomSpanExporter.java new file mode 100644 index 0000000000..e3ab1f6bc5 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomSpanExporter.java @@ -0,0 +1,36 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomSpanExporterProvider.java b/doc-snippets/configuration/src/main/java/otel/CustomSpanExporterProvider.java new file mode 100644 index 0000000000..bae56a76a5 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomSpanExporterProvider.java @@ -0,0 +1,19 @@ +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"; + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomSpanProcessor.java b/doc-snippets/configuration/src/main/java/otel/CustomSpanProcessor.java new file mode 100644 index 0000000000..047804f599 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomSpanProcessor.java @@ -0,0 +1,46 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomTextMapPropagator.java b/doc-snippets/configuration/src/main/java/otel/CustomTextMapPropagator.java new file mode 100644 index 0000000000..7be2036db8 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomTextMapPropagator.java @@ -0,0 +1,29 @@ +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; + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomTextMapPropagatorProvider.java b/doc-snippets/configuration/src/main/java/otel/CustomTextMapPropagatorProvider.java new file mode 100644 index 0000000000..ddfab727f9 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomTextMapPropagatorProvider.java @@ -0,0 +1,18 @@ +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"; + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomizedAutoConfiguredSdk.java b/doc-snippets/configuration/src/main/java/otel/CustomizedAutoConfiguredSdk.java new file mode 100644 index 0000000000..71f33d0436 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomizedAutoConfiguredSdk.java @@ -0,0 +1,41 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/CustomizerProvider.java b/doc-snippets/configuration/src/main/java/otel/CustomizerProvider.java new file mode 100644 index 0000000000..2c1a5ec078 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/CustomizerProvider.java @@ -0,0 +1,46 @@ +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; + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/LogLimitsConfig.java b/doc-snippets/configuration/src/main/java/otel/LogLimitsConfig.java new file mode 100644 index 0000000000..b7f9211605 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/LogLimitsConfig.java @@ -0,0 +1,12 @@ +package otel; + +import io.opentelemetry.sdk.logs.LogLimits; + +public class LogLimitsConfig { + public static LogLimits logLimits() { + return LogLimits.builder() + .setMaxNumberOfAttributes(128) + .setMaxAttributeValueLength(1024) + .build(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/LogRecordExporterConfig.java b/doc-snippets/configuration/src/main/java/otel/LogRecordExporterConfig.java new file mode 100644 index 0000000000..860f06bc45 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/LogRecordExporterConfig.java @@ -0,0 +1,34 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/LogRecordProcessorConfig.java b/doc-snippets/configuration/src/main/java/otel/LogRecordProcessorConfig.java new file mode 100644 index 0000000000..707d795d9f --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/LogRecordProcessorConfig.java @@ -0,0 +1,21 @@ +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); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/MetricExporterConfig.java b/doc-snippets/configuration/src/main/java/otel/MetricExporterConfig.java new file mode 100644 index 0000000000..b9201abc1b --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/MetricExporterConfig.java @@ -0,0 +1,34 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/MetricReaderConfig.java b/doc-snippets/configuration/src/main/java/otel/MetricReaderConfig.java new file mode 100644 index 0000000000..09085ca65c --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/MetricReaderConfig.java @@ -0,0 +1,17 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/OpenTelemetrySdkConfig.java b/doc-snippets/configuration/src/main/java/otel/OpenTelemetrySdkConfig.java new file mode 100644 index 0000000000..2215cf5fcc --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/OpenTelemetrySdkConfig.java @@ -0,0 +1,16 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/ResourceConfig.java b/doc-snippets/configuration/src/main/java/otel/ResourceConfig.java new file mode 100644 index 0000000000..ee7728160f --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/ResourceConfig.java @@ -0,0 +1,12 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/SamplerConfig.java b/doc-snippets/configuration/src/main/java/otel/SamplerConfig.java new file mode 100644 index 0000000000..1c33c5e989 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/SamplerConfig.java @@ -0,0 +1,37 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/SdkLoggerProviderConfig.java b/doc-snippets/configuration/src/main/java/otel/SdkLoggerProviderConfig.java new file mode 100644 index 0000000000..681286545f --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/SdkLoggerProviderConfig.java @@ -0,0 +1,16 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/SdkMeterProviderConfig.java b/doc-snippets/configuration/src/main/java/otel/SdkMeterProviderConfig.java new file mode 100644 index 0000000000..6a4f7fda83 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/SdkMeterProviderConfig.java @@ -0,0 +1,25 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/SdkTracerProviderConfig.java b/doc-snippets/configuration/src/main/java/otel/SdkTracerProviderConfig.java new file mode 100644 index 0000000000..81ddb24622 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/SdkTracerProviderConfig.java @@ -0,0 +1,17 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/SpanExporterConfig.java b/doc-snippets/configuration/src/main/java/otel/SpanExporterConfig.java new file mode 100644 index 0000000000..8f23e9731b --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/SpanExporterConfig.java @@ -0,0 +1,34 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/SpanLimitsConfig.java b/doc-snippets/configuration/src/main/java/otel/SpanLimitsConfig.java new file mode 100644 index 0000000000..7b020f0496 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/SpanLimitsConfig.java @@ -0,0 +1,16 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/SpanProcessorConfig.java b/doc-snippets/configuration/src/main/java/otel/SpanProcessorConfig.java new file mode 100644 index 0000000000..15517527cc --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/SpanProcessorConfig.java @@ -0,0 +1,21 @@ +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(); + } +} diff --git a/doc-snippets/configuration/src/main/java/otel/ViewConfig.java b/doc-snippets/configuration/src/main/java/otel/ViewConfig.java new file mode 100644 index 0000000000..407514cd51 --- /dev/null +++ b/doc-snippets/configuration/src/main/java/otel/ViewConfig.java @@ -0,0 +1,33 @@ +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()); + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 7f1dce576e..d55669f1ac 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -63,6 +63,7 @@ include( ":opentelemetry-examples-kotlin-extension", ":opentelemetry-examples-grpc", ":opentelemetry-examples-resource-detection-gcp", + ":doc-snippets:configuration", ":doc-snippets:getting-started", ":doc-snippets:exporters", ":doc-snippets:spring-starter",