Skip to content

Commit

Permalink
feat(resources): implements service.instance.id (#4608)
Browse files Browse the repository at this point in the history
* feat(node-sdk): implements `service.instance.id`

Implements `service.instance.id`

Signed-off-by: maryliag <marylia.gutierrez@grafana.com>

* implement service instance id by default with env var

use an experimental environment variable to set the default value of `service.instance.id` as default

* Update CHANGELOG.md

Co-authored-by: Marc Pichler <marc.pichler@dynatrace.com>

* create separate add experimental for browser and node

create a function to add experimental default values (currently only service instance id, but others can be added in the future),
with the value being set on the node case, but not on the browser case.

Signed-off-by: maryliag <marylia.gutierrez@grafana.com>

* use resource detector for service instance id

use a resource detector for service instance id

* remove references to env variables

* remove Detector and use DetectorSync

remove the Detector and use the DetectorSync instead. Also mark things as experimental.

Signed-off-by: maryliag <marylia.gutierrez@grafana.com>

* Update packages/opentelemetry-resources/src/platform/node/ServiceInstanceIDDetectorSync.ts

Co-authored-by: Marc Pichler <marc.pichler@dynatrace.com>

* rename ServiceInstanceIDDetector to ServiceInstanceIDDetectorSync

* change ID to Id

* renaming something temp so git will pick up the name change

it was not picking up the case change on previous commit

* update to final name using Id

---------

Signed-off-by: maryliag <marylia.gutierrez@grafana.com>
Co-authored-by: Marc Pichler <marc.pichler@dynatrace.com>
  • Loading branch information
maryliag and pichlermarc authored Apr 15, 2024
1 parent 3438777 commit 583cc7c
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 31 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/

### :rocket: (Enhancement)

feat(sdk-trace-base): log resource attributes in ConsoleSpanExporter [#4605](https://github.com/open-telemetry/opentelemetry-js/pull/4605) @pichlermarc
* feat(sdk-trace-base): log resource attributes in ConsoleSpanExporter [#4605](https://github.com/open-telemetry/opentelemetry-js/pull/4605) @pichlermarc
* feat(resources): new experimental detector ServiceInstanceIdDetectorSync that sets the value for `service.instance.id` as random UUID.

### :bug: (Bug Fix)

Expand Down
91 changes: 86 additions & 5 deletions experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {
processDetector,
hostDetector,
Resource,
serviceInstanceIdDetectorSync,
} from '@opentelemetry/resources';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { logs } from '@opentelemetry/api-logs';
Expand All @@ -70,6 +71,7 @@ import {
import {
SEMRESATTRS_HOST_NAME,
SEMRESATTRS_PROCESS_PID,
SEMRESATTRS_SERVICE_INSTANCE_ID,
} from '@opentelemetry/semantic-conventions';

const DefaultContextManager = semver.gte(process.version, '14.8.0')
Expand Down Expand Up @@ -126,6 +128,7 @@ describe('Node SDK', () => {
assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider));
assert.ok(!(logs.getLoggerProvider() instanceof LoggerProvider));
delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});

it('should register a diag logger with OTEL_LOG_LEVEL', () => {
Expand All @@ -145,6 +148,7 @@ describe('Node SDK', () => {
});

delete env.OTEL_LOG_LEVEL;
sdk.shutdown();
});

it('should not register a diag logger with OTEL_LOG_LEVEL unset', () => {
Expand All @@ -158,6 +162,7 @@ describe('Node SDK', () => {
sdk.start();

assert.strictEqual(spy.callCount, 0);
sdk.shutdown();
});

it('should register a tracer provider if an exporter is provided', async () => {
Expand All @@ -180,6 +185,7 @@ describe('Node SDK', () => {
const apiTracerProvider =
trace.getTracerProvider() as ProxyTracerProvider;
assert.ok(apiTracerProvider.getDelegate() instanceof NodeTracerProvider);
await sdk.shutdown();
});

it('should register a tracer provider if an exporter is provided via env', async () => {
Expand All @@ -203,6 +209,7 @@ describe('Node SDK', () => {
trace.getTracerProvider() as ProxyTracerProvider;
assert.ok(apiTracerProvider.getDelegate() instanceof NodeTracerProvider);
delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});

it('should register a tracer provider if span processors are provided', async () => {
Expand Down Expand Up @@ -240,6 +247,7 @@ describe('Node SDK', () => {
assert(listOfProcessors[0] instanceof NoopSpanProcessor);
assert(listOfProcessors[1] instanceof SimpleSpanProcessor);
assert(listOfProcessors[2] instanceof BatchSpanProcessor);
await sdk.shutdown();
});

it('should register a meter provider if a reader is provided', async () => {
Expand Down Expand Up @@ -446,6 +454,7 @@ describe('Node SDK', () => {
namespace: 'default',
version: '0.0.1',
});
await sdk.shutdown();
});
});

Expand Down Expand Up @@ -497,6 +506,7 @@ describe('Node SDK', () => {
namespace: 'default',
version: '0.0.1',
});
await sdk.shutdown();
});
});

Expand Down Expand Up @@ -551,6 +561,7 @@ describe('Node SDK', () => {
/{\s+"service\.instance\.id":\s+"627cc493",\s+"service\.name":\s+"my-service",\s+"service\.namespace":\s+"default",\s+"service\.version":\s+"0.0.1"\s+}\s*/gm
)
);
await sdk.shutdown();
});

describe('with a faulty environment variable', () => {
Expand Down Expand Up @@ -578,6 +589,7 @@ describe('Node SDK', () => {
'EnvDetector failed: Attribute value should be a ASCII string with a length not exceed 255 characters.'
)
);
await sdk.shutdown();
});
});
});
Expand All @@ -595,6 +607,7 @@ describe('Node SDK', () => {
assertServiceResource(resource, {
name: 'config-set-name',
});
await sdk.shutdown();
});

