├── .editorconfig ├── .github ├── dependabot.yml └── workflows │ ├── auto-update.yml │ ├── context.yml │ ├── dependadbot-auto-merge.yml │ ├── gradle-actions.yml │ └── update-gradle-wrapper.yml ├── .gitignore ├── LICENSE ├── README.md ├── api ├── all │ ├── build.gradle.kts │ └── src │ │ ├── commonMain │ │ └── kotlin │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── kotlin │ │ │ └── api │ │ │ ├── DefaultOpenTelemetry.kt │ │ │ ├── GlobalOpenTelemetry.kt │ │ │ ├── OpenTelemetry.kt │ │ │ ├── baggage │ │ │ ├── Baggage.kt │ │ │ ├── BaggageBuilder.kt │ │ │ ├── BaggageContextKey.kt │ │ │ ├── BaggageEntry.kt │ │ │ ├── BaggageEntryMetadata.kt │ │ │ ├── ImmutableBaggage.kt │ │ │ ├── ImmutableEntry.kt │ │ │ └── ImmutableEntryMetadata.kt │ │ │ ├── common │ │ │ ├── ArrayBackedAttributes.kt │ │ │ ├── ArrayBackedAttributesBuilder.kt │ │ │ ├── AttributeKey.kt │ │ │ ├── AttributeType.kt │ │ │ ├── Attributes.kt │ │ │ ├── AttributesBuilder.kt │ │ │ ├── DateTimeUnit.ext.kt │ │ │ └── Instant.ext.kt │ │ │ ├── internal │ │ │ ├── ImmutableKeyValuePairs.kt │ │ │ ├── ImmutableSpanContext.kt │ │ │ ├── InternalAttributeKeyImpl.kt │ │ │ ├── OtelEncodingUtils.kt │ │ │ ├── ReadOnlyArrayMap.kt │ │ │ └── TemporaryBuffers.kt │ │ │ ├── metrics │ │ │ ├── BoundDoubleCounter.kt │ │ │ ├── BoundDoubleHistogram.kt │ │ │ ├── BoundDoubleUpDownCounter.kt │ │ │ ├── BoundLongCounter.kt │ │ │ ├── BoundLongHistogram.kt │ │ │ ├── BoundLongUpDownCounter.kt │ │ │ ├── DoubleCounter.kt │ │ │ ├── DoubleCounterBuilder.kt │ │ │ ├── DoubleGaugeBuilder.kt │ │ │ ├── DoubleHistogram.kt │ │ │ ├── DoubleHistogramBuilder.kt │ │ │ ├── DoubleUpDownCounter.kt │ │ │ ├── DoubleUpDownCounterBuilder.kt │ │ │ ├── GlobalMeterProvider.kt │ │ │ ├── LongCounter.kt │ │ │ ├── LongCounterBuilder.kt │ │ │ ├── LongGaugeBuilder.kt │ │ │ ├── LongHistogram.kt │ │ │ ├── LongHistogramBuilder.kt │ │ │ ├── LongUpDownCounter.kt │ │ │ ├── LongUpDownCounterBuilder.kt │ │ │ ├── Meter.kt │ │ │ ├── MeterBuilder.kt │ │ │ ├── MeterProvider.kt │ │ │ ├── ObservableDoubleMeasurement.kt │ │ │ ├── ObservableLongMeasurement.kt │ │ │ ├── ObservableMeasurement.kt │ │ │ └── internal │ │ │ │ ├── NoopMeter.kt │ │ │ │ └── NoopMeterProvider.kt │ │ │ └── trace │ │ │ ├── ArrayBasedTraceState.kt │ │ │ ├── ArrayBasedTraceStateBuilder.kt │ │ │ ├── DefaultTracer.kt │ │ │ ├── DefaultTracerBuilder.kt │ │ │ ├── DefaultTracerProvider.kt │ │ │ ├── ImmutableTraceFlags.kt │ │ │ ├── PropagatedSpan.kt │ │ │ ├── Span.kt │ │ │ ├── SpanBuilder.kt │ │ │ ├── SpanContext.kt │ │ │ ├── SpanContextKey.kt │ │ │ ├── SpanId.kt │ │ │ ├── SpanKind.kt │ │ │ ├── StatusCode.kt │ │ │ ├── TraceFlags.kt │ │ │ ├── TraceId.kt │ │ │ ├── TraceState.kt │ │ │ ├── TraceStateBuilder.kt │ │ │ ├── Tracer.kt │ │ │ ├── TracerBuilder.kt │ │ │ └── TracerProvider.kt │ │ └── commonTest │ │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── kotlin │ │ └── api │ │ ├── EqualsTester.kt │ │ ├── Map.Entry.ext.kt │ │ ├── common │ │ ├── AttributeKeyTest.kt │ │ └── AttributesTest.kt │ │ ├── metrics │ │ └── internal │ │ │ ├── NoopMeterProviderTest.kt │ │ │ └── NoopMeterTest.kt │ │ └── trace │ │ ├── DefaultTracerProviderTest.kt │ │ ├── DefaultTracerTest.kt │ │ ├── PropagatedSpanTest.kt │ │ ├── SpanBuilderTest.kt │ │ ├── SpanContextTest.kt │ │ ├── SpanIdTest.kt │ │ ├── SpanTest.kt │ │ ├── TraceFlagsTest.kt │ │ ├── TraceIdTest.kt │ │ └── TraceStateTest.kt ├── build.gradle.kts └── metrics │ ├── build.gradle.kts │ └── src │ ├── commonMain │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── kotlin │ │ └── api │ │ └── metrics │ │ ├── BoundDoubleCounter.kt │ │ ├── BoundDoubleHistogram.kt │ │ ├── BoundDoubleUpDownCounter.kt │ │ ├── BoundLongCounter.kt │ │ ├── BoundLongHistogram.kt │ │ ├── BoundLongUpDownCounter.kt │ │ ├── DoubleCounter.kt │ │ ├── DoubleCounterBuilder.kt │ │ ├── DoubleGaugeBuilder.kt │ │ ├── DoubleHistogram.kt │ │ ├── DoubleHistogramBuilder.kt │ │ ├── DoubleUpDownCounter.kt │ │ ├── DoubleUpDownCounterBuilder.kt │ │ ├── GlobalMeterProvider.kt │ │ ├── LongCounter.kt │ │ ├── LongCounterBuilder.kt │ │ ├── LongGaugeBuilder.kt │ │ ├── LongHistogram.kt │ │ ├── LongHistogramBuilder.kt │ │ ├── LongUpDownCounter.kt │ │ ├── LongUpDownCounterBuilder.kt │ │ ├── Meter.kt │ │ ├── MeterBuilder.kt │ │ ├── MeterProvider.kt │ │ ├── ObservableDoubleMeasurement.kt │ │ ├── ObservableLongMeasurement.kt │ │ ├── ObservableMeasurement.kt │ │ └── internal │ │ ├── NoopMeter.kt │ │ └── NoopMeterProvider.kt │ └── commonTest │ └── kotlin │ └── io │ └── opentelemetry │ └── kotlin │ └── api │ └── metrics │ └── internal │ ├── NoopMeterProviderTest.kt │ └── NoopMeterTest.kt ├── build.gradle.kts ├── buildSrc ├── build.gradle.kts ├── settings.gradle.kts └── src │ └── main │ └── kotlin │ ├── common.gradle.kts │ ├── javalib.gradle.kts │ ├── mpplib.gradle.kts │ └── npmlib.gradle.kts ├── context ├── build.gradle.kts └── src │ ├── commonMain │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── kotlin │ │ ├── Closeable.kt │ │ ├── KotlinTarget.kt │ │ ├── Supplier.kt │ │ └── context │ │ ├── ArrayBasedContext.kt │ │ ├── ArrayBasedContextStorage.kt │ │ ├── Context.kt │ │ ├── ContextKey.kt │ │ ├── ContextStorage.kt │ │ ├── ContextStorageProvider.kt │ │ ├── DefaultContextKey.kt │ │ ├── ImplicitContextKeyed.kt │ │ ├── LazyStorage.kt │ │ ├── Scope.kt │ │ └── propagation │ │ ├── ContextPropagators.kt │ │ ├── DefaultContextPropagators.kt │ │ ├── MultiTextMapPropagator.kt │ │ ├── NoopTextMapPropagator.kt │ │ ├── TextMapGetter.kt │ │ ├── TextMapPropagator.kt │ │ └── TextMapSetter.kt │ ├── commonTest │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── kotlin │ │ └── context │ │ ├── ContextTest.kt │ │ └── propagation │ │ ├── DefaultPropagatorsTest.kt │ │ ├── MultiTextMapPropagatorTest.kt │ │ ├── NoopTextMapPropagatorTest.kt │ │ ├── PropagatorFactory.kt │ │ └── TextMapPropagatorTest.kt │ ├── jsMain │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── kotlin │ │ └── KotlinTarget.kt │ ├── jvmMain │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── kotlin │ │ └── KotlinTarget.kt │ └── nativeMain │ └── kotlin │ └── io │ └── opentelemetry │ └── kotlin │ └── KotlinTarget.kt ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── kotlin-js-store └── yarn.lock ├── sdk ├── build.gradle.kts ├── sdk-all │ ├── build.gradle.kts │ └── src │ │ ├── commonMain │ │ └── kotlin │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── kotlin │ │ │ └── sdk │ │ │ ├── OpenTelemetrySdk.kt │ │ │ └── OpenTelemetrySdkBuilder.kt │ │ └── commonTest │ │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── kotlin │ │ └── sdk │ │ ├── OpenTelemetrySdkTest.kt │ │ └── common │ │ └── SystemClockTest.kt ├── sdk-common │ ├── build.gradle.kts │ └── src │ │ ├── commonMain │ │ └── kotlin │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── kotlin │ │ │ └── sdk │ │ │ ├── common │ │ │ ├── Clock.kt │ │ │ ├── CompletableResultCode.kt │ │ │ ├── InstrumentationLibraryInfo.kt │ │ │ └── SystemClock.kt │ │ │ ├── internal │ │ │ ├── ComponentRegistry.kt │ │ │ └── RandomSupplier.kt │ │ │ └── resources │ │ │ ├── Resource.kt │ │ │ └── ResourceBuilder.kt │ │ └── commonTest │ │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── kotlin │ │ └── sdk │ │ └── CompletableResultCodeTest.kt ├── sdk-metrics │ ├── build.gradle.kts │ └── src │ │ ├── commonMain │ │ └── kotlin │ │ │ └── io │ │ │ └── opentelemetry │ │ │ └── kotlin │ │ │ └── sdk │ │ │ └── metrics │ │ │ ├── AbstractInstrument.kt │ │ │ ├── AbstractInstrumentBuilder.kt │ │ │ ├── Instrument.kt │ │ │ ├── SdkDoubleCounter.kt │ │ │ ├── SdkDoubleGaugeBuilder.kt │ │ │ ├── SdkDoubleHistogram.kt │ │ │ ├── SdkDoubleUpDownCounter.kt │ │ │ ├── SdkLongCounter.kt │ │ │ ├── SdkLongGaugeBuilder.kt │ │ │ ├── SdkLongHistogram.kt │ │ │ ├── SdkLongUpDownCounter.kt │ │ │ ├── SdkMeter.kt │ │ │ ├── SdkMeterBuilder.kt │ │ │ ├── SdkMeterProvider.kt │ │ │ ├── SdkMeterProviderBuilder.kt │ │ │ ├── common │ │ │ ├── InstrumentType.kt │ │ │ └── InstrumentValueType.kt │ │ │ ├── data │ │ │ ├── AggregationTemporality.kt │ │ │ ├── Data.kt │ │ │ ├── DoubleExemplarData.kt │ │ │ ├── DoubleExponentialHistogramData.kt │ │ │ ├── DoubleExponentialHistogramPointData.kt │ │ │ ├── DoubleGaugeData.kt │ │ │ ├── DoubleHistogramData.kt │ │ │ ├── DoubleHistogramPointData.kt │ │ │ ├── DoublePointData.kt │ │ │ ├── DoubleSumData.kt │ │ │ ├── DoubleSummaryData.kt │ │ │ ├── DoubleSummaryPointData.kt │ │ │ ├── ExemplarData.kt │ │ │ ├── ExponentialHistogramBuckets.kt │ │ │ ├── ExponentialHistogramData.kt │ │ │ ├── ExponentialHistogramPointData.kt │ │ │ ├── GaugeData.kt │ │ │ ├── LongExemplarData.kt │ │ │ ├── LongGaugeData.kt │ │ │ ├── LongPointData.kt │ │ │ ├── LongSumData.kt │ │ │ ├── MetricData.kt │ │ │ ├── MetricDataImpl.kt │ │ │ ├── MetricDataType.kt │ │ │ ├── PointData.kt │ │ │ ├── SumData.kt │ │ │ └── ValueAtPercentile.kt │ │ │ ├── exemplar │ │ │ ├── AbstractFixedSizeExemplarReservoir.kt │ │ │ ├── AlwaysSampleFilter.kt │ │ │ ├── ExemplarFilter.kt │ │ │ ├── ExemplarReservoir.kt │ │ │ ├── FilteredExemplarReservoir.kt │ │ │ ├── FixedSizeExemplarReservoir.kt │ │ │ ├── HistogramBucketExemplarReservoir.kt │ │ │ ├── NeverSampleFilter.kt │ │ │ ├── NoExemplarReservoir.kt │ │ │ └── WithTraceExemplarFilter.kt │ │ │ ├── export │ │ │ ├── MetricExporter.kt │ │ │ ├── MetricProducer.kt │ │ │ ├── MetricReader.kt │ │ │ ├── MetricReaderFactory.kt │ │ │ ├── PeriodicMetricReader.kt │ │ │ ├── PeriodicMetricReaderBuilder.kt │ │ │ └── PeriodicMetricReaderFactory.kt │ │ │ ├── internal │ │ │ ├── aggregator │ │ │ │ ├── AbstractMinMaxSumCountAggregator.kt │ │ │ │ ├── AbstractSumAggregator.kt │ │ │ │ ├── Aggregator.kt │ │ │ │ ├── AggregatorHandle.kt │ │ │ │ ├── BucketMapper.kt │ │ │ │ ├── CountAggregator.kt │ │ │ │ ├── DoubleAccumulation.kt │ │ │ │ ├── DoubleExponentialHistogramAggregator.kt │ │ │ │ ├── DoubleExponentialHistogramBuckets.kt │ │ │ │ ├── DoubleHistogramAggregator.kt │ │ │ │ ├── DoubleLastValueAggregator.kt │ │ │ │ ├── DoubleMinMaxSumCountAggregator.kt │ │ │ │ ├── DoubleSumAggregator.kt │ │ │ │ ├── EmptyAggregator.kt │ │ │ │ ├── ExplicitBucketHistogramUtils.kt │ │ │ │ ├── ExponentialHistogramAccumulation.kt │ │ │ │ ├── HistogramAccumulation.kt │ │ │ │ ├── LongAccumulation.kt │ │ │ │ ├── LongLastValueAggregator.kt │ │ │ │ ├── LongMinMaxSumCountAggregator.kt │ │ │ │ ├── LongSumAggregator.kt │ │ │ │ ├── MetricDataUtils.kt │ │ │ │ ├── MinMaxSumCountAccumulation.kt │ │ │ │ └── package-info.kt │ │ │ ├── debug │ │ │ │ ├── DebugConfig.kt │ │ │ │ ├── NoSourceInfo.kt │ │ │ │ ├── SourceInfo.kt │ │ │ │ └── StackTraceSourceInfo.kt │ │ │ ├── descriptor │ │ │ │ ├── InstrumentDescriptor.kt │ │ │ │ └── MetricDescriptor.kt │ │ │ ├── export │ │ │ │ ├── CollectionHandle.kt │ │ │ │ └── CollectionInfo.kt │ │ │ ├── state │ │ │ │ ├── AsynchronousMetricStorage.kt │ │ │ │ ├── BoundStorageHandle.kt │ │ │ │ ├── DebugUtils.kt │ │ │ │ ├── DefaultSynchronousMetricStorage.kt │ │ │ │ ├── DeltaAccumulation.kt │ │ │ │ ├── DeltaMetricStorage.kt │ │ │ │ ├── DuplicateMetricStorageException.kt │ │ │ │ ├── EmptyMetricStorage.kt │ │ │ │ ├── ExponentialCounter.kt │ │ │ │ ├── MapCounter.kt │ │ │ │ ├── MeterProviderSharedState.kt │ │ │ │ ├── MeterSharedState.kt │ │ │ │ ├── MetricStorage.kt │ │ │ │ ├── MetricStorageRegistry.kt │ │ │ │ ├── MetricStorageUtils.kt │ │ │ │ ├── MultiBoundStorageHandle.kt │ │ │ │ ├── MultiWritableMetricStorage.kt │ │ │ │ ├── SynchronousMetricStorage.kt │ │ │ │ ├── TemporalMetricStorage.kt │ │ │ │ ├── TemporalityUtils.kt │ │ │ │ └── WriteableMetricStorage.kt │ │ │ └── view │ │ │ │ ├── AttributesProcessor.kt │ │ │ │ ├── RegisteredView.kt │ │ │ │ ├── StringPredicates.kt │ │ │ │ ├── ViewRegistry.kt │ │ │ │ └── ViewRegistryBuilder.kt │ │ │ ├── math.kt │ │ │ ├── testing │ │ │ ├── InMemoryMetricExporter.kt │ │ │ └── InMemoryMetricReader.kt │ │ │ └── view │ │ │ ├── Aggregation.kt │ │ │ ├── DefaultAggregation.kt │ │ │ ├── ExplicitBucketHistogramAggregation.kt │ │ │ ├── InstrumentSelector.kt │ │ │ ├── LastValueAggregation.kt │ │ │ ├── MeterSelector.kt │ │ │ ├── NoAggregation.kt │ │ │ ├── SumAggregation.kt │ │ │ ├── View.kt │ │ │ ├── ViewBuilder.kt │ │ │ └── package-info.kt │ │ └── commonTest │ │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── kotlin │ │ └── sdk │ │ └── metrics │ │ ├── AbstractInstrumentTest.kt │ │ ├── CardinalityTest.kt │ │ ├── SdkDoubleCounterTest.kt │ │ ├── SdkDoubleGaugeBuilderTest.kt │ │ ├── SdkDoubleHistogramTest.kt │ │ ├── SdkDoubleSumObserverTest.kt │ │ ├── SdkDoubleUpDownCounterTest.kt │ │ ├── SdkDoubleUpDownSumObserverTest.kt │ │ ├── SdkLongCounterTest.kt │ │ ├── SdkLongGaugeBuilderTest.kt │ │ ├── SdkLongHistogramTest.kt │ │ ├── SdkLongSumObserverTest.kt │ │ ├── SdkLongUpDownCounterTest.kt │ │ ├── SdkLongUpDownSumObserverTest.kt │ │ ├── SdkMeterProviderBuilderTest.kt │ │ ├── SdkMeterProviderTest.kt │ │ ├── SdkMeterRegistryTest.kt │ │ ├── SdkMeterTest.kt │ │ ├── StressTestRunner.kt │ │ ├── data │ │ └── MetricDataImplTest.kt │ │ ├── exemplar │ │ ├── ExemplarFilterTest.kt │ │ ├── FilteredExemplarReservoirTest.kt │ │ ├── FixedSizeExemplarReservoirTest.kt │ │ ├── HistogramBucketExemplarReservoirTest.kt │ │ └── mock │ │ │ └── AttributesProcessorMock.kt │ │ ├── export │ │ └── PeriodicMetricReaderTest.kt │ │ ├── internal │ │ ├── aggregator │ │ │ ├── AggregatorHandleTest.kt │ │ │ ├── CountAggregatorTest.kt │ │ │ ├── DoubleExponentialHistogramAggregatorTest.kt │ │ │ ├── DoubleExponentialHistogramBucketsTest.kt │ │ │ ├── DoubleHistogramAggregatorTest.kt │ │ │ ├── DoubleLastValueAggregatorTest.kt │ │ │ ├── DoubleMinMaxSumCountAggregatorTest.kt │ │ │ ├── DoubleSumAggregatorTest.kt │ │ │ ├── LongLastValueAggregatorTest.kt │ │ │ ├── LongMinMaxSumCountAggregatorTest.kt │ │ │ ├── LongSumAggregatorTest.kt │ │ │ └── MinMaxSumCountAccumulationTest.kt │ │ ├── debug │ │ │ ├── DebugConfigTest.kt │ │ │ └── SourceInfoTest.kt │ │ ├── descriptor │ │ │ └── MetricDescriptorTest.kt │ │ ├── export │ │ │ └── TestCollectionHandle.kt │ │ ├── state │ │ │ ├── AsynchronousMetricStorageTest.kt │ │ │ ├── DeltaAccumulationTest.kt │ │ │ ├── DeltaMetricStorageTest.kt │ │ │ ├── MetricStorageRegistryTest.kt │ │ │ ├── MetricStorageUtilsTest.kt │ │ │ ├── SynchronousMetricStorageTest.kt │ │ │ ├── TemporalMetricStorageTest.kt │ │ │ └── TemporalityUtilsTest.kt │ │ └── view │ │ │ ├── AttributesProcessorTest.kt │ │ │ ├── ExplicitBucketHistogramTest.kt │ │ │ └── ViewRegistryTest.kt │ │ ├── mock │ │ ├── ExemplarReservoirMock.kt │ │ └── MetricReaderMock.kt │ │ ├── testing │ │ ├── InMemoryMetricExporterTest.kt │ │ ├── InMemoryMetricReaderCumulativeTest.kt │ │ └── InMemoryMetricReaderDeltaTest.kt │ │ └── view │ │ ├── AggregationTest.kt │ │ └── MeterSelectorTest.kt ├── sdk-testing │ ├── build.gradle.kts │ └── src │ │ └── commonMain │ │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── kotlin │ │ └── sdk │ │ └── testing │ │ ├── time │ │ └── TestClock.kt │ │ └── trace │ │ └── TestSpanData.kt └── sdk-trace │ ├── build.gradle.kts │ └── src │ ├── commonMain │ └── kotlin │ │ └── io │ │ └── opentelemetry │ │ └── kotlin │ │ └── sdk │ │ └── trace │ │ ├── AnchoredClock.kt │ │ ├── AttributeUtil.kt │ │ ├── AttributesMap.kt │ │ ├── IdGenerator.kt │ │ ├── MultiSpanProcessor.kt │ │ ├── NoopSpanProcessor.kt │ │ ├── RandomIdGenerator.kt │ │ ├── ReadWriteSpan.kt │ │ ├── ReadableSpan.kt │ │ ├── RecordEventsReadableSpan.kt │ │ ├── SdkSpanBuilder.kt │ │ ├── SdkTracer.kt │ │ ├── SdkTracerBuilder.kt │ │ ├── SdkTracerProvider.kt │ │ ├── SdkTracerProviderBuilder.kt │ │ ├── SpanLimits.kt │ │ ├── SpanLimitsBuilder.kt │ │ ├── SpanProcessor.kt │ │ ├── SpanWrapper.kt │ │ ├── TracerSharedState.kt │ │ ├── data │ │ ├── DelegatingSpanData.kt │ │ ├── EventData.kt │ │ ├── ImmutableEventData.kt │ │ ├── ImmutableLinkData.kt │ │ ├── ImmutableStatusData.kt │ │ ├── LinkData.kt │ │ ├── SpanData.kt │ │ └── StatusData.kt │ │ ├── export │ │ ├── BatchSpanProcessor.kt │ │ ├── BatchSpanProcessorBuilder.kt │ │ ├── MultiSpanExporter.kt │ │ ├── NoopSpanExporter.kt │ │ ├── SimpleSpanProcessor.kt │ │ └── SpanExporter.kt │ │ └── samplers │ │ ├── AlwaysOffSampler.kt │ │ ├── AlwaysOnSampler.kt │ │ ├── ImmutableSamplingResult.kt │ │ ├── ParentBasedSampler.kt │ │ ├── ParentBasedSamplerBuilder.kt │ │ ├── Sampler.kt │ │ ├── SamplingDecision.kt │ │ ├── SamplingResult.kt │ │ └── TraceIdRatioBasedSampler.kt │ └── commonTest │ └── kotlin │ └── io │ └── opentelemetry │ └── kotlin │ └── sdk │ └── trace │ ├── AnchoredClockTest.kt │ ├── AttributesMapTest.kt │ ├── MockFactory.kt │ ├── MultiSpanProcessorTest.kt │ ├── NoopSpanProcessorTest.kt │ ├── RandomIdGeneratorTest.kt │ ├── RecordEventsReadableSpanTest.kt │ ├── SdkSpanBuilderTest.kt │ ├── SdkTracerProviderTest.kt │ ├── SdkTracerTest.kt │ ├── StressTestRunner.kt │ └── TestUtils.kt ├── semconv ├── build.gradle.kts └── src │ └── commonMain │ └── kotlin │ └── io │ └── opentelemetry │ └── kotlin │ └── semconv │ ├── resource │ └── attributes │ │ └── ResourceAttributes.kt │ └── trace │ └── attributes │ └── SemanticAttributes.kt └── settings.gradle.kts /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "gradle" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | assignees: 13 | - "JochenGuckSnk" 14 | - "rbrogatzki" 15 | open-pull-requests-limit: 5 16 | 17 | - package-ecosystem: "github-actions" 18 | directory: "/" 19 | schedule: 20 | interval: "daily" 21 | assignees: 22 | - "JochenGuckSnk" 23 | - "rbrogatzki" 24 | -------------------------------------------------------------------------------- /.github/workflows/auto-update.yml: -------------------------------------------------------------------------------- 1 | name: autoupdate 2 | on: 3 | # This will trigger on all pushes to all branches. 4 | push: {} 5 | # Alternatively, you can only trigger if commits are pushed to certain branches, e.g.: 6 | # push: 7 | # branches: 8 | # - master 9 | # - unstable 10 | jobs: 11 | autoupdate: 12 | name: autoupdate 13 | runs-on: ubuntu-20.04 14 | steps: 15 | - uses: docker://chinthakagodawita/autoupdate-action:v1 16 | env: 17 | GITHUB_TOKEN: '${{ secrets.DCXP_DEPENDABOT_PAT }}' 18 | PR_READY_STATE: "ready_for_review" 19 | # TODO create pat to enable auto update and trigger workflows 20 | # https://github.community/t/triggering-a-new-workflow-from-another-workflow/16250 21 | -------------------------------------------------------------------------------- /.github/workflows/context.yml: -------------------------------------------------------------------------------- 1 | on: push 2 | name: Workflow Context 3 | jobs: 4 | context-debug: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Dump GitHub context 8 | env: 9 | GITHUB_CONTEXT: ${{ toJSON(github) }} 10 | run: echo "$GITHUB_CONTEXT" 11 | - name: Dump job context 12 | env: 13 | JOB_CONTEXT: ${{ toJSON(job) }} 14 | run: echo "$JOB_CONTEXT" 15 | - name: Dump steps context 16 | env: 17 | STEPS_CONTEXT: ${{ toJSON(steps) }} 18 | run: echo "$STEPS_CONTEXT" 19 | - name: Dump runner context 20 | env: 21 | RUNNER_CONTEXT: ${{ toJSON(runner) }} 22 | run: echo "$RUNNER_CONTEXT" 23 | - name: Dump strategy context 24 | env: 25 | STRATEGY_CONTEXT: ${{ toJSON(strategy) }} 26 | run: echo "$STRATEGY_CONTEXT" 27 | - name: Dump matrix context 28 | env: 29 | MATRIX_CONTEXT: ${{ toJSON(matrix) }} 30 | run: echo "$MATRIX_CONTEXT" 31 | -------------------------------------------------------------------------------- /.github/workflows/dependadbot-auto-merge.yml: -------------------------------------------------------------------------------- 1 | name: Enable Auto Merge 2 | on: 3 | pull_request_target: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | auto-merge: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Approve dependabot PRs 12 | uses: ahmadnassri/action-dependabot-auto-merge@v2.6.6 13 | with: 14 | target: minor # includes patch updates! 15 | github-token: ${{ secrets.DCXP_DEPENDABOT_PAT }} 16 | - name: Enable automerge on dependabot PRs 17 | uses: daneden/enable-automerge-action@v1 18 | with: 19 | github-token: ${{ secrets.DCXP_DEPENDABOT_PAT }} 20 | allowed-author: "dependabot[bot]" 21 | merge-method: SQUASH 22 | -------------------------------------------------------------------------------- /.github/workflows/update-gradle-wrapper.yml: -------------------------------------------------------------------------------- 1 | name: Update Gradle Wrapper 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "0 0 * * *" 7 | 8 | jobs: 9 | update-gradle-wrapper: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | pull-requests: write 13 | steps: 14 | - uses: actions/checkout@v4.1.2 15 | 16 | - name: Make gradlew executable 17 | run: chmod +x ./gradlew 18 | - name: Update Gradle Wrapper 19 | uses: gradle-update/update-gradle-wrapper-action@v1.0.20 20 | with: 21 | target-branch: update-gradle 22 | repo-token: ${{ secrets.DCXP_DEPENDABOT_PAT }} 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle 2 | build 3 | .gradle 4 | local.properties 5 | out/ 6 | 7 | # Maven (proto) 8 | target 9 | 10 | # IntelliJ IDEA 11 | .idea 12 | *.iml 13 | 14 | # Eclipse 15 | .classpath 16 | .project 17 | .settings 18 | bin 19 | 20 | # NetBeans 21 | /.nb-gradle 22 | /.nb-gradle-properties 23 | 24 | # VS Code 25 | .vscode 26 | 27 | # OS X 28 | .DS_Store 29 | 30 | # Emacs 31 | *~ 32 | \#*\# 33 | 34 | # Vim 35 | .swp 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Opentelemetry - Kotlin 2 | 3 | This repository contains a port of [Opentelemetry-Java](https://github.com/open-telemetry/opentelemetry-java) in to Kotlin Multiplatform 4 | 5 | It contains ports for: 6 | - The Tracing Api/SDK 7 | - The Metrics Api/SDK 8 | 9 | Working on JVM, JS and native (windows, mac, linux) 10 | 11 | Most unit tests are also ported. 12 | 13 | ## Installation 14 | 15 | To use the library, add the following to your `build.gradle.kts` file: 16 | ```kotlin 17 | repositories { 18 | maven(url = "https://maven.pkg.github.com/dcxp/opentelemetry-kotlin") 19 | } 20 | 21 | dependencies { 22 | implementation("io.opentelemetry.kotlin.api:all:VERSION") 23 | implementation("io.opentelemetry.kotlin.api:metrics:VERSION") 24 | implementation("io.opentelemetry.kotlin.sdk:sdk-metrics:VERSION") 25 | implementation("io.opentelemetry.kotlin.sdk:sdk-trace:VERSION") 26 | } 27 | ``` 28 | 29 | 30 | 31 | Ported by [SNK](https://www.snk.de/en/) 32 | 33 | -------------------------------------------------------------------------------- /api/all/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("mpplib") 3 | } 4 | 5 | kotlin { 6 | sourceSets { 7 | val commonMain by getting { 8 | dependencies { 9 | api(project(":context")) 10 | } 11 | } 12 | val commonTest by getting { 13 | dependencies { 14 | implementation(libs.bundles.kotlin.test) 15 | 16 | implementation(libs.jetbrains.kotlinx.coroutines.core) 17 | 18 | implementation(libs.kotest.assertions.core) 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/DefaultOpenTelemetry.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api 6 | 7 | import io.opentelemetry.kotlin.api.trace.TracerProvider 8 | import io.opentelemetry.kotlin.context.propagation.ContextPropagators 9 | 10 | /** 11 | * The default OpenTelemetry API, which tries to find API implementations via SPI or otherwise falls 12 | * back to no-op default implementations. 13 | */ 14 | class DefaultOpenTelemetry(override val propagators: ContextPropagators) : OpenTelemetry { 15 | 16 | override val tracerProvider: TracerProvider 17 | get() = TracerProvider.noop() 18 | 19 | companion object { 20 | private val NO_OP: OpenTelemetry = DefaultOpenTelemetry(ContextPropagators.noop()) 21 | val noop: OpenTelemetry 22 | get() = NO_OP 23 | 24 | fun getPropagating(propagators: ContextPropagators): OpenTelemetry { 25 | return DefaultOpenTelemetry(propagators) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/baggage/BaggageBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.baggage 6 | 7 | /** 8 | * A builder of [Baggage]. 9 | * 10 | * @see Baggage.builder 11 | */ 12 | interface BaggageBuilder { 13 | /** 14 | * Adds the key/value pair and metadata regardless of whether the key is present. 15 | * 16 | * @param key the `String` key which will be set. 17 | * @param value the `String` value to set for the given key. 18 | * @param entryMetadata the `BaggageEntryMetadata` metadata to set for the given key. 19 | * @return this 20 | */ 21 | /** 22 | * Adds the key/value pair with empty metadata regardless of whether the key is present. 23 | * 24 | * @param key the `String` key which will be set. 25 | * @param value the `String` value to set for the given key. 26 | * @return this 27 | */ 28 | fun put( 29 | key: String, 30 | value: String, 31 | entryMetadata: BaggageEntryMetadata = BaggageEntryMetadata.empty() 32 | ): BaggageBuilder 33 | 34 | /** 35 | * Removes the key if it exists. 36 | * 37 | * @param key the `String` key which will be removed. 38 | * @return this 39 | */ 40 | fun remove(key: String?): BaggageBuilder 41 | 42 | /** 43 | * Creates a `Baggage` from this builder. 44 | * 45 | * @return a `Baggage` with the same entries as this builder. 46 | */ 47 | fun build(): Baggage 48 | } 49 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/baggage/BaggageContextKey.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.baggage 6 | 7 | import io.opentelemetry.kotlin.context.ContextKey 8 | 9 | /** Util class to hold on to the key for storing Baggage in the Context. */ 10 | internal object BaggageContextKey { 11 | val KEY: ContextKey = ContextKey.named("opentelemetry-baggage-key") 12 | } 13 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/baggage/BaggageEntry.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.baggage 6 | 7 | /** An entry in a set of baggage. */ 8 | interface BaggageEntry { 9 | /** Returns the entry's value. */ 10 | val value: String 11 | 12 | /** Returns the entry's [BaggageEntryMetadata]. */ 13 | val metadata: BaggageEntryMetadata 14 | } 15 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/baggage/BaggageEntryMetadata.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.baggage 6 | /** 7 | * Metadata associated with an [BaggageEntry]. For the moment this is an opaque wrapper for a String 8 | * metadata value. 9 | */ 10 | interface BaggageEntryMetadata { 11 | /** Returns the String value of this [BaggageEntryMetadata]. */ 12 | val value: String 13 | 14 | companion object { 15 | /** Returns an empty [BaggageEntryMetadata]. */ 16 | fun empty(): BaggageEntryMetadata { 17 | return ImmutableEntryMetadata.EMPTY 18 | } 19 | 20 | /** Returns a new [BaggageEntryMetadata] with the given value. */ 21 | fun create(metadata: String): BaggageEntryMetadata { 22 | return ImmutableEntryMetadata.create(metadata) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/baggage/ImmutableEntry.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.baggage 6 | 7 | /** String-String key-value pair, along with [ImmutableEntryMetadata]. */ 8 | internal class ImmutableEntry( 9 | override val value: String, 10 | override val metadata: BaggageEntryMetadata 11 | ) : BaggageEntry { 12 | companion object { 13 | /** 14 | * Creates an `Entry` from the given key, value and metadata. 15 | * 16 | * @param value the entry value. 17 | * @param entryMetadata the entry metadata. 18 | * @return a `Entry`. 19 | */ 20 | fun create(value: String, entryMetadata: BaggageEntryMetadata): ImmutableEntry { 21 | return ImmutableEntry(value, entryMetadata) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/baggage/ImmutableEntryMetadata.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.baggage 6 | 7 | internal interface ImmutableEntryMetadata : BaggageEntryMetadata { 8 | /** 9 | * Returns the String value of this [ImmutableEntryMetadata]. 10 | * 11 | * @return the raw metadata value. 12 | */ 13 | override val value: String 14 | 15 | companion object { 16 | /** Returns an empty metadata. */ 17 | val EMPTY = create("") 18 | 19 | /** 20 | * Creates an [ImmutableEntryMetadata] with the given value. 21 | * 22 | * @param metadata TTL of an `Entry`. 23 | * @return an `EntryMetadata`. 24 | */ 25 | fun create(metadata: String?): ImmutableEntryMetadata { 26 | return metadata?.let { Implementation(it) } ?: EMPTY 27 | } 28 | 29 | class Implementation(override val value: String) : ImmutableEntryMetadata 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/common/AttributeType.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.common 6 | 7 | /** 8 | * An enum that represents all the possible value types for an `AttributeKey` and hence the types of 9 | * values that are allowed for [Attributes]. 10 | */ 11 | enum class AttributeType { 12 | STRING, 13 | BOOLEAN, 14 | LONG, 15 | DOUBLE, 16 | STRING_ARRAY, 17 | BOOLEAN_ARRAY, 18 | LONG_ARRAY, 19 | DOUBLE_ARRAY 20 | } 21 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/common/DateTimeUnit.ext.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin.api.common 2 | 3 | import kotlinx.datetime.DateTimeUnit 4 | 5 | fun DateTimeUnit.getNanos(): Long { 6 | return when (this) { 7 | is DateTimeUnit.TimeBased -> nanoseconds 8 | is DateTimeUnit.DayBased -> DateTimeUnit.HOUR.nanoseconds * 24 * days 9 | is DateTimeUnit.MonthBased -> 10 | throw IllegalStateException("Month based DateTimeUnits can not be converted to nanos") 11 | } 12 | } 13 | 14 | fun DateTimeUnit.normalizeToNanos(timestamp: Long): Long { 15 | return this.getNanos() * timestamp 16 | } 17 | 18 | fun DateTimeUnit.normalizeToNanos(timestamp: Int): Long { 19 | return this.getNanos() * timestamp 20 | } 21 | 22 | fun DateTimeUnit.normalizeToMilliseconds(timestamp: Int): Long { 23 | return normalizeToNanos(timestamp) / 1000 24 | } 25 | 26 | fun DateTimeUnit.normalizeToMilliseconds(timestamp: Long): Long { 27 | return normalizeToNanos(timestamp) / 1000 28 | } 29 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/common/Instant.ext.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin.api.common 2 | 3 | import kotlinx.datetime.DateTimeUnit 4 | import kotlinx.datetime.Instant 5 | 6 | fun Instant.getNanoseconds(): Long { 7 | return (DateTimeUnit.SECOND.nanoseconds * this.epochSeconds) + this.nanosecondsOfSecond 8 | } 9 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/internal/TemporaryBuffers.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.internal 6 | 7 | /** 8 | * [ThreadLocal] buffers for use when creating new derived objects such as [String]s. These buffers 9 | * are reused within a single thread - it is _not safe_ to use the buffer to generate multiple 10 | * derived objects at the same time because the same memory will be used. In general, you should get 11 | * a temporary buffer, fill it with data, and finish by converting into the derived object within 12 | * the same method to avoid multiple usages of the same buffer. 13 | * 14 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 15 | * any time. 16 | */ 17 | object TemporaryBuffers { 18 | // private val CHAR_ARRAY: ThreadLocal = ThreadLocal() 19 | 20 | /** 21 | * A [ThreadLocal] `char[]` of size `len`. Take care when using a large value of `len` as this 22 | * buffer will remain for the lifetime of the thread. The returned buffer will not be zeroed and 23 | * may be larger than the requested size, you must make sure to fill the entire content to the 24 | * desired value and set the length explicitly when converting to a [String]. 25 | */ 26 | fun chars(len: Int): CharArray { 27 | return CharArray(len) 28 | } 29 | 30 | // Visible for testing 31 | fun clearChars() {} 32 | } 33 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundDoubleCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** A counter instrument that records `double` values with pre-associated attributes. */ 10 | interface BoundDoubleCounter { 11 | /** 12 | * Records a value with pre-bound attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The increment amount. MUST be non-negative. 17 | */ 18 | fun add(value: Double) 19 | 20 | /** 21 | * Records a value with pre-bound attributes. 22 | * 23 | * @param value The increment amount. MUST be non-negative. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun add(value: Double, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [DoubleCounter]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundDoubleHistogram.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** A histogram instrument that records `long` values with pre-associated attributes. */ 10 | interface BoundDoubleHistogram { 11 | /** 12 | * Records a value with a pre-bound set of attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The amount of the measurement. 17 | */ 18 | fun record(value: Double) 19 | 20 | /** 21 | * Records a value with a pre-bound set of attributes. 22 | * 23 | * @param value The amount of the measurement. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun record(value: Double, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [DoubleHistogram]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundDoubleUpDownCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** An up-down-counter instrument with pre-bound attributes. */ 10 | interface BoundDoubleUpDownCounter { 11 | /** 12 | * Records a value with pre-bound attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The increment amount. May be positive, negative or zero. 17 | */ 18 | fun add(value: Double) 19 | 20 | /** 21 | * Records a value with a pre-bound attributes. 22 | * 23 | * @param value The increment amount. May be positive, negative or zero. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun add(value: Double, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [DoubleUpDownCounter]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundLongCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** A counter instrument that records `long` values with pre-associated attributes. */ 10 | interface BoundLongCounter { 11 | /** 12 | * Records a value with pre-bound attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The increment amount. MUST be non-negative. 17 | */ 18 | fun add(value: Long) 19 | 20 | /** 21 | * Records a value with pre-bound attributes. 22 | * 23 | * @param value The increment amount. MUST be non-negative. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun add(value: Long, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [LongCounter]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundLongHistogram.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** A histogram instrument that records `long` values with pre-associated attributes. */ 10 | interface BoundLongHistogram { 11 | /** 12 | * Records a value with a pre-bound set of attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The amount of the measurement. 17 | */ 18 | fun record(value: Long) 19 | 20 | /** 21 | * Records a value with a pre-bound set of attributes. 22 | * 23 | * @param value The amount of the measurement. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun record(value: Long, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [LongHistogram]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundLongUpDownCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** An up-down-counter instrument with pre-bound attributes. */ 10 | interface BoundLongUpDownCounter { 11 | /** 12 | * Records a value with pre-bound attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The increment amount. May be positive, negative or zero. 17 | */ 18 | fun add(value: Long) 19 | 20 | /** 21 | * Records a value with a pre-bound attributes. 22 | * 23 | * @param value The increment amount. May be positive, negative or zero. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun add(value: Long, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [LongUpDownCounter]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/DoubleCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | /** A counter instrument that records `double` values. */ 11 | interface DoubleCounter { 12 | /** 13 | * Records a value. 14 | * 15 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 16 | * 17 | * @param value The increment amount. MUST be non-negative. 18 | */ 19 | fun add(value: Double) 20 | 21 | /** 22 | * Records a value with a set of attributes. 23 | * 24 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 25 | * 26 | * @param value The increment amount. MUST be non-negative. 27 | * @param attributes A set of attributes to associate with the count. 28 | */ 29 | fun add(value: Double, attributes: Attributes) 30 | 31 | /** 32 | * Records a value with a set of attributes. 33 | * 34 | * @param value The increment amount. MUST be non-negative. 35 | * @param attributes A set of attributes to associate with the count. 36 | * @param context The explicit context to associate with this measurement. 37 | */ 38 | fun add(value: Double, attributes: Attributes, context: Context) 39 | 40 | /** 41 | * Constructs a bound version of this instrument where all recorded values use the given 42 | * attributes. 43 | */ 44 | fun bind(attributes: Attributes): BoundDoubleCounter 45 | } 46 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/DoubleCounterBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** Builder class for [DoubleCounter]. */ 8 | interface DoubleCounterBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): DoubleCounterBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): DoubleCounterBuilder 24 | 25 | /** Sets the counter for recording `long` values. */ 26 | fun ofLongs(): LongCounterBuilder 27 | 28 | /** 29 | * Builds and returns a `DoubleCounter` with the desired options. 30 | * 31 | * @return a `DoubleCounter` with the desired options. 32 | */ 33 | fun build(): DoubleCounter 34 | 35 | /** 36 | * Builds this asynchronous instrument with the given callback. 37 | * 38 | * The callback will only be called when the [Meter] is being observed. 39 | * 40 | * @param callback A state-capturing callback used to observe values on-demand. 41 | */ 42 | fun buildWithCallback(callback: (ObservableDoubleMeasurement) -> Unit) 43 | } 44 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/DoubleGaugeBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** A builder for Gauge metric types. These can only be asynchronously collected. */ 8 | interface DoubleGaugeBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): DoubleGaugeBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): DoubleGaugeBuilder 24 | 25 | /** Sets the gauge for recording `long` values. */ 26 | fun ofLongs(): LongGaugeBuilder 27 | 28 | /** 29 | * Builds this asynchronous instrument with the given callback. 30 | * 31 | * The callback will only be called when the [Meter] is being observed. 32 | * 33 | * @param callback A state-capturing callback used to observe values on-demand. 34 | */ 35 | fun buildWithCallback(callback: (ObservableDoubleMeasurement) -> Unit) 36 | } 37 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/DoubleHistogram.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | /** A histogram instrument that records `long` values. */ 11 | interface DoubleHistogram { 12 | /** 13 | * Records a value. 14 | * 15 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 16 | * 17 | * @param value The amount of the measurement. 18 | */ 19 | fun record(value: Double) 20 | 21 | /** 22 | * Records a value with a set of attributes. 23 | * 24 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 25 | * 26 | * @param value The amount of the measurement. 27 | * @param attributes A set of attributes to associate with the count. 28 | */ 29 | fun record(value: Double, attributes: Attributes) 30 | 31 | /** 32 | * Records a value with a set of attributes. 33 | * 34 | * @param value The amount of the measurement. 35 | * @param attributes A set of attributes to associate with the count. 36 | * @param context The explicit context to associate with this measurement. 37 | */ 38 | fun record(value: Double, attributes: Attributes, context: Context) 39 | 40 | /** 41 | * Constructs a bound version of this instrument where all recorded values use the given 42 | * attributes. 43 | */ 44 | fun bind(attributes: Attributes): BoundDoubleHistogram 45 | } 46 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/DoubleHistogramBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** Builder class for [DoubleHistogram]. */ 8 | interface DoubleHistogramBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): DoubleHistogramBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): DoubleHistogramBuilder 24 | 25 | /** Sets the counter for recording `long` values. */ 26 | fun ofLongs(): LongHistogramBuilder 27 | 28 | /** 29 | * Builds and returns a `DoubleHistogram` with the desired options. 30 | * 31 | * @return a `DoubleHistogram` with the desired options. 32 | */ 33 | fun build(): DoubleHistogram 34 | } 35 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/GlobalMeterProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.metrics.internal.NoopMeterProvider 8 | import kotlinx.atomicfu.atomic 9 | 10 | /** This class is a temporary solution until metrics SDK is marked stable. */ 11 | object GlobalMeterProvider { 12 | private val globalMeterProvider = atomic(NoopMeterProvider.instance) 13 | 14 | /** Returns the globally registered [MeterProvider]. */ 15 | fun get(): MeterProvider { 16 | return globalMeterProvider.value 17 | } 18 | 19 | /** 20 | * Sets the [MeterProvider] that should be the global instance. Future calls to [ ][.get] will 21 | * return the provided [MeterProvider] instance. This should be called once as early as possible 22 | * in your application initialization logic, often in a `static` block in your main class. 23 | */ 24 | fun set(provider: MeterProvider) { 25 | globalMeterProvider.lazySet(provider) 26 | } 27 | 28 | fun disableGlobalMeterProvider() { 29 | globalMeterProvider.lazySet(NoopMeterProvider.instance) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/LongCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | /** A counter instrument that records `long` values. */ 11 | interface LongCounter { 12 | /** 13 | * Records a value. 14 | * 15 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 16 | * 17 | * @param value The increment amount. MUST be non-negative. 18 | */ 19 | fun add(value: Long) 20 | 21 | /** 22 | * Records a value with a set of attributes. 23 | * 24 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 25 | * 26 | * @param value The increment amount. MUST be non-negative. 27 | * @param attributes A set of attributes to associate with the count. 28 | */ 29 | fun add(value: Long, attributes: Attributes) 30 | 31 | /** 32 | * Records a value with a set of attributes. 33 | * 34 | * @param value The increment amount. MUST be non-negative. 35 | * @param attributes A set of attributes to associate with the count. 36 | * @param context The explicit context to associate with this measurement. 37 | */ 38 | fun add(value: Long, attributes: Attributes, context: Context) 39 | 40 | /** 41 | * Constructs a bound version of this instrument where all recorded values use the given 42 | * attributes. 43 | */ 44 | fun bind(attributes: Attributes): BoundLongCounter 45 | } 46 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/LongCounterBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** Builder class for [LongCounter]. */ 8 | interface LongCounterBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): LongCounterBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): LongCounterBuilder 24 | 25 | /** Sets the counter for recording `double` values. */ 26 | fun ofDoubles(): DoubleCounterBuilder 27 | 28 | /** 29 | * Builds and returns a `LongCounter` with the desired options. 30 | * 31 | * @return a `LongCounter` with the desired options. 32 | */ 33 | fun build(): LongCounter 34 | 35 | /** 36 | * Builds this asynchronous instrument with the given callback. 37 | * 38 | * The callback will only be called when the [Meter] is being observed. 39 | * 40 | * @param callback A state-capturing callback used to observe values on-demand. 41 | */ 42 | fun buildWithCallback(callback: (ObservableLongMeasurement) -> Unit) 43 | } 44 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/LongGaugeBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** A builder for Gauge metric types. These can only be asynchronously collected. */ 8 | interface LongGaugeBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): LongGaugeBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): LongGaugeBuilder 24 | 25 | /** Sets the gauge for recording `double` values. */ 26 | fun ofDoubles(): DoubleGaugeBuilder 27 | 28 | /** 29 | * Builds this asynchronous instrument with the given callback. 30 | * 31 | * The callback will only be called when the [Meter] is being observed. 32 | * 33 | * @param callback A state-capturing callback used to observe values on-demand. 34 | */ 35 | fun buildWithCallback(callback: (ObservableLongMeasurement) -> Unit) 36 | } 37 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/LongHistogram.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | /** A histogram instrument that records `long` values. */ 11 | interface LongHistogram { 12 | /** 13 | * Records a value. 14 | * 15 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 16 | * 17 | * @param value The amount of the measurement. 18 | */ 19 | fun record(value: Long) 20 | 21 | /** 22 | * Records a value with a set of attributes. 23 | * 24 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 25 | * 26 | * @param value The amount of the measurement. 27 | * @param attributes A set of attributes to associate with the count. 28 | */ 29 | fun record(value: Long, attributes: Attributes) 30 | 31 | /** 32 | * Records a value with a set of attributes. 33 | * 34 | * @param value The amount of the measurement. 35 | * @param attributes A set of attributes to associate with the count. 36 | * @param context The explicit context to associate with this measurement. 37 | */ 38 | fun record(value: Long, attributes: Attributes, context: Context) 39 | 40 | /** 41 | * Construct a bound version of this instrument where all recorded values use the given 42 | * attributes. 43 | */ 44 | fun bind(attributes: Attributes): BoundLongHistogram 45 | } 46 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/LongHistogramBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** Builder class for [LongHistogram]. */ 8 | interface LongHistogramBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): LongHistogramBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): LongHistogramBuilder 24 | 25 | /** Sets the histogram for recording `double` values. */ 26 | fun ofDoubles(): DoubleHistogramBuilder 27 | 28 | /** 29 | * Builds and returns a `LongHistogram` with the desired options. 30 | * 31 | * @return a `LongHistogram` with the desired options. 32 | */ 33 | fun build(): LongHistogram 34 | } 35 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/MeterBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** 8 | * Builder class for creating [Meter] instances. 9 | * 10 | * @since 1.4.0 11 | */ 12 | interface MeterBuilder { 13 | /** 14 | * Assigns an OpenTelemetry schema URL to the resulting Meter. 15 | * 16 | * @param schemaUrl The URL of the OpenTelemetry schema being used by this instrumentation 17 | * library. 18 | * @return this 19 | */ 20 | fun setSchemaUrl(schemaUrl: String): MeterBuilder 21 | 22 | /** 23 | * Assigns a version to the instrumentation library that is using the resulting Meter. 24 | * 25 | * @param instrumentationVersion The version of the instrumentation library. 26 | * @return this 27 | */ 28 | fun setInstrumentationVersion(instrumentationVersion: String): MeterBuilder 29 | 30 | /** 31 | * Gets or creates a [Meter] instance. 32 | * 33 | * @return a [Meter] instance configured with the provided options. 34 | */ 35 | fun build(): io.opentelemetry.kotlin.api.metrics.Meter 36 | } 37 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/MeterProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.metrics.internal.NoopMeterProvider 8 | 9 | /** 10 | * A registry for creating named [Meter]s. 11 | * 12 | * A MeterProvider represents a configured (or noop) Metric collection system that can be used to 13 | * instrument code. 14 | * 15 | * The name *Provider* is for consistency with other languages and it is **NOT** loaded using 16 | * reflection. 17 | * 18 | * @see io.opentelemetry.kotlin.api.metrics.Meter 19 | */ 20 | interface MeterProvider { 21 | /** 22 | * Gets or creates a named and versioned meter instance. 23 | * 24 | * @param instrumentationName The name of the instrumentation library, not the name of the 25 | * instrument*ed* library. 26 | * @return a meter instance. 27 | */ 28 | operator fun get(instrumentationName: String): Meter { 29 | return meterBuilder(instrumentationName).build() 30 | } 31 | 32 | /** 33 | * Creates a MeterBuilder for a named meter instance. 34 | * 35 | * @param instrumentationName The name of the instrumentation library, not the name of the 36 | * instrument*ed* library. 37 | * @return a MeterBuilder instance. 38 | * @since 1.4.0 39 | */ 40 | fun meterBuilder(instrumentationName: String): MeterBuilder 41 | 42 | companion object { 43 | /** Returns a no-op [MeterProvider] which provides meters which do not record or emit. */ 44 | fun noop(): MeterProvider { 45 | return NoopMeterProvider.instance 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/ObservableDoubleMeasurement.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | 9 | /** An interface for observing measurements with `double` values. */ 10 | interface ObservableDoubleMeasurement : ObservableMeasurement { 11 | /** 12 | * Records a measurement. 13 | * 14 | * @param value The measurement amount. MUST be non-negative. 15 | */ 16 | fun observe(value: Double) 17 | 18 | /** 19 | * Records a measurement with a set of attributes. 20 | * 21 | * @param value The measurement amount. MUST be non-negative. 22 | * @param attributes A set of attributes to associate with the count. 23 | */ 24 | fun observe(value: Double, attributes: Attributes) 25 | } 26 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/ObservableLongMeasurement.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | 9 | /** An interface for observing measurements with `long` values. */ 10 | interface ObservableLongMeasurement : ObservableMeasurement { 11 | /** 12 | * Records a measurement. 13 | * 14 | * @param value The measurement amount. MUST be non-negative. 15 | */ 16 | fun observe(value: Long) 17 | 18 | /** 19 | * Records a measurement with a set of attributes. 20 | * 21 | * @param value The measurement amount. MUST be non-negative. 22 | * @param attributes A set of attributes to associate with the count. 23 | */ 24 | fun observe(value: Long, attributes: Attributes) 25 | } 26 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/ObservableMeasurement.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** 8 | * A mechanism for observing measurments. 9 | * 10 | * see [ObservableDoubleMeasurement] or [ObservableLongMeasurement]. 11 | */ 12 | interface ObservableMeasurement 13 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/internal/NoopMeterProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics.internal 6 | 7 | import io.opentelemetry.kotlin.api.metrics.Meter 8 | import io.opentelemetry.kotlin.api.metrics.MeterBuilder 9 | import io.opentelemetry.kotlin.api.metrics.MeterProvider 10 | 11 | /** A [MeterProvider] that does nothing. */ 12 | class NoopMeterProvider private constructor() : MeterProvider { 13 | override fun meterBuilder(instrumentationName: String): MeterBuilder { 14 | return BUILDER_INSTANCE 15 | } 16 | 17 | private class NoopMeterBuilder : MeterBuilder { 18 | override fun setSchemaUrl(schemaUrl: String): MeterBuilder { 19 | return this 20 | } 21 | 22 | override fun setInstrumentationVersion(instrumentationVersion: String): MeterBuilder { 23 | return this 24 | } 25 | 26 | override fun build(): Meter { 27 | return NoopMeter.instance 28 | } 29 | } 30 | 31 | companion object { 32 | private val INSTANCE = NoopMeterProvider() 33 | private val BUILDER_INSTANCE: MeterBuilder = NoopMeterBuilder() 34 | val instance: MeterProvider 35 | get() = INSTANCE 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/trace/DefaultTracerBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.trace 6 | 7 | internal class DefaultTracerBuilder : TracerBuilder { 8 | override fun setSchemaUrl(schemaUrl: String?): TracerBuilder { 9 | return this 10 | } 11 | 12 | override fun setInstrumentationVersion(instrumentationVersion: String?): TracerBuilder { 13 | return this 14 | } 15 | 16 | override fun build(): Tracer { 17 | return DefaultTracer.instance 18 | } 19 | 20 | companion object { 21 | private val INSTANCE = DefaultTracerBuilder() 22 | 23 | val instance: TracerBuilder 24 | get() = INSTANCE 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/trace/DefaultTracerProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.trace 6 | 7 | internal class DefaultTracerProvider private constructor() : TracerProvider { 8 | override operator fun get(instrumentationName: String): Tracer { 9 | return DefaultTracer.instance 10 | } 11 | 12 | override operator fun get(instrumentationName: String, instrumentationVersion: String): Tracer { 13 | return DefaultTracer.instance 14 | } 15 | 16 | companion object { 17 | private val INSTANCE: TracerProvider = DefaultTracerProvider() 18 | val instance: TracerProvider 19 | get() = INSTANCE 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/trace/SpanContextKey.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.trace 6 | 7 | import io.opentelemetry.kotlin.context.ContextKey 8 | 9 | /** Util class to hold on to the key for storing a Span in the Context. */ 10 | internal object SpanContextKey { 11 | val KEY: ContextKey = ContextKey.named("opentelemetry-trace-span-key") 12 | } 13 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/trace/SpanKind.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.trace 6 | 7 | /** 8 | * Type of [Span]. Can be used to specify additional relationships between spans in addition to a 9 | * parent/child relationship. 10 | */ 11 | enum class SpanKind { 12 | /** Default value. Indicates that the span is used internally. */ 13 | INTERNAL, 14 | 15 | /** Indicates that the span covers server-side handling of an RPC or other remote request. */ 16 | SERVER, 17 | 18 | /** 19 | * Indicates that the span covers the client-side wrapper around an RPC or other remote request. 20 | */ 21 | CLIENT, 22 | 23 | /** 24 | * Indicates that the span describes producer sending a message to a broker. Unlike client and 25 | * server, there is no direct critical path latency relationship between producer and consumer 26 | * spans. 27 | */ 28 | PRODUCER, 29 | 30 | /** 31 | * Indicates that the span describes consumer receiving a message from a broker. Unlike client 32 | * and server, there is no direct critical path latency relationship between producer and 33 | * consumer spans. 34 | */ 35 | CONSUMER 36 | } 37 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/trace/StatusCode.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.trace 6 | 7 | /** 8 | * The set of canonical status codes. If new codes are added over time they must choose a numerical 9 | * value that does not collide with any previously used value. 10 | */ 11 | enum class StatusCode { 12 | /** The default status. */ 13 | UNSET, 14 | 15 | /** 16 | * The operation has been validated by an Application developers or Operator to have completed 17 | * successfully. 18 | */ 19 | OK, 20 | 21 | /** The operation contains an error. */ 22 | ERROR 23 | } 24 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/trace/TraceStateBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.trace 6 | 7 | /** 8 | * A builder of [TraceState]. This implementation does full validation of the keys and values in the 9 | * entries, and will ignore any entries that do not conform to the W3C specification. 10 | */ 11 | interface TraceStateBuilder { 12 | /** 13 | * Adds or updates the `Entry` that has the given `key` if it is present. The new `Entry` will 14 | * always be added in the front of the list of entries. 15 | * 16 | * @param key the key for the `Entry` to be added. 17 | * @param value the value for the `Entry` to be added. 18 | * @return this. 19 | */ 20 | fun put(key: String, value: String): TraceStateBuilder 21 | 22 | /** 23 | * Removes the `Entry` that has the given `key` if it is present. 24 | * 25 | * @param key the key for the `Entry` to be removed. 26 | * @return this. 27 | */ 28 | fun remove(key: String): TraceStateBuilder 29 | 30 | /** 31 | * Builds a TraceState by adding the entries to the parent in front of the key-value pairs list 32 | * and removing duplicate entries. 33 | * 34 | * @return a TraceState with the new entries. 35 | */ 36 | fun build(): TraceState 37 | } 38 | -------------------------------------------------------------------------------- /api/all/src/commonMain/kotlin/io/opentelemetry/kotlin/api/trace/TracerBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.trace 6 | 7 | /** 8 | * Builder class for creating [Tracer] instances. 9 | * 10 | * @since 1.4.0 11 | */ 12 | interface TracerBuilder { 13 | /** 14 | * Assign an OpenTelemetry schema URL to the resulting Tracer. 15 | * 16 | * @param schemaUrl The URL of the OpenTelemetry schema being used by this instrumentation 17 | * library. 18 | * @return this 19 | */ 20 | fun setSchemaUrl(schemaUrl: String?): TracerBuilder 21 | 22 | /** 23 | * Assign a version to the instrumentation library that is using the resulting Tracer. 24 | * 25 | * @param instrumentationVersion The version of the instrumentation library. 26 | * @return this 27 | */ 28 | fun setInstrumentationVersion(instrumentationVersion: String?): TracerBuilder 29 | 30 | /** 31 | * Gets or creates a [Tracer] instance. 32 | * 33 | * @return a [Tracer] instance configured with the provided options. 34 | */ 35 | fun build(): Tracer 36 | } 37 | -------------------------------------------------------------------------------- /api/all/src/commonTest/kotlin/io/opentelemetry/kotlin/api/EqualsTester.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin.api 2 | 3 | class EqualsTester { 4 | val groups: MutableList> = mutableListOf() 5 | 6 | fun addEqualityGroup(vararg objects: Any) { 7 | groups.add(objects.toList()) 8 | } 9 | 10 | fun testEquals() { 11 | checkGroupEquality() 12 | checkInterGroupInequality() 13 | } 14 | 15 | fun checkGroupEquality() { 16 | for (group in groups) { 17 | for (element1 in group) { 18 | for (element2 in group) { 19 | require(element1 == element2) { "$element1 is not equal to $element2" } 20 | require(element1.hashCode() == element2.hashCode()) { 21 | "$element1 hashcode is not equal to $element2 hashcode" 22 | } 23 | } 24 | } 25 | } 26 | } 27 | fun checkInterGroupInequality() { 28 | for (group1 in groups) { 29 | for (group2 in groups) { 30 | if (group1 === group2) { 31 | continue 32 | } 33 | for (element1 in group1) { 34 | for (element2 in group2) { 35 | require(element1 != element2) { "$element1 is equal to $element2" } 36 | require(element1.hashCode() != element2.hashCode()) { 37 | "$element1 hashcode is equal to $element2 hashcode" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /api/all/src/commonTest/kotlin/io/opentelemetry/kotlin/api/Map.Entry.ext.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin.api 2 | 3 | /** 4 | * Creates a tuple of type [Map.Entry] from this and [that]. 5 | * 6 | * This can be useful for creating [Map] literals with less noise, for example: 7 | * @sample samples.collections.Maps.Instantiation.mapFromPairs 8 | */ 9 | infix fun A.entryTo(that: B): Map.Entry { 10 | val pair: Pair = this to that 11 | return mapOf(pair).entries.single() 12 | } 13 | -------------------------------------------------------------------------------- /api/all/src/commonTest/kotlin/io/opentelemetry/kotlin/api/common/AttributeKeyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.common 6 | 7 | import io.kotest.assertions.throwables.shouldNotThrowAny 8 | import io.opentelemetry.kotlin.api.EqualsTester 9 | import kotlin.test.Test 10 | 11 | internal class AttributeKeyTest { 12 | @Test 13 | fun equalsVerifier() { 14 | val tester = EqualsTester() 15 | tester.addEqualityGroup(AttributeKey.stringKey("test"), AttributeKey.stringKey("test")) 16 | tester.addEqualityGroup(AttributeKey.booleanKey("test"), AttributeKey.booleanKey("test")) 17 | tester.addEqualityGroup(AttributeKey.longKey("test"), AttributeKey.longKey("test")) 18 | tester.addEqualityGroup(AttributeKey.doubleKey("test"), AttributeKey.doubleKey("test")) 19 | tester.addEqualityGroup( 20 | AttributeKey.stringArrayKey("test"), 21 | AttributeKey.stringArrayKey("test") 22 | ) 23 | tester.addEqualityGroup( 24 | AttributeKey.booleanArrayKey("test"), 25 | AttributeKey.booleanArrayKey("test") 26 | ) 27 | tester.addEqualityGroup( 28 | AttributeKey.longArrayKey("test"), 29 | AttributeKey.longArrayKey("test") 30 | ) 31 | tester.addEqualityGroup( 32 | AttributeKey.doubleArrayKey("test"), 33 | AttributeKey.doubleArrayKey("test") 34 | ) 35 | shouldNotThrowAny { tester.testEquals() } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /api/all/src/commonTest/kotlin/io/opentelemetry/kotlin/api/metrics/internal/NoopMeterProviderTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.kotlin.api.metrics.internal 7 | 8 | import io.opentelemetry.kotlin.api.metrics.MeterProvider 9 | import kotlin.test.Test 10 | 11 | class NoopMeterProviderTest { 12 | @Test 13 | fun noopMeterProvider_getDoesNotThrow() { 14 | val provider = MeterProvider.noop() 15 | provider["user-instrumentation"] 16 | } 17 | 18 | @Test 19 | fun noopMeterProvider_builderDoesNotThrow() { 20 | val provider = MeterProvider.noop() 21 | provider.meterBuilder("user-instrumentation").build() 22 | provider.meterBuilder("advanced-instrumetnation").setInstrumentationVersion("1.0").build() 23 | provider.meterBuilder("schema-instrumentation").setSchemaUrl("myschema://url").build() 24 | provider 25 | .meterBuilder("schema-instrumentation") 26 | .setInstrumentationVersion("1.0") 27 | .setSchemaUrl("myschema://url") 28 | .build() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /api/all/src/commonTest/kotlin/io/opentelemetry/kotlin/api/trace/DefaultTracerProviderTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.trace 6 | 7 | import io.kotest.matchers.types.shouldNotBeSameInstanceAs 8 | import kotlin.test.Test 9 | 10 | internal class DefaultTracerProviderTest { 11 | @Test 12 | fun returnsDefaultTracer() { 13 | TracerProvider.noop()["test"] shouldNotBeSameInstanceAs DefaultTracer::class 14 | TracerProvider.noop()["test", "1.0"] shouldNotBeSameInstanceAs DefaultTracer::class 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /api/all/src/commonTest/kotlin/io/opentelemetry/kotlin/api/trace/TraceFlagsTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.kotlin.api.trace 7 | 8 | import io.kotest.matchers.booleans.shouldBeFalse 9 | import io.kotest.matchers.booleans.shouldBeTrue 10 | import io.kotest.matchers.shouldBe 11 | import kotlin.test.Test 12 | 13 | /** Unit tests for {@link TraceFlags}. */ 14 | class TraceFlagsTest { 15 | 16 | @Test 17 | fun defaultInstances() { 18 | TraceFlags.default.asHex() shouldBe "00" 19 | TraceFlags.sampled.asHex() shouldBe "01" 20 | } 21 | 22 | @Test 23 | fun isSampled() { 24 | TraceFlags.fromByte((0xff).toByte()).isSampled().shouldBeTrue() 25 | TraceFlags.fromByte(0x01).isSampled().shouldBeTrue() 26 | TraceFlags.fromByte(0x05).isSampled().shouldBeTrue() 27 | TraceFlags.fromByte(0x00).isSampled().shouldBeFalse() 28 | } 29 | 30 | @Test 31 | fun toFromHex() { 32 | for (i in 0..255) { 33 | var hex = i.toString(16) 34 | if (hex.length == 1) { 35 | hex = "0$hex" 36 | } 37 | TraceFlags.fromHex(hex, 0).asHex() shouldBe hex 38 | } 39 | } 40 | 41 | @Test 42 | fun toFromByte() { 43 | for (i in 0..255) { 44 | TraceFlags.fromByte(i.toByte()).asByte() shouldBe i.toByte() 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /api/build.gradle.kts: -------------------------------------------------------------------------------- 1 | subprojects { group = "io.opentelemetry.kotlin.api" } 2 | -------------------------------------------------------------------------------- /api/metrics/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("mpplib") 3 | } 4 | 5 | kotlin { 6 | sourceSets { 7 | val commonMain by getting { 8 | dependencies { 9 | api(project(":context")) 10 | api(project(":api:all")) 11 | } 12 | } 13 | val commonTest by getting { 14 | dependencies { 15 | implementation(libs.bundles.kotlin.test) 16 | 17 | implementation(libs.jetbrains.kotlinx.coroutines.core) 18 | 19 | implementation(libs.kotest.assertions.core) 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundDoubleCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** A counter instrument that records `double` values with pre-associated attributes. */ 10 | interface BoundDoubleCounter { 11 | /** 12 | * Records a value with pre-bound attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The increment amount. MUST be non-negative. 17 | */ 18 | fun add(value: Double) 19 | 20 | /** 21 | * Records a value with pre-bound attributes. 22 | * 23 | * @param value The increment amount. MUST be non-negative. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun add(value: Double, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [DoubleCounter]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundDoubleHistogram.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** A histogram instrument that records `long` values with pre-associated attributes. */ 10 | interface BoundDoubleHistogram { 11 | /** 12 | * Records a value with a pre-bound set of attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The amount of the measurement. 17 | */ 18 | fun record(value: Double) 19 | 20 | /** 21 | * Records a value with a pre-bound set of attributes. 22 | * 23 | * @param value The amount of the measurement. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun record(value: Double, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [DoubleHistogram]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundDoubleUpDownCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** An up-down-counter instrument with pre-bound attributes. */ 10 | interface BoundDoubleUpDownCounter { 11 | /** 12 | * Records a value with pre-bound attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The increment amount. May be positive, negative or zero. 17 | */ 18 | fun add(value: Double) 19 | 20 | /** 21 | * Records a value with a pre-bound attributes. 22 | * 23 | * @param value The increment amount. May be positive, negative or zero. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun add(value: Double, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [DoubleUpDownCounter]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundLongCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** A counter instrument that records `long` values with pre-associated attributes. */ 10 | interface BoundLongCounter { 11 | /** 12 | * Records a value with pre-bound attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The increment amount. MUST be non-negative. 17 | */ 18 | fun add(value: Long) 19 | 20 | /** 21 | * Records a value with pre-bound attributes. 22 | * 23 | * @param value The increment amount. MUST be non-negative. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun add(value: Long, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [LongCounter]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundLongHistogram.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** A histogram instrument that records `long` values with pre-associated attributes. */ 10 | interface BoundLongHistogram { 11 | /** 12 | * Records a value with a pre-bound set of attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The amount of the measurement. 17 | */ 18 | fun record(value: Long) 19 | 20 | /** 21 | * Records a value with a pre-bound set of attributes. 22 | * 23 | * @param value The amount of the measurement. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun record(value: Long, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [LongHistogram]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/BoundLongUpDownCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | /** An up-down-counter instrument with pre-bound attributes. */ 10 | interface BoundLongUpDownCounter { 11 | /** 12 | * Records a value with pre-bound attributes. 13 | * 14 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 15 | * 16 | * @param value The increment amount. May be positive, negative or zero. 17 | */ 18 | fun add(value: Long) 19 | 20 | /** 21 | * Records a value with a pre-bound attributes. 22 | * 23 | * @param value The increment amount. May be positive, negative or zero. 24 | * @param context The explicit context to associate with this measurement. 25 | */ 26 | fun add(value: Long, context: Context) 27 | 28 | /** 29 | * Unbinds the current bound instance from the [LongUpDownCounter]. 30 | * 31 | * After this method returns the current instance is considered invalid (not being managed by 32 | * the instrument). 33 | */ 34 | fun unbind() 35 | } 36 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/DoubleCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | /** A counter instrument that records `double` values. */ 11 | interface DoubleCounter { 12 | /** 13 | * Records a value. 14 | * 15 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 16 | * 17 | * @param value The increment amount. MUST be non-negative. 18 | */ 19 | fun add(value: Double) 20 | 21 | /** 22 | * Records a value with a set of attributes. 23 | * 24 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 25 | * 26 | * @param value The increment amount. MUST be non-negative. 27 | * @param attributes A set of attributes to associate with the count. 28 | */ 29 | fun add(value: Double, attributes: Attributes) 30 | 31 | /** 32 | * Records a value with a set of attributes. 33 | * 34 | * @param value The increment amount. MUST be non-negative. 35 | * @param attributes A set of attributes to associate with the count. 36 | * @param context The explicit context to associate with this measurement. 37 | */ 38 | fun add(value: Double, attributes: Attributes, context: Context) 39 | 40 | /** 41 | * Constructs a bound version of this instrument where all recorded values use the given 42 | * attributes. 43 | */ 44 | fun bind(attributes: Attributes): BoundDoubleCounter 45 | } 46 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/DoubleCounterBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** Builder class for [DoubleCounter]. */ 8 | interface DoubleCounterBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): DoubleCounterBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): DoubleCounterBuilder 24 | 25 | /** Sets the counter for recording `long` values. */ 26 | fun ofLongs(): LongCounterBuilder 27 | 28 | /** 29 | * Builds and returns a `DoubleCounter` with the desired options. 30 | * 31 | * @return a `DoubleCounter` with the desired options. 32 | */ 33 | fun build(): DoubleCounter 34 | 35 | /** 36 | * Builds this asynchronous instrument with the given callback. 37 | * 38 | * The callback will only be called when the [Meter] is being observed. 39 | * 40 | * @param callback A state-capturing callback used to observe values on-demand. 41 | */ 42 | fun buildWithCallback(callback: (ObservableDoubleMeasurement) -> Unit) 43 | } 44 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/DoubleGaugeBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** A builder for Gauge metric types. These can only be asynchronously collected. */ 8 | interface DoubleGaugeBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): DoubleGaugeBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): DoubleGaugeBuilder 24 | 25 | /** Sets the gauge for recording `long` values. */ 26 | fun ofLongs(): LongGaugeBuilder 27 | 28 | /** 29 | * Builds this asynchronous instrument with the given callback. 30 | * 31 | * The callback will only be called when the [Meter] is being observed. 32 | * 33 | * @param callback A state-capturing callback used to observe values on-demand. 34 | */ 35 | fun buildWithCallback(callback: (ObservableDoubleMeasurement) -> Unit) 36 | } 37 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/DoubleHistogram.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | /** A histogram instrument that records `long` values. */ 11 | interface DoubleHistogram { 12 | /** 13 | * Records a value. 14 | * 15 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 16 | * 17 | * @param value The amount of the measurement. 18 | */ 19 | fun record(value: Double) 20 | 21 | /** 22 | * Records a value with a set of attributes. 23 | * 24 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 25 | * 26 | * @param value The amount of the measurement. 27 | * @param attributes A set of attributes to associate with the count. 28 | */ 29 | fun record(value: Double, attributes: Attributes) 30 | 31 | /** 32 | * Records a value with a set of attributes. 33 | * 34 | * @param value The amount of the measurement. 35 | * @param attributes A set of attributes to associate with the count. 36 | * @param context The explicit context to associate with this measurement. 37 | */ 38 | fun record(value: Double, attributes: Attributes, context: Context) 39 | 40 | /** 41 | * Constructs a bound version of this instrument where all recorded values use the given 42 | * attributes. 43 | */ 44 | fun bind(attributes: Attributes): BoundDoubleHistogram 45 | } 46 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/DoubleHistogramBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** Builder class for [DoubleHistogram]. */ 8 | interface DoubleHistogramBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): DoubleHistogramBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): DoubleHistogramBuilder 24 | 25 | /** Sets the counter for recording `long` values. */ 26 | fun ofLongs(): LongHistogramBuilder 27 | 28 | /** 29 | * Builds and returns a `DoubleHistogram` with the desired options. 30 | * 31 | * @return a `DoubleHistogram` with the desired options. 32 | */ 33 | fun build(): DoubleHistogram 34 | } 35 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/GlobalMeterProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.metrics.internal.NoopMeterProvider 8 | import kotlinx.atomicfu.atomic 9 | 10 | /** This class is a temporary solution until metrics SDK is marked stable. */ 11 | object GlobalMeterProvider { 12 | private val globalMeterProvider = atomic(NoopMeterProvider.instance) 13 | 14 | /** Returns the globally registered [MeterProvider]. */ 15 | fun get(): MeterProvider { 16 | return globalMeterProvider.value 17 | } 18 | 19 | /** 20 | * Sets the [MeterProvider] that should be the global instance. Future calls to [ ][.get] will 21 | * return the provided [MeterProvider] instance. This should be called once as early as possible 22 | * in your application initialization logic, often in a `static` block in your main class. 23 | */ 24 | fun set(provider: MeterProvider) { 25 | globalMeterProvider.lazySet(provider) 26 | } 27 | 28 | fun disableGlobalMeterProvider() { 29 | globalMeterProvider.lazySet(NoopMeterProvider.instance) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/LongCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | /** A counter instrument that records `long` values. */ 11 | interface LongCounter { 12 | /** 13 | * Records a value. 14 | * 15 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 16 | * 17 | * @param value The increment amount. MUST be non-negative. 18 | */ 19 | fun add(value: Long) 20 | 21 | /** 22 | * Records a value with a set of attributes. 23 | * 24 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 25 | * 26 | * @param value The increment amount. MUST be non-negative. 27 | * @param attributes A set of attributes to associate with the count. 28 | */ 29 | fun add(value: Long, attributes: Attributes) 30 | 31 | /** 32 | * Records a value with a set of attributes. 33 | * 34 | * @param value The increment amount. MUST be non-negative. 35 | * @param attributes A set of attributes to associate with the count. 36 | * @param context The explicit context to associate with this measurement. 37 | */ 38 | fun add(value: Long, attributes: Attributes, context: Context) 39 | 40 | /** 41 | * Constructs a bound version of this instrument where all recorded values use the given 42 | * attributes. 43 | */ 44 | fun bind(attributes: Attributes): BoundLongCounter 45 | } 46 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/LongCounterBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** Builder class for [LongCounter]. */ 8 | interface LongCounterBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): LongCounterBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): LongCounterBuilder 24 | 25 | /** Sets the counter for recording `double` values. */ 26 | fun ofDoubles(): DoubleCounterBuilder 27 | 28 | /** 29 | * Builds and returns a `LongCounter` with the desired options. 30 | * 31 | * @return a `LongCounter` with the desired options. 32 | */ 33 | fun build(): LongCounter 34 | 35 | /** 36 | * Builds this asynchronous instrument with the given callback. 37 | * 38 | * The callback will only be called when the [Meter] is being observed. 39 | * 40 | * @param callback A state-capturing callback used to observe values on-demand. 41 | */ 42 | fun buildWithCallback(callback: (ObservableLongMeasurement) -> Unit) 43 | } 44 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/LongGaugeBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** A builder for Gauge metric types. These can only be asynchronously collected. */ 8 | interface LongGaugeBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): LongGaugeBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): LongGaugeBuilder 24 | 25 | /** Sets the gauge for recording `double` values. */ 26 | fun ofDoubles(): DoubleGaugeBuilder 27 | 28 | /** 29 | * Builds this asynchronous instrument with the given callback. 30 | * 31 | * The callback will only be called when the [Meter] is being observed. 32 | * 33 | * @param callback A state-capturing callback used to observe values on-demand. 34 | */ 35 | fun buildWithCallback(callback: (ObservableLongMeasurement) -> Unit) 36 | } 37 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/LongHistogram.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | /** A histogram instrument that records `long` values. */ 11 | interface LongHistogram { 12 | /** 13 | * Records a value. 14 | * 15 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 16 | * 17 | * @param value The amount of the measurement. 18 | */ 19 | fun record(value: Long) 20 | 21 | /** 22 | * Records a value with a set of attributes. 23 | * 24 | * Note: This may use `Context.current()` to pull the context associated with this measurement. 25 | * 26 | * @param value The amount of the measurement. 27 | * @param attributes A set of attributes to associate with the count. 28 | */ 29 | fun record(value: Long, attributes: Attributes) 30 | 31 | /** 32 | * Records a value with a set of attributes. 33 | * 34 | * @param value The amount of the measurement. 35 | * @param attributes A set of attributes to associate with the count. 36 | * @param context The explicit context to associate with this measurement. 37 | */ 38 | fun record(value: Long, attributes: Attributes, context: Context) 39 | 40 | /** 41 | * Construct a bound version of this instrument where all recorded values use the given 42 | * attributes. 43 | */ 44 | fun bind(attributes: Attributes): BoundLongHistogram 45 | } 46 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/LongHistogramBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** Builder class for [LongHistogram]. */ 8 | interface LongHistogramBuilder { 9 | /** 10 | * Sets the description for this instrument. 11 | * 12 | * Description strings should follow the instrument description rules: 13 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-description 14 | */ 15 | fun setDescription(description: String): LongHistogramBuilder 16 | 17 | /** 18 | * Sets the unit of measure for this instrument. 19 | * 20 | * Unit strings should follow the instrument unit rules: 21 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-unit 22 | */ 23 | fun setUnit(unit: String): LongHistogramBuilder 24 | 25 | /** Sets the histogram for recording `double` values. */ 26 | fun ofDoubles(): DoubleHistogramBuilder 27 | 28 | /** 29 | * Builds and returns a `LongHistogram` with the desired options. 30 | * 31 | * @return a `LongHistogram` with the desired options. 32 | */ 33 | fun build(): LongHistogram 34 | } 35 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/MeterBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** 8 | * Builder class for creating [Meter] instances. 9 | * 10 | * @since 1.4.0 11 | */ 12 | interface MeterBuilder { 13 | /** 14 | * Assigns an OpenTelemetry schema URL to the resulting Meter. 15 | * 16 | * @param schemaUrl The URL of the OpenTelemetry schema being used by this instrumentation 17 | * library. 18 | * @return this 19 | */ 20 | fun setSchemaUrl(schemaUrl: String): MeterBuilder 21 | 22 | /** 23 | * Assigns a version to the instrumentation library that is using the resulting Meter. 24 | * 25 | * @param instrumentationVersion The version of the instrumentation library. 26 | * @return this 27 | */ 28 | fun setInstrumentationVersion(instrumentationVersion: String): MeterBuilder 29 | 30 | /** 31 | * Gets or creates a [Meter] instance. 32 | * 33 | * @return a [Meter] instance configured with the provided options. 34 | */ 35 | fun build(): io.opentelemetry.kotlin.api.metrics.Meter 36 | } 37 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/ObservableDoubleMeasurement.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | 9 | /** An interface for observing measurements with `double` values. */ 10 | interface ObservableDoubleMeasurement : ObservableMeasurement { 11 | /** 12 | * Records a measurement. 13 | * 14 | * @param value The measurement amount. MUST be non-negative. 15 | */ 16 | fun observe(value: Double) 17 | 18 | /** 19 | * Records a measurement with a set of attributes. 20 | * 21 | * @param value The measurement amount. MUST be non-negative. 22 | * @param attributes A set of attributes to associate with the count. 23 | */ 24 | fun observe(value: Double, attributes: Attributes) 25 | } 26 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/ObservableLongMeasurement.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | 9 | /** An interface for observing measurements with `long` values. */ 10 | interface ObservableLongMeasurement : ObservableMeasurement { 11 | /** 12 | * Records a measurement. 13 | * 14 | * @param value The measurement amount. MUST be non-negative. 15 | */ 16 | fun observe(value: Long) 17 | 18 | /** 19 | * Records a measurement with a set of attributes. 20 | * 21 | * @param value The measurement amount. MUST be non-negative. 22 | * @param attributes A set of attributes to associate with the count. 23 | */ 24 | fun observe(value: Long, attributes: Attributes) 25 | } 26 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/ObservableMeasurement.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics 6 | 7 | /** 8 | * A mechanism for observing measurments. 9 | * 10 | * see [ObservableDoubleMeasurement] or [ObservableLongMeasurement]. 11 | */ 12 | interface ObservableMeasurement 13 | -------------------------------------------------------------------------------- /api/metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/api/metrics/internal/NoopMeterProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.api.metrics.internal 6 | 7 | import io.opentelemetry.kotlin.api.metrics.Meter 8 | import io.opentelemetry.kotlin.api.metrics.MeterBuilder 9 | import io.opentelemetry.kotlin.api.metrics.MeterProvider 10 | 11 | /** A [MeterProvider] that does nothing. */ 12 | class NoopMeterProvider private constructor() : MeterProvider { 13 | override fun meterBuilder(instrumentationName: String): MeterBuilder { 14 | return BUILDER_INSTANCE 15 | } 16 | 17 | private class NoopMeterBuilder : MeterBuilder { 18 | override fun setSchemaUrl(schemaUrl: String): MeterBuilder { 19 | return this 20 | } 21 | 22 | override fun setInstrumentationVersion(instrumentationVersion: String): MeterBuilder { 23 | return this 24 | } 25 | 26 | override fun build(): Meter { 27 | return NoopMeter.instance 28 | } 29 | } 30 | 31 | companion object { 32 | private val INSTANCE = NoopMeterProvider() 33 | private val BUILDER_INSTANCE: MeterBuilder = NoopMeterBuilder() 34 | val instance: MeterProvider 35 | get() = INSTANCE 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /api/metrics/src/commonTest/kotlin/io/opentelemetry/kotlin/api/metrics/internal/NoopMeterProviderTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package io.opentelemetry.kotlin.api.metrics.internal 7 | 8 | import io.opentelemetry.kotlin.api.metrics.MeterProvider 9 | import kotlin.test.Test 10 | 11 | class NoopMeterProviderTest { 12 | @Test 13 | fun noopMeterProvider_getDoesNotThrow() { 14 | val provider = MeterProvider.noop() 15 | provider["user-instrumentation"] 16 | } 17 | 18 | @Test 19 | fun noopMeterProvider_builderDoesNotThrow() { 20 | val provider = MeterProvider.noop() 21 | provider.meterBuilder("user-instrumentation").build() 22 | provider.meterBuilder("advanced-instrumetnation").setInstrumentationVersion("1.0").build() 23 | provider.meterBuilder("schema-instrumentation").setSchemaUrl("myschema://url").build() 24 | provider 25 | .meterBuilder("schema-instrumentation") 26 | .setInstrumentationVersion("1.0") 27 | .setSchemaUrl("myschema://url") 28 | .build() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `java-gradle-plugin` 3 | `kotlin-dsl` 4 | `kotlin-dsl-precompiled-script-plugins` 5 | } 6 | 7 | repositories { 8 | gradlePluginPortal() 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | implementation(libs.gradleplugin.kotlin.main) 14 | implementation(libs.gradleplugin.kotlinx.serialization) 15 | } 16 | 17 | -------------------------------------------------------------------------------- /buildSrc/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | 2 | dependencyResolutionManagement { 3 | versionCatalogs { 4 | create("libs") { 5 | from(files("../gradle/libs.versions.toml")) 6 | } 7 | } 8 | } 9 | pluginManagement { 10 | repositories { 11 | gradlePluginPortal() 12 | mavenCentral() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/common.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("multiplatform") 3 | kotlin("plugin.serialization") 4 | } 5 | 6 | if (System.getenv("PACKAGE_VERSION") != null) { 7 | project.version = System.getenv("PACKAGE_VERSION") 8 | } 9 | 10 | tasks { 11 | withType().configureEach { 12 | kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" 13 | } 14 | withType { 15 | isPreserveFileTimestamps = false 16 | isReproducibleFileOrder = true 17 | } 18 | } 19 | 20 | repositories { 21 | mavenCentral() 22 | maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers") 23 | } 24 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/javalib.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("common") 3 | } 4 | val compileNative = findProperty("compileNative") == "true" 5 | 6 | kotlin { 7 | jvm { withJava() } 8 | 9 | sourceSets { 10 | all { 11 | languageSettings.optIn("kotlin.js.ExperimentalJsExport") 12 | languageSettings.optIn("kotlin.RequiresOptIn") 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/mpplib.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("common") 3 | } 4 | 5 | val ideaActive = System.getProperty("idea.active") == "true" 6 | val compileNative = findProperty("compileNative") == "true" 7 | 8 | kotlin { 9 | jvm { withJava() } 10 | js(IR) { 11 | nodejs { testTask { useMocha { timeout = "80s" } } } 12 | browser { testTask { useMocha { timeout = "80s" } } } 13 | } 14 | if(compileNative){ 15 | if (ideaActive) { 16 | val os = 17 | org.gradle.nativeplatform.platform.internal.DefaultNativePlatform 18 | .getCurrentOperatingSystem() 19 | if (os.isWindows) { 20 | mingwX64() 21 | } else if (os.isLinux) { 22 | linuxX64() 23 | } else if (os.isMacOsX) { 24 | macosArm64() 25 | } 26 | } else { 27 | macosArm64() 28 | macosX64() 29 | iosArm64() 30 | iosX64() 31 | linuxX64() 32 | // linuxArm32Hfp() 33 | // linuxMips32() 34 | watchosArm32() 35 | watchosArm64() 36 | watchosX64() 37 | tvosArm64() 38 | tvosX64() 39 | // androidNativeArm32() 40 | // androidNativeArm64() 41 | mingwX64() 42 | } 43 | } 44 | 45 | sourceSets { 46 | all { 47 | languageSettings.optIn("kotlin.js.ExperimentalJsExport") 48 | languageSettings.optIn("kotlin.RequiresOptIn") 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/npmlib.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("common") 3 | } 4 | val compileNative = findProperty("compileNative") == "true" 5 | 6 | kotlin { 7 | js(IR) { 8 | binaries.library() 9 | nodejs { testTask { useMocha { timeout = "20000" } } } 10 | } 11 | 12 | sourceSets { 13 | all { 14 | languageSettings.optIn("kotlin.js.ExperimentalJsExport") 15 | languageSettings.optIn("kotlin.RequiresOptIn") 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /context/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("mpplib") 3 | } 4 | 5 | kotlin { 6 | sourceSets { 7 | val commonMain by getting { 8 | dependencies { 9 | api("org.jetbrains.kotlinx:kotlinx-datetime:0.5.0") 10 | } 11 | } 12 | val commonTest by getting { 13 | dependencies { 14 | implementation(libs.bundles.kotlin.test) 15 | 16 | implementation(libs.jetbrains.kotlinx.coroutines.core) 17 | 18 | implementation(libs.kotest.assertions.core) 19 | } 20 | } 21 | 22 | val jvmMain by getting { 23 | dependsOn(commonMain) 24 | dependencies {} 25 | } 26 | val jsMain by getting { 27 | dependsOn(commonMain) 28 | dependencies {} 29 | } 30 | val nativeMain by creating { dependsOn(commonMain) } 31 | 32 | targets.forEach { 33 | it.compilations.forEach { compilation -> 34 | when (compilation.name) { 35 | "main" -> 36 | compilation.apply { 37 | when (this) { 38 | is org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation -> { // Native 39 | defaultSourceSet { dependsOn(nativeMain) } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /context/src/commonMain/kotlin/io/opentelemetry/kotlin/Closeable.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin 2 | 3 | interface Closeable { 4 | fun close() 5 | } 6 | 7 | inline fun T.use(block: (T) -> R): R { 8 | try { 9 | return block(this) 10 | } finally { 11 | close() 12 | } 13 | } 14 | 15 | inline fun T.use(block: (T) -> Unit) { 16 | try { 17 | block(this) 18 | } finally { 19 | close() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /context/src/commonMain/kotlin/io/opentelemetry/kotlin/KotlinTarget.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin 2 | 3 | expect class KotlinTarget { 4 | companion object { 5 | fun isJvm(): Boolean 6 | fun isJs(): Boolean 7 | fun isNative(): Boolean 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /context/src/commonMain/kotlin/io/opentelemetry/kotlin/Supplier.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin 2 | 3 | fun interface Supplier { 4 | fun get(): T 5 | } 6 | -------------------------------------------------------------------------------- /context/src/commonMain/kotlin/io/opentelemetry/kotlin/context/ArrayBasedContextStorage.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin.context 2 | 3 | import kotlinx.atomicfu.atomic 4 | 5 | class ArrayBasedContextStorage : ContextStorage { 6 | val context = atomic(ArrayBasedContext.root()) 7 | 8 | override fun attach(toAttach: Context): Scope { 9 | val oldContext = context.value 10 | context.value = toAttach 11 | return ContextScope { context.value = oldContext } 12 | } 13 | 14 | override fun current(): Context { 15 | return context.value 16 | } 17 | 18 | private class ContextScope(private val reset: () -> Unit) : Scope { 19 | override fun close() { 20 | reset() 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /context/src/commonMain/kotlin/io/opentelemetry/kotlin/context/ContextKey.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.context 6 | 7 | /** 8 | * Key for indexing values of type [T] stored in a [Context]. [ContextKey] are compared by 9 | * reference, so it is expected that only one [ContextKey] is created for a particular type of 10 | * context value. 11 | * 12 | *
`public class ContextUser {
13 |  *
14 |  * private static final ContextKey KEY = ContextKey.named("MyState");
15 |  *
16 |  * public Context startWork() { return Context.withValues(KEY, new MyState()); }
17 |  *
18 |  * public void continueWork(Context context) { MyState state = context.get(KEY); // Keys are
19 |  * compared by reference only. assert state != Context.current().get(ContextKey.named("MyState"));
20 |  * ... } }
21 |  *
22 |  * `
* 23 | */ 24 | // ErrorProne false positive, this is used for its type constraint, not only as a bag of statics. 25 | interface ContextKey { 26 | companion object { 27 | /** 28 | * Returns a new [ContextKey] with the given debug name. The name does not impact behavior 29 | * and is only for debugging purposes. Multiple different keys with the same name will be 30 | * separate keys. 31 | */ 32 | fun named(name: String): ContextKey { 33 | return DefaultContextKey(name) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /context/src/commonMain/kotlin/io/opentelemetry/kotlin/context/ContextStorageProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.context 6 | 7 | /** 8 | * A Java SPI (Service Provider Interface) to allow replacing the default [ContextStorage]. This can 9 | * be useful if, for example, you want to store OpenTelemetry [Context] in another context 10 | * propagation system. For example, the returned [ContextStorage] could delegate to methods in 11 | * 12 | * [`com.linecorp.armeria.common.RequestContext`](https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/RequestContext.html) 13 | * , [`io.grpc.context.Context`](https://grpc.github.io/grpc-java/javadoc/io/grpc/Context.html), or 14 | * [`org.eclipse.microprofile.context.ThreadContext`](https://download.eclipse.org/microprofile/microprofile-context-propagation-1.0.2/apidocs/org/eclipse/microprofile/context/ThreadContext.html) 15 | * 16 | * if you are already using one of those systems in your application. Then you would not have to use 17 | * methods like [Context.wrap] and can use your current system instead. 18 | */ 19 | interface ContextStorageProvider { 20 | /** Returns the [ContextStorage] to use to store [Context]. */ 21 | fun get(): ContextStorage 22 | } 23 | -------------------------------------------------------------------------------- /context/src/commonMain/kotlin/io/opentelemetry/kotlin/context/DefaultContextKey.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.context 6 | 7 | internal class DefaultContextKey(private val name: String) : ContextKey { 8 | override fun toString(): String { 9 | return name 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /context/src/commonMain/kotlin/io/opentelemetry/kotlin/context/Scope.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.context 6 | 7 | import io.opentelemetry.kotlin.Closeable 8 | 9 | /** 10 | * An [AutoCloseable] that represents a mounted context for a block of code. A failure to call 11 | * [Scope.close] will generally break tracing or cause memory leaks. It is recommended that you use 12 | * this class with a `try-with-resources` block: 13 | * 14 | *
`try (Scope ignored = span.makeCurrent()) { ... } `
* 15 | */ 16 | interface Scope : Closeable { 17 | companion object { 18 | /** 19 | * Returns a [Scope] that does nothing. Represents attaching a [Context] when it is already 20 | * attached. 21 | * 22 | * fun noop(): Scope? { return NoopScope.INSTANCE } 23 | */ 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /context/src/commonMain/kotlin/io/opentelemetry/kotlin/context/propagation/DefaultContextPropagators.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.context.propagation 6 | 7 | /** 8 | * `DefaultContextPropagators` is the default, built-in implementation of [ ]. 9 | * 10 | * All the registered propagators are stored internally as a simple list, and are invoked 11 | * synchronically upon injection and extraction. 12 | * 13 | * The propagation fields retrieved from all registered propagators are de-duplicated. 14 | */ 15 | internal class DefaultContextPropagators(override val textMapPropagator: TextMapPropagator) : 16 | ContextPropagators { 17 | 18 | companion object { 19 | private val NOOP: ContextPropagators = 20 | DefaultContextPropagators(NoopTextMapPropagator.instance) 21 | 22 | fun noop(): ContextPropagators { 23 | return NOOP 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /context/src/commonMain/kotlin/io/opentelemetry/kotlin/context/propagation/NoopTextMapPropagator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.context.propagation 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | internal class NoopTextMapPropagator : TextMapPropagator { 10 | override fun fields(): Collection { 11 | return emptyList() 12 | } 13 | 14 | override fun inject(context: Context, carrier: C, setter: TextMapSetter) {} 15 | 16 | override fun extract(context: Context, carrier: C, getter: TextMapGetter): Context { 17 | return context 18 | } 19 | 20 | companion object { 21 | private val INSTANCE = NoopTextMapPropagator() 22 | val instance: TextMapPropagator 23 | get() = INSTANCE 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /context/src/commonMain/kotlin/io/opentelemetry/kotlin/context/propagation/TextMapSetter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.context.propagation 6 | 7 | /** 8 | * Class that allows a `TextMapPropagator` to set propagated fields into a carrier. 9 | * 10 | * `Setter` is stateless and allows to be saved as a constant to avoid runtime allocations. 11 | * 12 | * @param carrier of propagation fields, such as an http request 13 | */ 14 | fun interface TextMapSetter { 15 | /** 16 | * Replaces a propagated field with the given value. 17 | * 18 | * For example, a setter for an [java.net.HttpURLConnection] would be the method reference 19 | * [java.net.HttpURLConnection.addRequestProperty] 20 | * 21 | * @param carrier holds propagation fields. For example, an outgoing message or http request. To 22 | * facilitate implementations as java lambdas, this parameter may be null. 23 | * @param key the key of the field. 24 | * @param value the value of the field. 25 | */ 26 | operator fun set(carrier: C, key: String, value: String?) 27 | } 28 | -------------------------------------------------------------------------------- /context/src/commonTest/kotlin/io/opentelemetry/kotlin/context/propagation/TextMapPropagatorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.context.propagation 6 | 7 | import io.kotest.matchers.shouldBe 8 | import io.kotest.matchers.shouldNotBe 9 | import kotlin.test.Test 10 | 11 | class TextMapPropagatorTest { 12 | @Test 13 | fun emptyCompositeShouldBeNoop() { 14 | TextMapPropagator.composite() shouldBe TextMapPropagator.noop() 15 | } 16 | 17 | @Test 18 | fun singleCompositeShouldNotBeWrapped() { 19 | val propagator: TextMapPropagator = PropagatorFactory.createDummyTextMapPropagator() 20 | TextMapPropagator.composite(propagator) shouldBe propagator 21 | } 22 | 23 | @Test 24 | fun multiCompositeShouldNotBeWrapped() { 25 | val propagator1: TextMapPropagator = PropagatorFactory.createDummyTextMapPropagator() 26 | val propagator2: TextMapPropagator = PropagatorFactory.createDummyTextMapPropagator() 27 | val result = TextMapPropagator.composite(propagator1, propagator2) 28 | result shouldNotBe propagator1 29 | result shouldNotBe propagator2 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /context/src/jsMain/kotlin/io/opentelemetry/kotlin/KotlinTarget.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin 2 | 3 | actual class KotlinTarget { 4 | actual companion object { 5 | actual fun isJvm(): Boolean { 6 | return false 7 | } 8 | 9 | actual fun isJs(): Boolean { 10 | return true 11 | } 12 | 13 | actual fun isNative(): Boolean { 14 | return false 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /context/src/jvmMain/kotlin/io/opentelemetry/kotlin/KotlinTarget.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin 2 | 3 | actual class KotlinTarget { 4 | actual companion object { 5 | actual fun isJvm(): Boolean { 6 | return true 7 | } 8 | 9 | actual fun isJs(): Boolean { 10 | return false 11 | } 12 | 13 | actual fun isNative(): Boolean { 14 | return false 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /context/src/nativeMain/kotlin/io/opentelemetry/kotlin/KotlinTarget.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin 2 | 3 | actual class KotlinTarget { 4 | actual companion object { 5 | actual fun isJvm(): Boolean { 6 | return false 7 | } 8 | 9 | actual fun isJs(): Boolean { 10 | return false 11 | } 12 | 13 | actual fun isNative(): Boolean { 14 | return true 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx2048m 2 | org.gradle.daemon=true 3 | org.gradle.parallel=true 4 | org.gradle.configureondemand=false 5 | kotlin.incremental=true 6 | kotlin.incremental.js.ir=true 7 | org.gradle.caching=true 8 | kotlin.code.style=official 9 | kotlin.native.ignoreDisabledTargets=true 10 | kotlin.native.ignoreIncorrectDependencies=true 11 | kotlin.native.cacheKind.linuxX64=none 12 | kotlin.js.generate.executable.default=false 13 | kotlin.mpp.stability.nowarn=true 14 | kotlin.native.binary.memoryModel=experimental 15 | compileNative=true 16 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | kotlin = "1.9.23" 3 | kotlinxCoroutines = "1.8.0" 4 | 5 | [libraries] 6 | benasher44-uuid = "com.benasher44:uuid:0.8.4" 7 | 8 | gradleplugin-kotlin-main = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } 9 | gradleplugin-kotlinx-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin" } 10 | kotlin-test-annotations-common = { module = "org.jetbrains.kotlin:kotlin-test-annotations-common", version.ref = "kotlin" } 11 | kotlin-test-common = { module = "org.jetbrains.kotlin:kotlin-test-common", version.ref = "kotlin" } 12 | kotlin-test-main = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } 13 | 14 | gradleplugin-kotlinx-atomicfu = "org.jetbrains.kotlinx:atomicfu-gradle-plugin:0.22.0" 15 | jetbrains-kotlinx-collections-immutable = "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7" 16 | jetbrains-kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" } 17 | jetbrains-kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" } 18 | jetbrains-kotlinx-datetime = "org.jetbrains.kotlinx:kotlinx-datetime:0.5.0" 19 | 20 | kotest-assertions-core = "io.kotest:kotest-assertions-core:5.8.1" 21 | 22 | [bundles] 23 | kotlin-test = ["kotlin-test-main", "kotlin-test-common", "kotlin-test-annotations-common"] 24 | 25 | [plugins] 26 | kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } 27 | kotlin-plugin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dcxp/opentelemetry-kotlin/9c3186e26bd3ac78b650163be2c8f569096aaeec/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionSha256Sum=03ec176d388f2aa99defcadc3ac6adf8dd2bce5145a129659537c0874dea5ad1 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /sdk/build.gradle.kts: -------------------------------------------------------------------------------- 1 | subprojects { group = "io.opentelemetry.kotlin.sdk" } 2 | -------------------------------------------------------------------------------- /sdk/sdk-all/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("mpplib") 3 | } 4 | 5 | 6 | 7 | kotlin { 8 | sourceSets { 9 | val commonMain by getting { 10 | dependencies { 11 | api(project(":context")) 12 | api(project(":api:all")) 13 | api(project(":sdk:sdk-common")) 14 | api(project(":sdk:sdk-trace")) 15 | 16 | implementation(libs.jetbrains.kotlinx.collections.immutable) 17 | implementation(libs.jetbrains.kotlinx.coroutines.core) 18 | } 19 | } 20 | val commonTest by getting { 21 | dependencies { 22 | api(project(":sdk:sdk-testing")) 23 | 24 | implementation(libs.bundles.kotlin.test) 25 | 26 | implementation(libs.kotest.assertions.core) 27 | 28 | implementation(libs.benasher44.uuid) 29 | 30 | implementation(libs.jetbrains.kotlinx.coroutines.test) 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sdk/sdk-all/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/common/SystemClockTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.common 6 | 7 | import io.kotest.matchers.ints.shouldNotBeExactly 8 | import io.kotest.matchers.longs.shouldBeExactly 9 | import kotlin.test.Test 10 | 11 | // This test is placed in the all artifact instead of the common one so it uses the dependency jar 12 | // instead of the classes directly, which allows verifying mrjar behavior. 13 | internal class SystemClockTest { 14 | // @Test 15 | fun millisPrecision() { 16 | // If we test many times, we can be fairly sure we didn't just get lucky with having a 17 | // rounded 18 | // result on a higher than expected precision timestamp. 19 | for (i in 0..99) { 20 | val now: Long = SystemClock.instance.now() 21 | (now % 1000000) shouldBeExactly 0 22 | } 23 | } 24 | 25 | @Test 26 | fun microsPrecision() { 27 | // If we test many times, we can be fairly sure we get at least one timestamp that isn't 28 | // coincidentally rounded to millis precision. 29 | var numHasMicros = 0 30 | for (i in 0..99) { 31 | val now: Long = SystemClock.instance.now() 32 | if (now % 1000000 != 0L) { 33 | numHasMicros++ 34 | } 35 | } 36 | numHasMicros shouldNotBeExactly 0 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sdk/sdk-common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("mpplib") 3 | } 4 | 5 | kotlin { 6 | 7 | sourceSets { 8 | val commonMain by getting { 9 | dependencies { 10 | api(project(":semconv")) 11 | api(project(":api:all")) 12 | 13 | implementation(libs.jetbrains.kotlinx.collections.immutable) 14 | implementation(libs.jetbrains.kotlinx.coroutines.core) 15 | } 16 | } 17 | val commonTest by getting { 18 | dependencies { 19 | 20 | implementation(libs.bundles.kotlin.test) 21 | 22 | implementation(libs.kotest.assertions.core) 23 | 24 | implementation(libs.jetbrains.kotlinx.coroutines.test) 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /sdk/sdk-common/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/common/Clock.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.common 6 | 7 | /** Interface for getting the current time. */ 8 | interface Clock { 9 | 10 | /** 11 | * Returns the current epoch timestamp in nanos from this clock. This timestamp should only be 12 | * used to compute a current time. To compute a duration, timestamps should always be obtained 13 | * using [.nanoTime]. For example, this usage is correct. 14 | * 15 | *
`long startNanos = clock.nanoTime(); // Spend time... long durationNanos =
16 |      * clock.nanoTime() - startNanos; `
* 17 | * 18 | * This usage is NOT correct. 19 | * 20 | *
`long startNanos = clock.now(); // Spend time... long durationNanos = clock.now() -
21 |      * startNanos; `
* 22 | */ 23 | fun now(): Long 24 | 25 | /** 26 | * Returns a time measurement with nanosecond precision that can only be used to calculate 27 | * elapsed time. 28 | */ 29 | fun nanoTime(): Long 30 | 31 | companion object { 32 | /** Returns a default [Clock] which reads from [system time][System]. */ 33 | val default: Clock 34 | get() = SystemClock.instance 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sdk/sdk-common/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/common/SystemClock.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.common 6 | 7 | import io.opentelemetry.kotlin.api.common.getNanoseconds 8 | import kotlinx.datetime.Clock as DateTimeClock 9 | 10 | /** A [Clock] that uses [System.currentTimeMillis] and [System.nanoTime]. */ 11 | class SystemClock private constructor() : Clock { 12 | override fun now(): Long { 13 | return DateTimeClock.System.now().toEpochMilliseconds() 14 | } 15 | 16 | override fun nanoTime(): Long { 17 | return DateTimeClock.System.now().getNanoseconds() 18 | } 19 | 20 | companion object { 21 | private val INSTANCE = SystemClock() 22 | 23 | /** 24 | * Returns a `MillisClock`. 25 | * 26 | * @return a `MillisClock`. 27 | */ 28 | val instance: Clock 29 | get() = INSTANCE 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sdk/sdk-common/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/internal/RandomSupplier.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.internal 6 | 7 | import kotlin.random.Random 8 | 9 | /** 10 | * Provides random number generater constructor utilities. 11 | * 12 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 13 | * any time. 14 | */ 15 | object RandomSupplier { 16 | /** Returns the platform default for random number generation. */ 17 | fun platformDefault(): () -> Random { 18 | // note: check borrowed from OkHttp's check for Android. 19 | return { Random.Default } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("mpplib") 3 | } 4 | 5 | kotlin { 6 | sourceSets { 7 | 8 | val commonMain by getting { 9 | dependencies { 10 | api(project(":context")) 11 | //api(project(":api:metrics")) 12 | api(project(":sdk:sdk-common")) 13 | 14 | implementation(libs.jetbrains.kotlinx.collections.immutable) 15 | implementation(libs.jetbrains.kotlinx.coroutines.core) 16 | } 17 | } 18 | val commonTest by getting { 19 | dependencies { 20 | api(project(":sdk:sdk-testing")) 21 | 22 | implementation(libs.bundles.kotlin.test) 23 | 24 | implementation(libs.kotest.assertions.core) 25 | 26 | implementation(libs.jetbrains.kotlinx.coroutines.test) 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/AbstractInstrument.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics 6 | 7 | import io.opentelemetry.kotlin.sdk.metrics.internal.descriptor.InstrumentDescriptor 8 | 9 | abstract class AbstractInstrument(descriptor: InstrumentDescriptor) : Instrument { 10 | private val descriptor: InstrumentDescriptor 11 | 12 | // All arguments cannot be null because they are checked in the abstract builder classes. 13 | init { 14 | this.descriptor = descriptor 15 | } 16 | 17 | fun getDescriptor(): InstrumentDescriptor { 18 | return descriptor 19 | } 20 | 21 | override fun equals(other: Any?): Boolean { 22 | if (this === other) { 23 | return true 24 | } 25 | if (other !is AbstractInstrument) { 26 | return false 27 | } 28 | return descriptor == other.descriptor 29 | } 30 | 31 | override fun hashCode(): Int { 32 | return descriptor.hashCode() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/Instrument.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics 6 | 7 | /** 8 | * Placeholder to avoid modifying SDK implementation. 9 | * 10 | * Previously, this was defined in the API. However, the new API for asynchronous instruments 11 | * returns no value to the user, as there's nothing the user can alter (yet). 12 | */ 13 | internal interface Instrument 14 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/SdkLongGaugeBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics 6 | 7 | import io.opentelemetry.kotlin.api.metrics.DoubleGaugeBuilder 8 | import io.opentelemetry.kotlin.api.metrics.LongGaugeBuilder 9 | import io.opentelemetry.kotlin.api.metrics.ObservableLongMeasurement 10 | import io.opentelemetry.kotlin.sdk.metrics.common.InstrumentType 11 | import io.opentelemetry.kotlin.sdk.metrics.internal.state.MeterProviderSharedState 12 | import io.opentelemetry.kotlin.sdk.metrics.internal.state.MeterSharedState 13 | 14 | internal class SdkLongGaugeBuilder( 15 | meterProviderSharedState: MeterProviderSharedState, 16 | sharedState: MeterSharedState, 17 | name: String, 18 | description: String, 19 | unit: String 20 | ) : 21 | AbstractInstrumentBuilder( 22 | meterProviderSharedState, 23 | sharedState, 24 | name, 25 | description, 26 | unit 27 | ), 28 | LongGaugeBuilder { 29 | override val `this`: SdkLongGaugeBuilder 30 | protected get() = this 31 | 32 | override fun ofDoubles(): DoubleGaugeBuilder { 33 | return swapBuilder(::SdkDoubleGaugeBuilder) 34 | } 35 | 36 | override fun buildWithCallback(callback: (ObservableLongMeasurement) -> Unit) { 37 | registerLongAsynchronousInstrument(InstrumentType.OBSERVABLE_GAUGE, callback) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/SdkMeterBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics 6 | 7 | import io.opentelemetry.kotlin.api.metrics.Meter 8 | import io.opentelemetry.kotlin.api.metrics.MeterBuilder 9 | import io.opentelemetry.kotlin.sdk.internal.ComponentRegistry 10 | 11 | internal class SdkMeterBuilder(registry: ComponentRegistry, instrumentationName: String) : 12 | MeterBuilder { 13 | private val registry: ComponentRegistry 14 | private val instrumentationName: String 15 | private var instrumentationVersion: String? = null 16 | private var schemaUrl: String? = null 17 | 18 | init { 19 | this.registry = registry 20 | this.instrumentationName = instrumentationName 21 | } 22 | 23 | override fun setSchemaUrl(schemaUrl: String): MeterBuilder { 24 | this.schemaUrl = schemaUrl 25 | return this 26 | } 27 | 28 | override fun setInstrumentationVersion(instrumentationVersion: String): MeterBuilder { 29 | this.instrumentationVersion = instrumentationVersion 30 | return this 31 | } 32 | 33 | override fun build(): Meter { 34 | return registry[instrumentationName, instrumentationVersion, schemaUrl] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/common/InstrumentType.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.common 6 | 7 | /** All instrument types available in the metric package. */ 8 | enum class InstrumentType { 9 | COUNTER, 10 | UP_DOWN_COUNTER, 11 | HISTOGRAM, 12 | OBSERVABLE_SUM, 13 | OBSERVABLE_UP_DOWN_SUM, 14 | OBSERVABLE_GAUGE 15 | } 16 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/common/InstrumentValueType.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.common 6 | 7 | /** All possible types for the values recorded via the instruments. */ 8 | enum class InstrumentValueType { 9 | LONG, 10 | DOUBLE 11 | } 12 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/AggregationTemporality.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** An enumeration which describes the time period over which metrics should be aggregated. */ 8 | enum class AggregationTemporality { 9 | /** Metrics will be aggregated only over the most recent collection interval. */ 10 | DELTA, 11 | 12 | /** Metrics will be aggregated over the lifetime of the associated Instrument. */ 13 | CUMULATIVE 14 | } 15 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/Data.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** 8 | * A collection of data points associated to a metric. 9 | * 10 | * Loosely equivalent with "Metric" message in OTLP. See: 11 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/datamodel.md#metric-points 12 | */ 13 | interface Data { 14 | /** 15 | * Returns the data [PointData]s for this metric. 16 | * 17 | * @return the data [PointData]s for this metric, or empty `Collection` if no points. 18 | */ 19 | val points: Collection 20 | } 21 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/DoubleExponentialHistogramData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** 8 | * A simple, autovalue implementation of [ExponentialHistogramData]. For more detailed javadoc on 9 | * the type, see [ExponentialHistogramData]. 10 | * 11 | * See: 12 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/datamodel.md#exponentialhistogram 13 | */ 14 | interface DoubleExponentialHistogramData : ExponentialHistogramData { 15 | 16 | companion object { 17 | val EMPTY: DoubleExponentialHistogramData = 18 | create(AggregationTemporality.CUMULATIVE, listOf()) 19 | 20 | /** 21 | * Create a DoubleExponentialHistogramData. 22 | * 23 | * @return a DoubleExponentialHistogramData 24 | */ 25 | fun create( 26 | temporality: AggregationTemporality, 27 | points: Collection 28 | ): DoubleExponentialHistogramData { 29 | return Implementation(temporality, points) 30 | } 31 | 32 | data class Implementation( 33 | override val aggregationTemporality: AggregationTemporality, 34 | override val points: Collection 35 | ) : DoubleExponentialHistogramData 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/DoubleGaugeData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** [GaugeData] recorded uses `double`s. */ 8 | interface DoubleGaugeData : GaugeData { 9 | 10 | companion object { 11 | val EMPTY = create(emptyList()) 12 | fun create(points: Collection): DoubleGaugeData { 13 | return Implementation(points) 14 | } 15 | data class Implementation(override val points: Collection) : 16 | DoubleGaugeData 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/DoubleHistogramData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** 8 | * A histogram metric point. 9 | * 10 | * See: 11 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/datamodel.md#histogram 12 | * 13 | * *Note: This is called "DoubleHistogram" to reflect which primitives are used to record it, 14 | * however "Histogram" is the equivalent OTLP type.* 15 | */ 16 | interface DoubleHistogramData : Data { 17 | /** 18 | * Returns the `AggregationTemporality` of this metric, 19 | * 20 | * AggregationTemporality describes if the aggregator reports delta changes since last report 21 | * time, or cumulative changes since a fixed start time. 22 | * 23 | * @return the `AggregationTemporality` of this metric 24 | */ 25 | val aggregationTemporality: AggregationTemporality 26 | 27 | companion object { 28 | val EMPTY = create(AggregationTemporality.CUMULATIVE, emptyList()) 29 | 30 | fun create( 31 | temporality: AggregationTemporality, 32 | points: Collection 33 | ): DoubleHistogramData { 34 | return Implementation(temporality, points) 35 | } 36 | 37 | data class Implementation( 38 | override val aggregationTemporality: AggregationTemporality, 39 | override val points: Collection, 40 | ) : DoubleHistogramData 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/DoubleSumData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** [SumData] recorded uses `double`s. */ 8 | interface DoubleSumData : SumData { 9 | companion object { 10 | val EMPTY = create(false, AggregationTemporality.CUMULATIVE, emptyList()) 11 | 12 | fun create( 13 | isMonotonic: Boolean, 14 | temporality: AggregationTemporality, 15 | points: Collection 16 | ): DoubleSumData { 17 | return Implementation(points, isMonotonic, temporality) 18 | } 19 | 20 | data class Implementation( 21 | override val points: Collection, 22 | override val isMonotonic: Boolean, 23 | override val aggregationTemporality: AggregationTemporality 24 | ) : DoubleSumData 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/DoubleSummaryData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** 8 | * A summary metric point. 9 | * 10 | * See: 11 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/datamodel.md#summary 12 | * 13 | * *Note: This is called "DoubleSummary" to reflect which primitives are used to record it, however 14 | * "Summary" is the equivalent OTLP type.* 15 | * 16 | * Summary is considered a legacy metric type, and shouldn't be produced (by default) from 17 | * instruments. 18 | */ 19 | interface DoubleSummaryData : Data { 20 | companion object { 21 | val EMPTY = create(emptyList()) 22 | fun create(points: Collection): DoubleSummaryData { 23 | return Implementation(points) 24 | } 25 | data class Implementation(override val points: Collection) : 26 | DoubleSummaryData 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/ExemplarData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | 9 | /** 10 | * A sample input measurement. 11 | * 12 | * Exemplars also hold information about the environment when the measurement was recorded, for 13 | * example the span and trace ID of the active span when the exemplar was recorded. 14 | */ 15 | interface ExemplarData { 16 | /** 17 | * The set of key/value pairs that were filtered out by the aggregator, but recorded alongside 18 | * the original measurement. Only key/value pairs that were filtered out by the aggregator 19 | * should be included 20 | */ 21 | val filteredAttributes: Attributes 22 | 23 | /** Returns the timestamp in nanos when measurement was collected. */ 24 | val epochNanos: Long 25 | 26 | /** 27 | * (Optional) Span ID of the exemplar trace. 28 | * 29 | * Span ID may be `null` if the measurement is not recorded inside a trace or the trace was not 30 | * sampled. 31 | */ 32 | val spanId: String? 33 | 34 | /** 35 | * (Optional) Trace ID of the exemplar trace. 36 | * 37 | * Trace ID may be `null` if the measurement is not recorded inside a trace or if the trace is 38 | * not sampled. 39 | */ 40 | val traceId: String? 41 | 42 | /** 43 | * Coerces this exemplar to a double value. 44 | * 45 | * Note: This could create a loss of precision from `long` measurements. 46 | */ 47 | val valueAsDouble: Double 48 | } 49 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/ExponentialHistogramBuckets.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** 8 | * ExponentialHistogramBuckets represents either the positive or negative measurements taken for a 9 | * [ExponentialHistogramPointData]. 10 | * 11 | * The bucket boundaries are lower-bound inclusive, and are calculated using the [ ] 12 | * [ExponentialHistogramPointData.getScale] and the [.getOffset]. 13 | * 14 | * For example, assume [ExponentialHistogramPointData.getScale] is 0, the base is 2.0. Then, if 15 | * `offset` is 0, the bucket lower bounds would be 1.0, 2.0, 4.0, 8.0, etc. If `offset` is -3, the 16 | * bucket lower bounds would be 0.125, 0.25, 0.5, 1.0, 2,0, etc. If `offset` is +3, the bucket lower 17 | * bounds would be 8.0, 16.0, 32.0, etc. 18 | */ 19 | interface ExponentialHistogramBuckets { 20 | /** 21 | * The offset shifts the bucket boundaries according to `lower_bound = base^(offset+i). ` * . 22 | * 23 | * @return the offset. 24 | */ 25 | val offset: Int 26 | 27 | /** 28 | * The bucket counts is a of counts representing number of measurements that fall into each 29 | * bucket. 30 | * 31 | * @return the bucket counts. 32 | */ 33 | val bucketCounts: List 34 | 35 | /** 36 | * The total count is the sum of all the values in the buckets. 37 | * 38 | * @return the total count. 39 | */ 40 | val totalCount: Long 41 | } 42 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/GaugeData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** 8 | * A gauge metric point. 9 | * 10 | * See: 11 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/datamodel.md#gauge 12 | */ 13 | interface GaugeData : Data 14 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/LongGaugeData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** [GaugeData] recorded uses `long`s. */ 8 | interface LongGaugeData : GaugeData { 9 | 10 | companion object { 11 | val EMPTY = create(emptyList()) 12 | fun create(points: Collection): LongGaugeData { 13 | return Implementation(points) 14 | } 15 | data class Implementation(override val points: Collection) : LongGaugeData 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/LongSumData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** [SumData] recorded uses `long`s. */ 8 | interface LongSumData : SumData { 9 | companion object { 10 | val EMPTY = 11 | create( 12 | /* isMonotonic= */ false, 13 | AggregationTemporality.CUMULATIVE, 14 | emptyList() 15 | ) 16 | 17 | fun create( 18 | isMonotonic: Boolean, 19 | temporality: AggregationTemporality, 20 | points: Collection 21 | ): LongSumData { 22 | return Implementation(points, isMonotonic, temporality) 23 | } 24 | data class Implementation( 25 | override val points: Collection, 26 | override val isMonotonic: Boolean, 27 | override val aggregationTemporality: AggregationTemporality 28 | ) : LongSumData 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/MetricDataImpl.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | import io.opentelemetry.kotlin.sdk.common.InstrumentationLibraryInfo 8 | import io.opentelemetry.kotlin.sdk.resources.Resource 9 | 10 | data class MetricDataImpl( 11 | override val resource: Resource, 12 | override val instrumentationLibraryInfo: InstrumentationLibraryInfo, 13 | override val name: String, 14 | override val description: String, 15 | override val unit: String, 16 | override val type: MetricDataType, 17 | override val data: Data<*> 18 | ) : MetricData { 19 | companion object { 20 | fun create( 21 | resource: Resource, 22 | instrumentationLibraryInfo: InstrumentationLibraryInfo, 23 | name: String, 24 | description: String, 25 | unit: String, 26 | type: MetricDataType, 27 | data: Data<*> 28 | ): MetricDataImpl { 29 | return MetricDataImpl( 30 | resource, 31 | instrumentationLibraryInfo, 32 | name, 33 | description, 34 | unit, 35 | type, 36 | data 37 | ) 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/MetricDataType.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** The kind of metric. It describes how the data is reported. */ 8 | enum class MetricDataType { 9 | /** 10 | * A Gauge represents a measurement of a long value at a moment in time. Generally only one 11 | * instance of a given Gauge metric will be reported per reporting interval. 12 | */ 13 | LONG_GAUGE, 14 | 15 | /** 16 | * A Gauge represents a measurement of a double value at a moment in time. Generally only one 17 | * instance of a given Gauge metric will be reported per reporting interval. 18 | */ 19 | DOUBLE_GAUGE, 20 | 21 | /** A sum of non negative long (int64) values. Reports [LongSumData] data. */ 22 | LONG_SUM, 23 | 24 | /** A sum of non negative double values. Reports [DoubleSumData] data. */ 25 | DOUBLE_SUM, 26 | 27 | /** 28 | * A Summary of measurements of numeric values, containing the minimum value recorded, the 29 | * maximum value recorded, the sum of all measurements and the total number of measurements 30 | * recorded. 31 | */ 32 | SUMMARY, 33 | 34 | /** 35 | * A Histogram represents an approximate representation of the distribution of measurements 36 | * recorded. 37 | */ 38 | HISTOGRAM, 39 | 40 | /** 41 | * An Exponential Histogram represents an approximate representation of the distribution of 42 | * measurements recorded. The bucket boundaries follow a pre-determined exponential formula. 43 | */ 44 | EXPONENTIAL_HISTOGRAM 45 | } 46 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/PointData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | 9 | /** 10 | * A point in the "Metric stream" data model. 11 | * 12 | * This is distinguished from `Measurement` in that it may have aggregated data, and has its type 13 | * defined by the metric data model (no longer an instrument). 14 | */ 15 | interface PointData { 16 | /** 17 | * Returns the start epoch timestamp in nanos of this `Instrument`, usually the time when the 18 | * metric was created or an aggregation was enabled. 19 | * 20 | * @return the start epoch timestamp in nanos. 21 | */ 22 | val startEpochNanos: Long 23 | 24 | /** 25 | * Returns the epoch timestamp in nanos when data were collected, usually it represents the 26 | * moment when `Instrument.getData()` was called. 27 | * 28 | * @return the epoch timestamp in nanos. 29 | */ 30 | val epochNanos: Long 31 | 32 | /** 33 | * Returns the attributes associated with this `Point`. 34 | * 35 | * @return the attributes associated with this `Point`. 36 | */ 37 | val attributes: Attributes 38 | 39 | /** List of exemplars collected from measurements that were used to form the data point. */ 40 | val exemplars: List 41 | } 42 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/SumData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | /** 8 | * A sum metric point. 9 | * 10 | * See: 11 | * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/datamodel.md#sums 12 | */ 13 | interface SumData : Data { 14 | /** 15 | * Returns "true" if the sum is monotonic. 16 | * 17 | * @return "true" if the sum is monotonic 18 | */ 19 | val isMonotonic: Boolean 20 | 21 | /** 22 | * Returns the `AggregationTemporality` of this metric, 23 | * 24 | * AggregationTemporality describes if the aggregator reports delta changes since last report 25 | * time, or cumulative changes since a fixed start time. 26 | * 27 | * @return the `AggregationTemporality` of this metric 28 | */ 29 | val aggregationTemporality: AggregationTemporality 30 | } 31 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/data/ValueAtPercentile.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.data 6 | 7 | interface ValueAtPercentile { 8 | /** 9 | * The percentile of a distribution. Must be in the interval [0.0, 100.0]. 10 | * 11 | * @return the percentile. 12 | */ 13 | val percentile: Double 14 | 15 | /** 16 | * The value at the given percentile of a distribution. 17 | * 18 | * @return the value at the percentile. 19 | */ 20 | val value: Double 21 | 22 | companion object { 23 | fun create(percentile: Double, value: Double): ValueAtPercentile { 24 | return Implementation(percentile, value) 25 | } 26 | data class Implementation(override val percentile: Double, override val value: Double) : 27 | ValueAtPercentile 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/exemplar/AlwaysSampleFilter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.exemplar 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | class AlwaysSampleFilter : ExemplarFilter { 11 | override fun shouldSampleMeasurement( 12 | value: Long, 13 | attributes: Attributes, 14 | context: Context 15 | ): Boolean { 16 | return true 17 | } 18 | 19 | override fun shouldSampleMeasurement( 20 | value: Double, 21 | attributes: Attributes, 22 | context: Context 23 | ): Boolean { 24 | return true 25 | } 26 | 27 | companion object { 28 | val INSTANCE: ExemplarFilter = AlwaysSampleFilter() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/exemplar/ExemplarFilter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.exemplar 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | /** 11 | * Exemplar filters are used to pre-filter measurements before attempting to store them in a 12 | * reservoir. 13 | */ 14 | interface ExemplarFilter { 15 | /** Returns whether or not a reservoir should attempt to filter a measurement. */ 16 | fun shouldSampleMeasurement(value: Long, attributes: Attributes, context: Context): Boolean 17 | 18 | /** Returns whether or not a reservoir should attempt to filter a measurement. */ 19 | fun shouldSampleMeasurement(value: Double, attributes: Attributes, context: Context): Boolean 20 | 21 | companion object { 22 | /** 23 | * A filter that only accepts measurements where there is a `Span` in [Context] that is 24 | * being sampled. 25 | */ 26 | fun sampleWithTraces(): ExemplarFilter { 27 | return WithTraceExemplarFilter.INSTANCE 28 | } 29 | 30 | /** A filter that accepts any measurement. */ 31 | fun alwaysSample(): ExemplarFilter { 32 | return AlwaysSampleFilter.INSTANCE 33 | } 34 | 35 | /** A filter that accepts no measurements. */ 36 | fun neverSample(): ExemplarFilter { 37 | return NeverSampleFilter.INSTANCE 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/exemplar/FilteredExemplarReservoir.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.exemplar 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | import io.opentelemetry.kotlin.sdk.metrics.data.ExemplarData 10 | 11 | /** Implementation of a reservoir that has a pre-filter on measurements. */ 12 | internal class FilteredExemplarReservoir(filter: ExemplarFilter, reservoir: ExemplarReservoir) : 13 | ExemplarReservoir { 14 | private val filter: ExemplarFilter 15 | private val reservoir: ExemplarReservoir 16 | 17 | init { 18 | this.filter = filter 19 | this.reservoir = reservoir 20 | } 21 | 22 | override fun offerMeasurement(value: Long, attributes: Attributes, context: Context) { 23 | if (filter.shouldSampleMeasurement(value, attributes, context)) { 24 | reservoir.offerMeasurement(value, attributes, context) 25 | } 26 | } 27 | 28 | override fun offerMeasurement(value: Double, attributes: Attributes, context: Context) { 29 | if (filter.shouldSampleMeasurement(value, attributes, context)) { 30 | reservoir.offerMeasurement(value, attributes, context) 31 | } 32 | } 33 | 34 | override fun collectAndReset(pointAttributes: Attributes): List { 35 | return reservoir.collectAndReset(pointAttributes) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/exemplar/HistogramBucketExemplarReservoir.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.exemplar 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | import io.opentelemetry.kotlin.sdk.common.Clock 10 | import io.opentelemetry.kotlin.sdk.metrics.internal.aggregator.ExplicitBucketHistogramUtils.createBoundaryArray 11 | import io.opentelemetry.kotlin.sdk.metrics.internal.aggregator.ExplicitBucketHistogramUtils.findBucketIndex 12 | 13 | /** A Reservoir sampler that preserves the latest seen measurement per-histogram bucket. */ 14 | /** 15 | * Constructs a new reservoir sampler that aligns exemplars with histogram buckets. 16 | * 17 | * @param clock The clock to use when annotating measurements with time. 18 | * @param boundaries Histogram bucket boundaries. 19 | */ 20 | internal class HistogramBucketExemplarReservoir(clock: Clock, private val boundaries: DoubleArray) : 21 | AbstractFixedSizeExemplarReservoir(clock, boundaries.size + 1) { 22 | 23 | override fun reservoirIndexFor(value: Double, attributes: Attributes, context: Context): Int { 24 | return findBucketIndex(boundaries, value) 25 | } 26 | 27 | companion object { 28 | /** Constructs a new histogram bucket exemplar reservoir using standard configuration. */ 29 | fun create(clock: Clock, boundaries: List): HistogramBucketExemplarReservoir { 30 | return HistogramBucketExemplarReservoir(clock, createBoundaryArray(boundaries)) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/exemplar/NeverSampleFilter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.exemplar 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | internal class NeverSampleFilter private constructor() : ExemplarFilter { 11 | override fun shouldSampleMeasurement( 12 | value: Long, 13 | attributes: Attributes, 14 | context: Context 15 | ): Boolean { 16 | return false 17 | } 18 | 19 | override fun shouldSampleMeasurement( 20 | value: Double, 21 | attributes: Attributes, 22 | context: Context 23 | ): Boolean { 24 | return false 25 | } 26 | 27 | companion object { 28 | val INSTANCE: io.opentelemetry.kotlin.sdk.metrics.exemplar.ExemplarFilter = 29 | NeverSampleFilter() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/exemplar/NoExemplarReservoir.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.exemplar 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | import io.opentelemetry.kotlin.sdk.metrics.data.ExemplarData 10 | 11 | /** Implementation of a reservoir that keeps no exemplars. */ 12 | internal class NoExemplarReservoir private constructor() : 13 | io.opentelemetry.kotlin.sdk.metrics.exemplar.ExemplarReservoir { 14 | override fun offerMeasurement(value: Long, attributes: Attributes, context: Context) { 15 | // Stores nothing 16 | } 17 | 18 | override fun offerMeasurement(value: Double, attributes: Attributes, context: Context) { 19 | // Stores nothing. 20 | } 21 | 22 | override fun collectAndReset(pointAttributes: Attributes): List { 23 | return emptyList() 24 | } 25 | 26 | companion object { 27 | val INSTANCE: io.opentelemetry.kotlin.sdk.metrics.exemplar.ExemplarReservoir = 28 | NoExemplarReservoir() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/exemplar/WithTraceExemplarFilter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.exemplar 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.api.trace.Span 9 | import io.opentelemetry.kotlin.context.Context 10 | 11 | /** Exemplar sampler that only samples measurements with associated sampled traces. */ 12 | internal class WithTraceExemplarFilter private constructor() : 13 | io.opentelemetry.kotlin.sdk.metrics.exemplar.ExemplarFilter { 14 | override fun shouldSampleMeasurement( 15 | value: Long, 16 | attributes: Attributes, 17 | context: Context 18 | ): Boolean { 19 | return hasSampledTrace(context) 20 | } 21 | 22 | override fun shouldSampleMeasurement( 23 | value: Double, 24 | attributes: Attributes, 25 | context: Context 26 | ): Boolean { 27 | return hasSampledTrace(context) 28 | } 29 | 30 | companion object { 31 | val INSTANCE: io.opentelemetry.kotlin.sdk.metrics.exemplar.ExemplarFilter = 32 | WithTraceExemplarFilter() 33 | private fun hasSampledTrace(context: Context): Boolean { 34 | return Span.fromContext(context).spanContext.isSampled() 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/export/MetricProducer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.export 6 | 7 | import io.opentelemetry.kotlin.sdk.metrics.data.MetricData 8 | 9 | /** 10 | * `MetricProducer` is the interface that is used to make metric data available to the OpenTelemetry 11 | * exporters. Implementations should be stateful, in that each call to [ ][.collectAllMetrics] will 12 | * return any metric generated since the last call was made. 13 | * 14 | * Implementations must be thread-safe. 15 | */ 16 | interface MetricProducer { 17 | /** 18 | * Returns a collection of produced [MetricData]s to be exported. This will only be those 19 | * metrics that have been produced since the last time this method was called. 20 | * 21 | * @return a collection of produced [MetricData]s to be exported. 22 | */ 23 | fun collectAllMetrics(): Collection 24 | } 25 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/export/MetricReaderFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.export 6 | 7 | /** A constructor of [MetricReader]s. */ 8 | fun interface MetricReaderFactory { 9 | /** 10 | * Construct a new MetricReader. 11 | * 12 | * @param producer the mechanism of reading SDK metrics. 13 | * @return a controller for this metric reader. 14 | */ 15 | fun apply(producer: MetricProducer): MetricReader 16 | } 17 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/export/PeriodicMetricReaderFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.export 6 | 7 | import kotlin.time.Duration 8 | 9 | internal class PeriodicMetricReaderFactory( 10 | private val exporter: MetricExporter, 11 | private val scheduleDelay: Duration 12 | ) : MetricReaderFactory { 13 | override fun apply(producer: MetricProducer): MetricReader { 14 | val result = PeriodicMetricReader(producer, exporter) 15 | // TODO - allow a different start delay. 16 | result.start(scheduleDelay) 17 | return result 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/aggregator/AbstractSumAggregator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.aggregator 6 | 7 | import io.opentelemetry.kotlin.sdk.metrics.internal.descriptor.InstrumentDescriptor 8 | 9 | abstract class AbstractSumAggregator(instrumentDescriptor: InstrumentDescriptor) : 10 | io.opentelemetry.kotlin.sdk.metrics.internal.aggregator.Aggregator { 11 | val isMonotonic: Boolean 12 | 13 | init { 14 | isMonotonic = 15 | io.opentelemetry.kotlin.sdk.metrics.internal.aggregator.MetricDataUtils 16 | .isMonotonicInstrument(instrumentDescriptor) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/aggregator/BucketMapper.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.aggregator 6 | 7 | /** Interface defining methods for mapping values to buckets for [ ]. */ 8 | internal interface BucketMapper { 9 | /** 10 | * Maps a recorded double value to a bucket index. If the index falls out of the range that can 11 | * be represented by an int, then it is expected that the histogram would be downscaled. 12 | * 13 | * @param value Measured value 14 | * @return the index of the bucket which the value maps to. 15 | */ 16 | fun valueToIndex(value: Double): Int 17 | } 18 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/aggregator/DoubleAccumulation.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.aggregator 6 | 7 | import io.opentelemetry.kotlin.sdk.metrics.data.ExemplarData 8 | 9 | /** 10 | * An accumulation representing `long` values and exemplars. 11 | * 12 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 13 | * any time. 14 | * 15 | * Visible for testing. 16 | */ 17 | interface DoubleAccumulation { 18 | /** The current value. */ 19 | val value: Double 20 | 21 | /** Sampled measurements recorded during this accumulation. */ 22 | val exemplars: List 23 | 24 | companion object { 25 | fun create(value: Double, exemplars: List): DoubleAccumulation { 26 | return Implementation(value, exemplars) 27 | } 28 | 29 | fun create(value: Double): DoubleAccumulation { 30 | return create(value, emptyList()) 31 | } 32 | 33 | data class Implementation( 34 | override val value: Double, 35 | override val exemplars: List 36 | ) : DoubleAccumulation 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/aggregator/LongAccumulation.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.aggregator 6 | 7 | import io.opentelemetry.kotlin.sdk.metrics.data.ExemplarData 8 | 9 | /** An accumulation representing `long` values and exemplars. */ 10 | interface LongAccumulation { 11 | /** The current value. */ 12 | val value: Long 13 | 14 | /** Sampled measurements recorded during this accumulation. */ 15 | val exemplars: List 16 | 17 | companion object { 18 | fun create(value: Long, exemplars: List = emptyList()): LongAccumulation { 19 | return Implementation(value, exemplars) 20 | } 21 | data class Implementation( 22 | override val value: Long, 23 | override val exemplars: List 24 | ) : LongAccumulation 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/aggregator/package-info.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /** 6 | * Metric aggregators. 7 | * 8 | * This package is internal and is hence not for public use. Its APIs are unstable and can change at 9 | * any time. 10 | */ 11 | package io.opentelemetry.kotlin.sdk.metrics.internal.aggregator 12 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/debug/NoSourceInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.debug 6 | 7 | internal enum class NoSourceInfo : SourceInfo { 8 | INSTANCE; 9 | 10 | override fun shortDebugString(): String { 11 | return "unknown source" 12 | } 13 | 14 | override fun multiLineDebugString(): String { 15 | return """ at unknown source 16 | ${DebugConfig.howToEnableMessage}""" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/debug/SourceInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.debug 6 | 7 | /** 8 | * An interface that can be used to record the (runtime) source of registered metrics in the sdk. 9 | * 10 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 11 | * any time. 12 | */ 13 | interface SourceInfo { 14 | /** 15 | * Returns a debugging string to report where a given metric was registered. 16 | * 17 | * Example: `MyFile.java:15` 18 | */ 19 | fun shortDebugString(): String 20 | 21 | /** 22 | * Returns a multi-line debugging string to report where a given metric was registered. 23 | * 24 | * Example: 25 | * 26 | *
 at full.package.name.method MyFile.java:15 at full.packae.name.otherMethod
27 |      * MyOtherFile.java:10 
* 28 | */ 29 | fun multiLineDebugString(): String 30 | 31 | companion object { 32 | /** Returns a source info that asks the user to register information. */ 33 | fun noSourceInfo(): SourceInfo { 34 | return NoSourceInfo.INSTANCE 35 | } 36 | 37 | /** 38 | * Constructs source information form the current stack. 39 | * 40 | * This will attempt to ignore SDK classes. 41 | */ 42 | fun fromCurrentStack(): SourceInfo { 43 | return noSourceInfo() 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/state/BoundStorageHandle.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.state 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | /** 11 | * A bound handle for recording measurements against a particular set of attributes. 12 | * 13 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 14 | * any time. 15 | */ 16 | interface BoundStorageHandle { 17 | /** Records a measurement. */ 18 | fun recordLong(value: Long, attributes: Attributes, context: Context) 19 | 20 | /** Records a measurement. */ 21 | fun recordDouble(value: Double, attributes: Attributes, context: Context) 22 | 23 | /** Release this handle back to the storage. */ 24 | fun release() 25 | } 26 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/state/DeltaAccumulation.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.state 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.sdk.metrics.internal.export.CollectionHandle 9 | 10 | /** 11 | * Synchronous recording of delta-accumulated measurements. 12 | * 13 | * This stores in-progress metric values that haven't been exported yet. 14 | */ 15 | internal class DeltaAccumulation(private val recording: Map) { 16 | private val readers: MutableSet = CollectionHandle.mutableSet() 17 | 18 | /** Returns true if this accumulation was read by the [CollectionHandle]. */ 19 | fun wasReadBy(handle: CollectionHandle): Boolean { 20 | return readers.contains(handle) 21 | } 22 | 23 | /** Returns true if all readers in the given set have read this accumulation. */ 24 | fun wasReadByAll(handles: Set): Boolean { 25 | return readers.containsAll(handles) 26 | } 27 | 28 | /** 29 | * Reads the current delta accumulation. 30 | * 31 | * @param handle The reader of the accumulation. 32 | * @return the accumulation. 33 | */ 34 | fun read(handle: CollectionHandle): Map { 35 | readers.add(handle) 36 | return recording 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/state/DuplicateMetricStorageException.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.state 6 | 7 | import io.opentelemetry.kotlin.sdk.metrics.internal.descriptor.MetricDescriptor 8 | 9 | /** 10 | * There are multiple metrics defined with the same name/identity. 11 | * 12 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 13 | * any time. 14 | */ 15 | class DuplicateMetricStorageException( 16 | val existing: MetricDescriptor, 17 | val conflict: MetricDescriptor, 18 | message: String 19 | ) : 20 | IllegalArgumentException( 21 | "$message Found previous metric: $existing, cannot register metric: $conflict" 22 | ) { 23 | 24 | companion object { 25 | private const val serialVersionUID = 1547329629200005982L 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/state/ExponentialCounter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.state 6 | 7 | import kotlin.js.JsName 8 | 9 | /** 10 | * Interface for use as backing data structure for exponential histogram buckets. 11 | * 12 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 13 | * any time. 14 | */ 15 | interface ExponentialCounter { 16 | /** 17 | * The first index with a recording. May be negative. 18 | * 19 | * @return the first index with a recording. 20 | */ 21 | val indexStart: Int 22 | 23 | /** 24 | * The last index with a recording. May be negative. 25 | * 26 | * @return The last index with a recording. 27 | */ 28 | val indexEnd: Int 29 | 30 | /** 31 | * Persist new data at index, incrementing by delta amount. 32 | * 33 | * @param index The index of where to perform the incrementation. 34 | * @param delta How much to increment the index by. 35 | * @return success status. 36 | */ 37 | fun increment(index: Int, delta: Long): Boolean 38 | 39 | /** 40 | * Get the number of recordings for the given index. 41 | * 42 | * @return the number of recordings for the index. 43 | */ 44 | operator fun get(index: Int): Long 45 | 46 | /** 47 | * Boolean denoting if the backing structure has recordings or not. 48 | * 49 | * @return true if no recordings, false if at least one recording. 50 | */ 51 | @JsName("isExponentialCounterEmpty") fun isEmpty(): Boolean 52 | } 53 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/state/MultiBoundStorageHandle.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.state 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | 10 | /** Storage handle that aggregates across several instances. */ 11 | internal class MultiBoundStorageHandle(handles: List) : BoundStorageHandle { 12 | private val underlyingHandles: List 13 | 14 | init { 15 | underlyingHandles = handles 16 | } 17 | 18 | override fun recordLong(value: Long, attributes: Attributes, context: Context) { 19 | for (handle in underlyingHandles) { 20 | handle.recordLong(value, attributes, context) 21 | } 22 | } 23 | 24 | override fun recordDouble(value: Double, attributes: Attributes, context: Context) { 25 | for (handle in underlyingHandles) { 26 | handle.recordDouble(value, attributes, context) 27 | } 28 | } 29 | 30 | override fun release() { 31 | for (handle in underlyingHandles) { 32 | handle.release() 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/state/MultiWritableMetricStorage.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.state 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | 9 | internal class MultiWritableMetricStorage( 10 | private val underlyingMetrics: List 11 | ) : WriteableMetricStorage { 12 | 13 | override fun bind(attributes: Attributes): BoundStorageHandle { 14 | val handles = underlyingMetrics.map { metric -> metric.bind(attributes) } 15 | return MultiBoundStorageHandle(handles) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/state/TemporalityUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.state 6 | 7 | import io.opentelemetry.kotlin.sdk.metrics.data.AggregationTemporality 8 | 9 | internal object TemporalityUtils { 10 | /** 11 | * Resolves which aggregation temporality to use for a given measurement. 12 | * 13 | * @param supported All aggregation temporalities supported by the exporter. 14 | * @param preferred The preferred temporality of the exporter. 15 | */ 16 | fun resolveTemporality( 17 | supported: Set, 18 | preferred: AggregationTemporality? 19 | ): AggregationTemporality { 20 | // Next assume preferred should always win. 21 | if (preferred != null) { 22 | return preferred 23 | } 24 | // If the exporter doesn't support the configured temporality (or there was none) and 25 | // doesn't 26 | // have a preference, use CUMULATIVE if we can, otherwise DELTA. 27 | if (supported.contains(AggregationTemporality.CUMULATIVE)) { 28 | return AggregationTemporality.CUMULATIVE 29 | } 30 | return if (supported.contains(AggregationTemporality.DELTA)) { 31 | AggregationTemporality.DELTA 32 | } else AggregationTemporality.CUMULATIVE 33 | // Default to cumulative if there are no supported temporalities reported. 34 | // This is likely a bug in the exporter. 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/state/WriteableMetricStorage.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.state 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.context.Context 9 | import io.opentelemetry.kotlin.sdk.metrics.data.MetricData 10 | 11 | /** 12 | * Stores [MetricData] and allows synchronous writes of measurements. 13 | * 14 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 15 | * any time. 16 | */ 17 | interface WriteableMetricStorage { 18 | /** Bind an efficient storage handle for a set of attributes. */ 19 | fun bind(attributes: Attributes): BoundStorageHandle 20 | 21 | /** Records a measurement. */ 22 | fun recordLong(value: Long, attributes: Attributes, context: Context) { 23 | val handle: BoundStorageHandle = bind(attributes) 24 | try { 25 | handle.recordLong(value, attributes, context) 26 | } finally { 27 | handle.release() 28 | } 29 | } 30 | 31 | /** Records a measurement. */ 32 | fun recordDouble(value: Double, attributes: Attributes, context: Context) { 33 | val handle: BoundStorageHandle = bind(attributes) 34 | try { 35 | handle.recordDouble(value, attributes, context) 36 | } finally { 37 | handle.release() 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/view/RegisteredView.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.view 6 | 7 | import io.opentelemetry.kotlin.sdk.metrics.view.InstrumentSelector 8 | import io.opentelemetry.kotlin.sdk.metrics.view.View 9 | 10 | /** 11 | * Internal representation of a [View] and [InstrumentSelector]. 12 | * 13 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 14 | * any time. 15 | */ 16 | interface RegisteredView { 17 | /** Instrument fitler for applying this view. */ 18 | val instrumentSelector: InstrumentSelector 19 | 20 | /** The view to apply. */ 21 | val view: View 22 | 23 | companion object { 24 | fun create(selector: InstrumentSelector, view: View): RegisteredView { 25 | return Implementation(selector, view) 26 | } 27 | } 28 | class Implementation( 29 | override val instrumentSelector: InstrumentSelector, 30 | override val view: View 31 | ) : RegisteredView 32 | } 33 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/view/StringPredicates.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.view 6 | 7 | /** 8 | * Re-usable string predicates. 9 | * 10 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 11 | * any time. 12 | */ 13 | object StringPredicates { 14 | /** A string predicate that matches all strings. */ 15 | val ALL: (String) -> Boolean = { _: String -> true } 16 | 17 | /** A string predicate that does exact string matching. */ 18 | fun exact(match: String): (String) -> Boolean { 19 | return { anObject: Any? -> match == anObject } 20 | } 21 | 22 | /** A string predicate that matches against a regular expression. */ 23 | fun regex(pattern: Regex): (String) -> Boolean { 24 | return { input: String -> pattern.matches(input) } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/view/ViewRegistryBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.view 6 | 7 | import io.opentelemetry.kotlin.sdk.metrics.view.InstrumentSelector 8 | import io.opentelemetry.kotlin.sdk.metrics.view.View 9 | 10 | /** 11 | * Builder for [ViewRegistry]. 12 | * 13 | * This class is internal and is hence not for public use. Its APIs are unstable and can change at 14 | * any time. 15 | */ 16 | class ViewRegistryBuilder internal constructor() { 17 | private val orderedViews: MutableList = mutableListOf() 18 | 19 | /** Returns the [ViewRegistry]. */ 20 | fun build(): ViewRegistry { 21 | return ViewRegistry(orderedViews.toList()) 22 | } 23 | 24 | /** 25 | * Adds a new view to the registry. 26 | * 27 | * @param selector The instruments that should have their defaults altered. 28 | * @param view The [View] metric definition. 29 | * @return this 30 | */ 31 | fun addView(selector: InstrumentSelector, view: View): ViewRegistryBuilder { 32 | orderedViews.add(RegisteredView.create(selector, view)) 33 | return this 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/math.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin.sdk.metrics 2 | 3 | internal object Math { 4 | fun scalb(d: Double, n: Int): Double { 5 | // Todo: provide a correct implementation to enable ExponentialHistograms 6 | return 1.0 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/view/NoAggregation.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.view 6 | 7 | import io.opentelemetry.kotlin.sdk.metrics.exemplar.ExemplarFilter 8 | import io.opentelemetry.kotlin.sdk.metrics.internal.aggregator.Aggregator 9 | import io.opentelemetry.kotlin.sdk.metrics.internal.descriptor.InstrumentDescriptor 10 | 11 | /** Configuration representing no aggregation. */ 12 | internal class NoAggregation private constructor() : Aggregation() { 13 | override fun createAggregator( 14 | instrumentDescriptor: InstrumentDescriptor, 15 | exemplarFilter: ExemplarFilter 16 | ): Aggregator { 17 | return Aggregator.empty() as Aggregator 18 | } 19 | 20 | override fun toString(): String { 21 | return "NoAggregation" 22 | } 23 | 24 | companion object { 25 | val INSTANCE: Aggregation = NoAggregation() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/metrics/view/package-info.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /** Metric views. */ 6 | package io.opentelemetry.kotlin.sdk.metrics.view 7 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/metrics/AbstractInstrumentTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics 6 | 7 | import io.kotest.matchers.shouldBe 8 | import io.opentelemetry.kotlin.sdk.metrics.common.InstrumentType 9 | import io.opentelemetry.kotlin.sdk.metrics.common.InstrumentValueType 10 | import io.opentelemetry.kotlin.sdk.metrics.internal.descriptor.InstrumentDescriptor 11 | import kotlin.test.Test 12 | 13 | /** Unit tests for [AbstractInstrument]. */ 14 | internal class AbstractInstrumentTest { 15 | @Test 16 | fun getValues() { 17 | val testInstrument = TestInstrument(INSTRUMENT_DESCRIPTOR) 18 | testInstrument.getDescriptor() shouldBe INSTRUMENT_DESCRIPTOR 19 | } 20 | 21 | private class TestInstrument(descriptor: InstrumentDescriptor?) : 22 | AbstractInstrument(descriptor!!) 23 | 24 | companion object { 25 | private val INSTRUMENT_DESCRIPTOR = 26 | InstrumentDescriptor.create( 27 | "name", 28 | "description", 29 | "1", 30 | InstrumentType.COUNTER, 31 | InstrumentValueType.LONG 32 | ) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/metrics/SdkMeterProviderBuilderTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics 6 | 7 | import io.kotest.matchers.shouldBe 8 | import io.opentelemetry.kotlin.api.metrics.GlobalMeterProvider 9 | import io.opentelemetry.kotlin.sdk.metrics.testing.InMemoryMetricReader 10 | import io.opentelemetry.kotlin.sdk.resources.Resource 11 | import kotlin.test.Test 12 | 13 | internal class SdkMeterProviderBuilderTest { 14 | @Test 15 | fun buildAndRegisterGlobal() { 16 | val meterProvider = SdkMeterProvider.builder().buildAndRegisterGlobal() 17 | try { 18 | GlobalMeterProvider.get() shouldBe meterProvider 19 | } finally { 20 | GlobalMeterProvider.disableGlobalMeterProvider() 21 | } 22 | } 23 | 24 | @Test 25 | fun defaultResource() { 26 | // We need a reader to have a resource. 27 | val meterProvider = 28 | SdkMeterProvider.builder().registerMetricReader(InMemoryMetricReader.create()).build() 29 | meterProvider.sharedState.resource shouldBe Resource.default 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/metrics/exemplar/mock/AttributesProcessorMock.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin.sdk.metrics.exemplar.mock 2 | 3 | import io.opentelemetry.kotlin.api.common.Attributes 4 | import io.opentelemetry.kotlin.context.Context 5 | import io.opentelemetry.kotlin.sdk.metrics.internal.view.AttributesProcessor 6 | import kotlinx.atomicfu.atomic 7 | import kotlinx.atomicfu.update 8 | import kotlinx.collections.immutable.persistentListOf 9 | 10 | class AttributesProcessorMock(private val wrappedProcessor: AttributesProcessor? = null) : 11 | AttributesProcessor() { 12 | 13 | private val store = atomic(persistentListOf()) 14 | 15 | val calls: List 16 | get() { 17 | return store.value 18 | } 19 | 20 | override fun process(incoming: Attributes, context: Context): Attributes { 21 | store.update { it.add(ProcessCall(incoming, context)) } 22 | return if (wrappedProcessor == null) { 23 | incoming 24 | } else { 25 | wrappedProcessor.process(incoming, context) 26 | } 27 | } 28 | 29 | override fun usesContext(): Boolean { 30 | return if (wrappedProcessor == null) { 31 | false 32 | } else { 33 | wrappedProcessor.usesContext() 34 | } 35 | } 36 | 37 | data class ProcessCall(val incoming: Attributes, val context: Context) 38 | } 39 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/debug/DebugConfigTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.debug 6 | 7 | import io.kotest.matchers.booleans.shouldBeFalse 8 | import io.kotest.matchers.booleans.shouldBeTrue 9 | import kotlin.test.Test 10 | 11 | internal class DebugConfigTest { 12 | @Test 13 | fun enableForTests() { 14 | DebugConfig.enableForTesting(true) 15 | DebugConfig.isMetricsDebugEnabled.shouldBeTrue() 16 | DebugConfig.enableForTesting(false) 17 | DebugConfig.isMetricsDebugEnabled.shouldBeFalse() 18 | } 19 | 20 | @Test 21 | fun hasActionableMessage() { 22 | // Ensure error message includes system property. 23 | DebugConfig.howToEnableMessage.contains("-D") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/debug/SourceInfoTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.debug 6 | 7 | import kotlin.test.Test 8 | 9 | internal class SourceInfoTest { 10 | @Test 11 | fun noSourceInfo_includesEnableDebugMessage() { 12 | SourceInfo.noSourceInfo().multiLineDebugString().contains(DebugConfig.howToEnableMessage) 13 | } 14 | /* 15 | @Test 16 | fun doesNotGrabStackWhenDisabled() { 17 | DebugConfig.enableForTesting(false) 18 | assertThat(SourceInfo.fromCurrentStack()).isInstanceOf(NoSourceInfo::class.java) 19 | } 20 | 21 | @Test 22 | fun doesGrabStackWhenEnabled() { 23 | DebugConfig.enableForTesting(true) 24 | assertThat(SourceInfo.fromCurrentStack()).isInstanceOf( 25 | StackTraceSourceInfo::class.java 26 | ) 27 | }*/ 28 | } 29 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/metrics/internal/state/TemporalityUtilsTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.internal.state 6 | 7 | import io.kotest.matchers.shouldBe 8 | import io.opentelemetry.kotlin.sdk.metrics.data.AggregationTemporality 9 | import io.opentelemetry.kotlin.sdk.metrics.internal.state.TemporalityUtils.resolveTemporality 10 | import kotlin.test.Test 11 | 12 | internal class TemporalityUtilsTest { 13 | @Test 14 | fun testUsePreferred() { 15 | resolveTemporality( 16 | AggregationTemporality.values().toSet(), 17 | AggregationTemporality.CUMULATIVE 18 | ) shouldBe AggregationTemporality.CUMULATIVE 19 | resolveTemporality( 20 | AggregationTemporality.values().toSet(), 21 | AggregationTemporality.DELTA 22 | ) shouldBe AggregationTemporality.DELTA 23 | } 24 | 25 | @Test 26 | fun testDefaultToCumulativeIfAble() { 27 | resolveTemporality(AggregationTemporality.values().toSet(), null) shouldBe 28 | AggregationTemporality.CUMULATIVE 29 | resolveTemporality(setOf(AggregationTemporality.CUMULATIVE), null) shouldBe 30 | AggregationTemporality.CUMULATIVE 31 | resolveTemporality(setOf(AggregationTemporality.DELTA), null) shouldBe 32 | AggregationTemporality.DELTA 33 | } 34 | 35 | @Test 36 | fun testHandleErrorScenarios() { 37 | // Default to cumulative if preferred/supported is empty. 38 | resolveTemporality(setOf(), null) shouldBe AggregationTemporality.CUMULATIVE 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/metrics/mock/ExemplarReservoirMock.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin.sdk.metrics.mock 2 | 3 | import io.opentelemetry.kotlin.api.common.Attributes 4 | import io.opentelemetry.kotlin.context.Context 5 | import io.opentelemetry.kotlin.sdk.metrics.data.ExemplarData 6 | import io.opentelemetry.kotlin.sdk.metrics.exemplar.ExemplarReservoir 7 | 8 | class ExemplarReservoirMock(private val result: List = listOf()) : ExemplarReservoir { 9 | var value: Double = 0.0 10 | var attributes: Attributes = Attributes.empty() 11 | var context: Context = Context.root() 12 | 13 | constructor(vararg exemplarData: ExemplarData) : this(exemplarData.toList()) 14 | 15 | override fun offerMeasurement(value: Long, attributes: Attributes, context: Context) { 16 | this.value = value.toDouble() 17 | this.attributes = attributes 18 | this.context = context 19 | } 20 | 21 | override fun offerMeasurement(value: Double, attributes: Attributes, context: Context) { 22 | this.value = value 23 | this.attributes = attributes 24 | this.context = context 25 | } 26 | 27 | override fun collectAndReset(pointAttributes: Attributes): List { 28 | return result 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/metrics/mock/MetricReaderMock.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin.sdk.metrics.mock 2 | 3 | import io.opentelemetry.kotlin.sdk.common.CompletableResultCode 4 | import io.opentelemetry.kotlin.sdk.metrics.data.AggregationTemporality 5 | import io.opentelemetry.kotlin.sdk.metrics.export.MetricReader 6 | 7 | class MetricReaderMock : MetricReader { 8 | override val supportedTemporality: Set 9 | get() = AggregationTemporality.values().toSet() 10 | override val preferredTemporality: AggregationTemporality? 11 | get() = null 12 | 13 | override fun flush(): CompletableResultCode { 14 | return CompletableResultCode.ofSuccess() 15 | } 16 | 17 | override fun shutdown(): CompletableResultCode { 18 | return CompletableResultCode.ofSuccess() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /sdk/sdk-metrics/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/metrics/view/AggregationTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.metrics.view 6 | 7 | import kotlin.test.Test 8 | 9 | /** Simple tests of Aggregation classes API. */ 10 | internal class AggregationTest { 11 | @Test 12 | fun haveToString() { 13 | Aggregation.none().toString().contains("NoAggregation") 14 | Aggregation.defaultAggregation().toString().contains("Default") 15 | Aggregation.lastValue().toString().contains("LastValue") 16 | Aggregation.sum().toString().contains("Sum") 17 | Aggregation.explicitBucketHistogram().toString().contains("ExplicitBucketHistogram") 18 | Aggregation.explicitBucketHistogram(listOf(1.0)) 19 | .toString() 20 | .contains("ExplicitBucketHistogram") 21 | } 22 | 23 | @Test 24 | fun histogramUsesExplicitBucket() { 25 | // Note: This will change when exponential histograms are launched. 26 | Aggregation.histogram().toString().contains("ExplicitBucketHistogram") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /sdk/sdk-testing/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("mpplib") 3 | } 4 | 5 | kotlin { 6 | sourceSets { 7 | val commonMain by getting { 8 | dependencies { 9 | implementation(project(":context")) 10 | implementation(project(":sdk:sdk-all")) 11 | implementation(project(":sdk:sdk-common")) 12 | 13 | implementation(libs.jetbrains.kotlinx.collections.immutable) 14 | implementation(libs.jetbrains.kotlinx.coroutines.core) 15 | } 16 | } 17 | val commonTest by getting { 18 | dependencies { 19 | 20 | implementation(libs.bundles.kotlin.test) 21 | 22 | implementation(libs.kotest.assertions.core) 23 | 24 | implementation(libs.jetbrains.kotlinx.coroutines.test) 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /sdk/sdk-testing/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/testing/time/TestClock.kt: -------------------------------------------------------------------------------- 1 | package io.opentelemetry.kotlin.sdk.testing.time 2 | 3 | import io.opentelemetry.kotlin.api.common.getNanoseconds 4 | import io.opentelemetry.kotlin.sdk.common.Clock 5 | import kotlinx.datetime.Instant 6 | import kotlin.time.Duration 7 | import kotlin.time.ExperimentalTime 8 | 9 | class TestClock private constructor(private var current: Instant) : Clock { 10 | override fun now(): Long { 11 | return current.getNanoseconds() 12 | } 13 | 14 | override fun nanoTime(): Long { 15 | return current.getNanoseconds() 16 | } 17 | 18 | @OptIn(ExperimentalTime::class) 19 | fun advance(duration: Duration) { 20 | current = current.plus(duration) 21 | } 22 | 23 | companion object { 24 | fun create(now: Instant): TestClock { 25 | return TestClock(now) 26 | } 27 | 28 | fun create(): TestClock { 29 | return TestClock(kotlinx.datetime.Clock.System.now()) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /sdk/sdk-trace/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("mpplib") 3 | } 4 | 5 | kotlin { 6 | sourceSets { 7 | val commonMain by getting { 8 | dependencies { 9 | api(project(":context")) 10 | api(project(":api:all")) 11 | api(project(":sdk:sdk-common")) 12 | 13 | implementation(libs.jetbrains.kotlinx.collections.immutable) 14 | implementation(libs.jetbrains.kotlinx.coroutines.core) 15 | } 16 | } 17 | val commonTest by getting { 18 | dependencies { 19 | api(project(":sdk:sdk-testing")) 20 | 21 | implementation(libs.bundles.kotlin.test) 22 | 23 | implementation(libs.kotest.assertions.core) 24 | 25 | implementation(libs.jetbrains.kotlinx.coroutines.test) 26 | 27 | implementation(libs.benasher44.uuid) 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/trace/IdGenerator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace 6 | 7 | /** Interface used by the [SdkTracer] to generate new [SpanId]s and [TraceId]s. */ 8 | interface IdGenerator { 9 | /** 10 | * Generates a new valid `SpanId`. 11 | * 12 | * @return a new valid `SpanId`. 13 | */ 14 | fun generateSpanId(): String 15 | 16 | /** 17 | * Generates a new valid `TraceId`. 18 | * 19 | * @return a new valid `TraceId`. 20 | */ 21 | fun generateTraceId(): String 22 | 23 | companion object { 24 | /** 25 | * Returns a [IdGenerator] that generates purely random IDs, which is the default for 26 | * OpenTelemetry. 27 | * 28 | * The underlying implementation uses [java.util.concurrent.ThreadLocalRandom] for 29 | * randomness but may change in the future. 30 | */ 31 | fun random(): IdGenerator { 32 | // note: uses RandomHolder's platformDefault to account for android. 33 | return RandomIdGenerator.INSTANCE 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/trace/NoopSpanProcessor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace 6 | 7 | import io.opentelemetry.kotlin.context.Context 8 | 9 | internal class NoopSpanProcessor private constructor() : SpanProcessor { 10 | override fun onStart(parentContext: Context, span: ReadWriteSpan) {} 11 | 12 | override fun isStartRequired(): Boolean { 13 | return false 14 | } 15 | 16 | override fun onEnd(span: ReadableSpan) {} 17 | 18 | override fun isEndRequired(): Boolean { 19 | return false 20 | } 21 | 22 | companion object { 23 | private val INSTANCE = NoopSpanProcessor() 24 | val instance: SpanProcessor 25 | get() = INSTANCE 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/trace/RandomIdGenerator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace 6 | 7 | import io.opentelemetry.kotlin.api.trace.SpanId 8 | import io.opentelemetry.kotlin.api.trace.TraceId 9 | import io.opentelemetry.kotlin.sdk.internal.RandomSupplier 10 | import kotlin.random.Random 11 | 12 | internal enum class RandomIdGenerator : IdGenerator { 13 | INSTANCE; 14 | 15 | override fun generateSpanId(): String { 16 | var id: Long 17 | val random: Random = randomSupplier() 18 | do { 19 | id = random.nextLong() 20 | } while (id == INVALID_ID) 21 | return SpanId.fromLong(id) 22 | } 23 | 24 | override fun generateTraceId(): String { 25 | val random: Random = randomSupplier() 26 | val idHi: Long = random.nextLong() 27 | var idLo: Long 28 | do { 29 | idLo = random.nextLong() 30 | } while (idLo == INVALID_ID) 31 | return TraceId.fromLongs(idHi, idLo) 32 | } 33 | 34 | companion object { 35 | private const val INVALID_ID: Long = 0 36 | private val randomSupplier: () -> Random = RandomSupplier.platformDefault() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/trace/ReadWriteSpan.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace 6 | 7 | import io.opentelemetry.kotlin.api.trace.Span 8 | 9 | /** 10 | * A combination of the write methods from the [Span] interface and the read methods from the 11 | * [ReadableSpan] interface. 12 | */ 13 | interface ReadWriteSpan : Span, ReadableSpan 14 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/trace/SdkTracerBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace 6 | 7 | import io.opentelemetry.kotlin.api.trace.Tracer 8 | import io.opentelemetry.kotlin.api.trace.TracerBuilder 9 | import io.opentelemetry.kotlin.sdk.internal.ComponentRegistry 10 | 11 | internal class SdkTracerBuilder( 12 | private val registry: ComponentRegistry, 13 | private val instrumentationName: String 14 | ) : TracerBuilder { 15 | 16 | private var instrumentationVersion: String? = null 17 | 18 | private var schemaUrl: String? = null 19 | 20 | override fun setSchemaUrl(schemaUrl: String?): TracerBuilder { 21 | this.schemaUrl = schemaUrl 22 | return this 23 | } 24 | 25 | override fun setInstrumentationVersion(instrumentationVersion: String?): TracerBuilder { 26 | this.instrumentationVersion = instrumentationVersion 27 | return this 28 | } 29 | 30 | override fun build(): Tracer { 31 | return registry[instrumentationName, instrumentationVersion, schemaUrl] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/trace/export/NoopSpanExporter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace.export 6 | 7 | import io.opentelemetry.kotlin.sdk.common.CompletableResultCode 8 | import io.opentelemetry.kotlin.sdk.trace.data.SpanData 9 | 10 | internal class NoopSpanExporter : SpanExporter { 11 | override fun export(spans: Collection): CompletableResultCode { 12 | return CompletableResultCode.ofSuccess() 13 | } 14 | 15 | override fun flush(): CompletableResultCode { 16 | return CompletableResultCode.ofSuccess() 17 | } 18 | 19 | override fun shutdown(): CompletableResultCode { 20 | return CompletableResultCode.ofSuccess() 21 | } 22 | 23 | companion object { 24 | private val INSTANCE: SpanExporter = NoopSpanExporter() 25 | val instance: SpanExporter 26 | get() = INSTANCE 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/trace/samplers/AlwaysOffSampler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace.samplers 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.api.trace.SpanKind 9 | import io.opentelemetry.kotlin.context.Context 10 | import io.opentelemetry.kotlin.sdk.trace.data.LinkData 11 | 12 | internal enum class AlwaysOffSampler : Sampler { 13 | INSTANCE; 14 | 15 | // Returns a "no" {@link SamplingResult} on {@link Span} sampling. 16 | override fun shouldSample( 17 | parentContext: Context, 18 | traceId: String, 19 | name: String, 20 | spanKind: SpanKind, 21 | attributes: Attributes, 22 | parentLinks: List 23 | ): SamplingResult { 24 | return ImmutableSamplingResult.EMPTY_NOT_SAMPLED_OR_RECORDED_SAMPLING_RESULT 25 | } 26 | 27 | override val description: String 28 | get() = "AlwaysOffSampler" 29 | 30 | override fun toString(): String { 31 | return description 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/trace/samplers/AlwaysOnSampler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace.samplers 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | import io.opentelemetry.kotlin.api.trace.SpanKind 9 | import io.opentelemetry.kotlin.context.Context 10 | import io.opentelemetry.kotlin.sdk.trace.data.LinkData 11 | 12 | internal enum class AlwaysOnSampler : io.opentelemetry.kotlin.sdk.trace.samplers.Sampler { 13 | INSTANCE; 14 | 15 | // Returns a "yes" {@link SamplingResult} on {@link Span} sampling. 16 | override fun shouldSample( 17 | parentContext: Context, 18 | traceId: String, 19 | name: String, 20 | spanKind: SpanKind, 21 | attributes: Attributes, 22 | parentLinks: List 23 | ): SamplingResult { 24 | return ImmutableSamplingResult.EMPTY_RECORDED_AND_SAMPLED_SAMPLING_RESULT 25 | } 26 | 27 | override val description: String 28 | get() = "AlwaysOnSampler" 29 | 30 | override fun toString(): String { 31 | return description 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/trace/samplers/ImmutableSamplingResult.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace.samplers 6 | 7 | import io.opentelemetry.kotlin.api.common.Attributes 8 | 9 | internal abstract class ImmutableSamplingResult : SamplingResult { 10 | abstract override val decision: SamplingDecision 11 | abstract override val attributes: Attributes 12 | 13 | companion object { 14 | val EMPTY_RECORDED_AND_SAMPLED_SAMPLING_RESULT: SamplingResult = 15 | createWithoutAttributes(SamplingDecision.RECORD_AND_SAMPLE) 16 | val EMPTY_NOT_SAMPLED_OR_RECORDED_SAMPLING_RESULT: SamplingResult = 17 | createWithoutAttributes(SamplingDecision.DROP) 18 | val EMPTY_RECORDED_SAMPLING_RESULT: SamplingResult = 19 | createWithoutAttributes(SamplingDecision.RECORD_ONLY) 20 | 21 | fun createSamplingResult( 22 | decision: SamplingDecision, 23 | attributes: Attributes 24 | ): SamplingResult { 25 | return Instance(decision, attributes) 26 | } 27 | 28 | private fun createWithoutAttributes(decision: SamplingDecision): SamplingResult { 29 | return Instance(decision, Attributes.empty()) 30 | } 31 | 32 | private class Instance( 33 | override val decision: SamplingDecision, 34 | override val attributes: Attributes 35 | ) : ImmutableSamplingResult() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonMain/kotlin/io/opentelemetry/kotlin/sdk/trace/samplers/SamplingDecision.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace.samplers 6 | 7 | /** A decision on whether a span should be recorded, recorded and sampled or dropped. */ 8 | enum class SamplingDecision { 9 | /** Span is dropped. The resulting span will be completely no-op. */ 10 | DROP, 11 | 12 | /** 13 | * Span is recorded only. The resulting span will record all information like timings and 14 | * attributes but will not be exported. Downstream [ parent-based][Sampler.parentBased] samplers 15 | * will not sample the span. 16 | */ 17 | RECORD_ONLY, 18 | 19 | /** 20 | * Span is recorded and sampled. The resulting span will record all information like timings and 21 | * attributes and will be exported. 22 | */ 23 | RECORD_AND_SAMPLE 24 | } 25 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/trace/AttributesMapTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace 6 | 7 | import io.kotest.matchers.maps.shouldContainExactly 8 | import io.opentelemetry.kotlin.api.common.AttributeKey.Companion.longKey 9 | import kotlin.test.Test 10 | 11 | class AttributesMapTest { 12 | @Test 13 | fun asMap() { 14 | val attributesMap = AttributesMap(2, Int.MAX_VALUE) 15 | attributesMap.put(longKey("one"), 1L) 16 | attributesMap.put(longKey("two"), 2L) 17 | attributesMap.asMap() shouldContainExactly mapOf(longKey("one") to 1L, longKey("two") to 2L) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/trace/NoopSpanProcessorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace 6 | 7 | import io.kotest.matchers.booleans.shouldBeFalse 8 | import io.opentelemetry.kotlin.context.Context 9 | import io.opentelemetry.kotlin.sdk.trace.MockFactory.createReadWriteSpan 10 | import kotlin.test.Test 11 | 12 | internal class NoopSpanProcessorTest { 13 | 14 | @Test 15 | fun noCrash() { 16 | val readableSpan: ReadableSpan = createReadWriteSpan() 17 | val readWriteSpan: ReadWriteSpan = createReadWriteSpan() 18 | val noopSpanProcessor: SpanProcessor = NoopSpanProcessor.instance 19 | noopSpanProcessor.onStart(Context.root(), readWriteSpan) 20 | noopSpanProcessor.isStartRequired().shouldBeFalse() 21 | noopSpanProcessor.onEnd(readableSpan) 22 | noopSpanProcessor.isEndRequired().shouldBeFalse() 23 | noopSpanProcessor.forceFlush() 24 | noopSpanProcessor.shutdown() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sdk/sdk-trace/src/commonTest/kotlin/io/opentelemetry/kotlin/sdk/trace/RandomIdGeneratorTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenTelemetry Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package io.opentelemetry.kotlin.sdk.trace 6 | 7 | import io.kotest.matchers.shouldNotBe 8 | import io.opentelemetry.kotlin.api.trace.SpanId 9 | import io.opentelemetry.kotlin.api.trace.TraceId 10 | import kotlin.test.Test 11 | 12 | internal class RandomIdGeneratorTest { 13 | @Test 14 | fun defaults() { 15 | val generator = IdGenerator.random() 16 | 17 | // Can't assert values but can assert they're valid, try a lot as a sort of fuzz check. 18 | for (i in 0..99) { 19 | val traceId = generator.generateTraceId() 20 | traceId shouldNotBe TraceId.invalid 21 | val spanId = generator.generateSpanId() 22 | spanId shouldNotBe SpanId.invalid 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /semconv/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("mpplib") 3 | } 4 | 5 | kotlin { 6 | sourceSets { 7 | val commonMain by getting { dependencies { api(project(":api:all")) } } 8 | val commonTest by getting { 9 | dependencies { 10 | implementation(libs.bundles.kotlin.test) 11 | implementation(libs.jetbrains.kotlinx.coroutines.core) 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "opentelemetry-kotlin" 2 | 3 | pluginManagement { 4 | plugins { 5 | id("org.jetbrains.kotlinx.kover") version "0.7.6" 6 | } 7 | repositories { 8 | gradlePluginPortal() 9 | mavenCentral() 10 | } 11 | } 12 | 13 | include(":api:all") 14 | 15 | include(":api:metrics") 16 | 17 | include(":sdk:sdk-trace") 18 | 19 | include(":sdk:sdk-metrics") 20 | 21 | include(":sdk:sdk-testing") 22 | 23 | include(":sdk:sdk-common") 24 | 25 | include(":sdk:sdk-all") 26 | 27 | include(":context") 28 | 29 | include(":semconv") --------------------------------------------------------------------------------