Skip to content

Commit

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

Signed-off-by: maryliag <marylia.gutierrez@grafana.com>
  • Loading branch information
maryliag committed Apr 5, 2024
1 parent c046867 commit 059622b
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/

### :rocket: (Enhancement)

feat(sdk-node): set value for `service.instance.id` as random UUID when not defined by environment variable or cloud provider.

### :bug: (Bug Fix)

* fix(sdk-trace-web): fix invalid timings in span events [#4486](https://github.com/open-telemetry/opentelemetry-js/pull/4486) @Abinet18
Expand Down
80 changes: 75 additions & 5 deletions experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,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 +127,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 +147,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 +161,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 +184,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 +208,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 +246,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 @@ -547,6 +554,7 @@ describe('Node SDK', () => {
namespace: 'default',
version: '0.0.1',
});
await sdk.shutdown();
});
});

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

Expand Down Expand Up @@ -652,6 +661,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 @@ -679,6 +689,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 @@ -696,6 +707,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 @@ -710,6 +722,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 @@ -726,11 +739,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 @@ -739,13 +753,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 @@ -756,8 +772,45 @@ 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 () => {
process.env.OTEL_RESOURCE_ATTRIBUTES = 'service.name=my-service';
const sdk = new NodeSDK();

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

assert.equal(
resource.attributes[SEMRESATTRS_SERVICE_INSTANCE_ID]?.toString().length,
36
);
delete process.env.OTEL_RESOURCE_ATTRIBUTES;
await sdk.shutdown();
});
});

Expand All @@ -772,7 +825,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 @@ -795,7 +848,7 @@ describe('Node SDK', () => {
metricReader: metricReader,
autoDetectResources: false,
});
await sdk.start();
sdk.start();

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

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

assert.deepStrictEqual(resource, Resource.empty());
await sdk.shutdown();
});
});
});
Expand Down Expand Up @@ -859,6 +913,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 @@ -887,6 +942,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 @@ -903,6 +959,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 @@ -920,6 +977,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 @@ -938,6 +996,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 @@ -953,6 +1012,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 @@ -967,6 +1027,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 @@ -980,6 +1041,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 @@ -991,16 +1053,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 @@ -1013,6 +1077,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 @@ -1027,6 +1092,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 @@ -1038,6 +1104,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 @@ -1055,6 +1122,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 @@ -1072,6 +1140,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 @@ -1084,5 +1153,6 @@ describe('setup exporter from env', () => {
assert(listOfProcessors[0] instanceof SimpleSpanProcessor);
assert(listOfProcessors[1] instanceof BatchSpanProcessor);
delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});
});
21 changes: 13 additions & 8 deletions packages/opentelemetry-resources/src/Resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@
*/

import { diag } from '@opentelemetry/api';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
import {
SEMRESATTRS_SERVICE_NAME,
SEMRESATTRS_TELEMETRY_SDK_LANGUAGE,
SEMRESATTRS_TELEMETRY_SDK_NAME,
SEMRESATTRS_TELEMETRY_SDK_VERSION,
} from '@opentelemetry/semantic-conventions';
import { SDK_INFO } from '@opentelemetry/core';
import { ResourceAttributes } from './types';
import { defaultServiceName } from './platform';
Expand Down Expand Up @@ -51,13 +56,13 @@ export class Resource implements IResource {
*/
static default(): IResource {
return new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: defaultServiceName(),
[SemanticResourceAttributes.TELEMETRY_SDK_LANGUAGE]:
SDK_INFO[SemanticResourceAttributes.TELEMETRY_SDK_LANGUAGE],
[SemanticResourceAttributes.TELEMETRY_SDK_NAME]:
SDK_INFO[SemanticResourceAttributes.TELEMETRY_SDK_NAME],
[SemanticResourceAttributes.TELEMETRY_SDK_VERSION]:
SDK_INFO[SemanticResourceAttributes.TELEMETRY_SDK_VERSION],
[SEMRESATTRS_SERVICE_NAME]: defaultServiceName(),
[SEMRESATTRS_TELEMETRY_SDK_LANGUAGE]:
SDK_INFO[SEMRESATTRS_TELEMETRY_SDK_LANGUAGE],
[SEMRESATTRS_TELEMETRY_SDK_NAME]:
SDK_INFO[SEMRESATTRS_TELEMETRY_SDK_NAME],
[SEMRESATTRS_TELEMETRY_SDK_VERSION]:
SDK_INFO[SEMRESATTRS_TELEMETRY_SDK_VERSION],
});
}

Expand Down
Loading

0 comments on commit 059622b

Please sign in to comment.