it('should configure service name via OTEL_SERVICE_NAME env var', async () => {
Expand All @@ -609,6 +622,7 @@ describe('Node SDK', () => {
name: 'env-set-name',
});
delete process.env.OTEL_SERVICE_NAME;
await sdk.shutdown();
});

it('should favor config set service name over OTEL_SERVICE_NAME env set service name', async () => {
Expand All @@ -625,11 +639,12 @@ describe('Node SDK', () => {
name: 'config-set-name',
});
delete process.env.OTEL_SERVICE_NAME;
await sdk.shutdown();
});

it('should configure service name via OTEL_RESOURCE_ATTRIBUTES env var', async () => {
process.env.OTEL_RESOURCE_ATTRIBUTES =
'service.name=resource-env-set-name';
'service.name=resource-env-set-name,service.instance.id=my-instance-id';
const sdk = new NodeSDK();

sdk.start();
Expand All @@ -638,13 +653,15 @@ describe('Node SDK', () => {

assertServiceResource(resource, {
name: 'resource-env-set-name',
instanceId: 'my-instance-id',
});
delete process.env.OTEL_RESOURCE_ATTRIBUTES;
await sdk.shutdown();
});

it('should favor config set service name over OTEL_RESOURCE_ATTRIBUTES env set service name', async () => {
process.env.OTEL_RESOURCE_ATTRIBUTES =
'service.name=resource-env-set-name';
'service.name=resource-env-set-name,service.instance.id=my-instance-id';
const sdk = new NodeSDK({
serviceName: 'config-set-name',
});
Expand All @@ -655,8 +672,55 @@ describe('Node SDK', () => {

assertServiceResource(resource, {
name: 'config-set-name',
instanceId: 'my-instance-id',
});
delete process.env.OTEL_RESOURCE_ATTRIBUTES;
await sdk.shutdown();
});
});

describe('configureServiceInstanceId', async () => {
it('should configure service instance id via OTEL_RESOURCE_ATTRIBUTES env var', async () => {
process.env.OTEL_RESOURCE_ATTRIBUTES =
'service.instance.id=627cc493,service.name=my-service';
const sdk = new NodeSDK();

sdk.start();
const resource = sdk['_resource'];
await resource.waitForAsyncAttributes?.();

assertServiceResource(resource, {
name: 'my-service',
instanceId: '627cc493',
});
delete process.env.OTEL_RESOURCE_ATTRIBUTES;
sdk.shutdown();
});

it('should configure service instance id with random UUID', async () => {
const sdk = new NodeSDK({
autoDetectResources: true,
resourceDetectors: [
processDetector,
envDetector,
hostDetector,
serviceInstanceIdDetectorSync,
],
});

sdk.start();
const resource = sdk['_resource'];
await resource.waitForAsyncAttributes?.();

const UUID_REGEX =
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
assert.equal(
UUID_REGEX.test(
resource.attributes[SEMRESATTRS_SERVICE_INSTANCE_ID]?.toString() || ''
),
true
);
await sdk.shutdown();
});
});

Expand All @@ -671,7 +735,7 @@ describe('Node SDK', () => {

it('should not register a trace provider', async () => {
const sdk = new NodeSDK({});
await sdk.start();
sdk.start();

assert.strictEqual(
(trace.getTracerProvider() as ProxyTracerProvider).getDelegate(),
Expand All @@ -694,7 +758,7 @@ describe('Node SDK', () => {
metricReader: metricReader,
autoDetectResources: false,
});
await sdk.start();
sdk.start();

assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider));

Expand Down Expand Up @@ -730,6 +794,7 @@ describe('Node SDK', () => {
await resource.waitForAsyncAttributes?.();

assert.deepStrictEqual(resource, Resource.empty());
await sdk.shutdown();
});
});
});
Expand Down Expand Up @@ -758,6 +823,7 @@ describe('Node SDK', () => {

assert.strictEqual(span.spanContext().spanId, 'constant-test-span-id');
assert.strictEqual(span.spanContext().traceId, 'constant-test-trace-id');
await sdk.shutdown();
});
});
});
Expand Down Expand Up @@ -786,6 +852,7 @@ describe('setup exporter from env', () => {
assert(sdk['_tracerProvider'] instanceof TracerProviderWithEnvExporters);
assert(listOfProcessors.length === 1);
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
await sdk.shutdown();
});
it('ignore env exporter when user provides exporter to sdk config', async () => {
const traceExporter = new ConsoleSpanExporter();
Expand All @@ -802,6 +869,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors.length === 1);
assert(listOfProcessors[0] instanceof SimpleSpanProcessor === false);
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
await sdk.shutdown();
});
it('ignores default env exporter when user provides span processor to sdk config', async () => {
const traceExporter = new ConsoleSpanExporter();
Expand All @@ -819,6 +887,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors.length === 1);
assert(listOfProcessors[0] instanceof SimpleSpanProcessor);
assert(listOfProcessors[0] instanceof BatchSpanProcessor === false);
await sdk.shutdown();
});
it('ignores env exporter when user provides tracer exporter to sdk config and sets exporter via env', async () => {
env.OTEL_TRACES_EXPORTER = 'console';
Expand All @@ -837,6 +906,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors[0] instanceof SimpleSpanProcessor === false);
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});
it('should only create one span processor when configured using env vars and config', async () => {
env.OTEL_TRACES_EXPORTER = 'console';
Expand All @@ -852,6 +922,7 @@ describe('setup exporter from env', () => {
);
assert.strictEqual(listOfProcessors.length, 1);
delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});
it('use otlp exporter and defined exporter protocol env value', async () => {
env.OTEL_TRACES_EXPORTER = 'otlp';
Expand All @@ -866,6 +937,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
delete env.OTEL_TRACES_EXPORTER;
delete env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL;
await sdk.shutdown();
});
it('use noop span processor when user sets env exporter to none', async () => {
env.OTEL_TRACES_EXPORTER = 'none';
Expand All @@ -879,6 +951,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors.length === 0);
assert(activeProcessor instanceof NoopSpanProcessor);
delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});
it('log warning that sdk will not be initialized when exporter is set to none', async () => {
env.OTEL_TRACES_EXPORTER = 'none';
Expand All @@ -890,16 +963,18 @@ describe('setup exporter from env', () => {
'OTEL_TRACES_EXPORTER contains "none". SDK will not be initialized.'
);
delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});
it('use default otlp exporter when user does not set exporter via env or config', async () => {
const sdk = new NodeSDK();
await sdk.start();
sdk.start();

const listOfProcessors =
sdk['_tracerProvider']!['_registeredSpanProcessors']!;
assert(sdk['_tracerProvider'] instanceof TracerProviderWithEnvExporters);
assert(listOfProcessors.length === 1);
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
await sdk.shutdown();
});
it('use default otlp exporter when empty value is provided for exporter via env', async () => {
env.OTEL_TRACES_EXPORTER = '';
Expand All @@ -912,6 +987,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors.length === 1);
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
env.OTEL_TRACES_EXPORTER = '';
await sdk.shutdown();
});

