Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions exporters/otlp/all/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ apply<io.opentelemetry.gradle.OtelVersionClassPlugin>()
description = "OpenTelemetry Protocol (OTLP) Exporters"
otelJava.moduleName.set("io.opentelemetry.exporter.otlp")
otelJava.osgiOptionalPackages.set(listOf("io.opentelemetry.api.incubator.config"))
// io.grpc is not an OSGi bundle and has no package versioning; must use unversioned optional.
otelJava.osgiUnversionedOptionalPackages.set(listOf("io.grpc"))
// io.grpc and org.jspecify.annotations are not OSGi bundles; must use unversioned optional.
otelJava.osgiUnversionedOptionalPackages.set(listOf("io.grpc", "org.jspecify.annotations"))
base.archivesName.set("opentelemetry-exporter-otlp")

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;

import io.github.netmikey.logunit.api.LogCapturer;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.metrics.internal.state.MetricStorageRegistry;
Expand All @@ -28,6 +29,8 @@ class IdentityTest {
@RegisterExtension
LogCapturer viewRegistryLogs = LogCapturer.create().captureForType(ViewRegistry.class);

@RegisterExtension LogCapturer sdkMeterLogs = LogCapturer.create().captureForType(SdkMeter.class);

private InMemoryMetricReader reader;
private SdkMeterProviderBuilder builder;

Expand Down Expand Up @@ -1092,6 +1095,55 @@ void sameMeterDifferentInstrumentIncompatibleViewAggregation() {
.hasSize(1);
}

@Test
void viewNameNotValidated() {
// View names are not validated against the instrument name pattern. When a view sets a name
// that would be rejected if used directly as an instrument name (e.g. starts with a digit),
// the SDK accepts it and produces a metric with the invalid name without logging a warning.
SdkMeterProvider meterProvider =
builder
.registerView(
InstrumentSelector.builder().setType(InstrumentType.COUNTER).build(),
View.builder().setName("1invalid-name").build())
.build();

LongCounter counter = meterProvider.get("meter1").counterBuilder("counter1").build();
counter.add(10);

assertThat(counter.isEnabled()).isTrue();
assertThat(reader.collectAllMetrics())
.satisfiesExactlyInAnyOrder(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(forMeter("meter1"))
.hasName("1invalid-name")
.hasLongSumSatisfying(
sum -> sum.hasPointsSatisfying(point -> point.hasValue(10))));

assertThat(metricStorageRegistryLogs.getEvents()).hasSize(0);
assertThat(viewRegistryLogs.getEvents()).hasSize(0);
}

@Test
@SuppressLogger(SdkMeter.class)
void instrumentWithInvalidName() {
// When an instrument is initialized with an invalid name, a noop instrument is returned
Comment thread
jack-berg marked this conversation as resolved.
// and a warning is logged. No metric data is produced.
SdkMeterProvider meterProvider = builder.build();

LongCounter counter = meterProvider.get("meter1").counterBuilder("1invalid-name").build();
counter.add(10);

assertThat(counter.isEnabled()).isFalse();
assertThat(reader.collectAllMetrics()).isEmpty();
assertThat(sdkMeterLogs.getEvents())
.allSatisfy(
logEvent ->
assertThat(logEvent.getMessage())
.contains("Instrument name \"1invalid-name\" is invalid"))
.hasSize(1);
}

private static InstrumentationScopeInfo forMeter(String meterName) {
return InstrumentationScopeInfo.create(meterName);
}
Expand Down
Loading