it('use only default exporter when none value is provided with other exporters', async () => {
Expand All @@ -926,6 +1002,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors[0] instanceof BatchSpanProcessor);

delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});
it('log warning that only default exporter will be used since exporter list contains none with other exports ', async () => {
env.OTEL_TRACES_EXPORTER = 'otlp,zipkin,none';
Expand All @@ -937,6 +1014,7 @@ describe('setup exporter from env', () => {
'OTEL_TRACES_EXPORTER contains "none" along with other exporters. Using default otlp exporter.'
);
delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});
it('should warn that provided exporter value is unrecognized and not able to be set up', async () => {
env.OTEL_TRACES_EXPORTER = 'invalid';
Expand All @@ -954,6 +1032,7 @@ describe('setup exporter from env', () => {
);

delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});
it('setup zipkin, jaeger and otlp exporters', async () => {
env.OTEL_TRACES_EXPORTER = 'zipkin, otlp, jaeger';
Expand All @@ -971,6 +1050,7 @@ describe('setup exporter from env', () => {

delete env.OTEL_TRACES_EXPORTER;
delete env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL;
await sdk.shutdown();
});
it('use the console exporter', async () => {
env.OTEL_TRACES_EXPORTER = 'console, otlp';
Expand All @@ -983,5 +1063,6 @@ describe('setup exporter from env', () => {
assert(listOfProcessors[0] instanceof SimpleSpanProcessor);
assert(listOfProcessors[1] instanceof BatchSpanProcessor);
delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});
});
15 changes: 0 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 583cc7c

Please sign in to comment.