From 363c6655fc0c751cd00f15218fffbd8e46d451f9 Mon Sep 17 00:00:00 2001
From: Naseem Ullah <24660299+naseemkullah@users.noreply.github.com>
Date: Mon, 23 May 2022 20:25:29 -0400
Subject: [PATCH] feat(node-sdk): add serviceName config option
---
experimental/CHANGELOG.md | 1 +
.../packages/opentelemetry-sdk-node/README.md | 4 ++
.../opentelemetry-sdk-node/src/sdk.ts | 34 ++++++---
.../opentelemetry-sdk-node/src/types.ts | 9 +--
.../opentelemetry-sdk-node/test/sdk.test.ts | 72 +++++++++++++++++++
.../test/util/resource-assertions.ts | 2 +-
6 files changed, 109 insertions(+), 13 deletions(-)
diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md
index 027a58898fe..0ec30255168 100644
--- a/experimental/CHANGELOG.md
+++ b/experimental/CHANGELOG.md
@@ -20,6 +20,7 @@ All notable changes to experimental packages in this project will be documented
* fix(sdk-metrics-base): misbehaving aggregation temporality selector tolerance #2958 @legendecas
* feat(trace-otlp-grpc): configure security with env vars #2827 @svetlanabrennan
* feat(sdk-metrics-base): async instruments callback timeout #2742 @legendecas
+* feat(node-sdk): add serviceName config option #2867 @naseemkullah
### :bug: (Bug Fix)
diff --git a/experimental/packages/opentelemetry-sdk-node/README.md b/experimental/packages/opentelemetry-sdk-node/README.md
index 841bff28247..a21de3c7411 100644
--- a/experimental/packages/opentelemetry-sdk-node/README.md
+++ b/experimental/packages/opentelemetry-sdk-node/README.md
@@ -128,6 +128,10 @@ Configure a trace exporter. If an exporter OR span processor is not configured,
Configure tracing parameters. These are the same trace parameters used to [configure a tracer](../../../packages/opentelemetry-sdk-trace-base/src/types.ts#L71).
+### serviceName
+
+Configure the [service name](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service).
+
## Useful links
- For more information on OpenTelemetry, visit:
diff --git a/experimental/packages/opentelemetry-sdk-node/src/sdk.ts b/experimental/packages/opentelemetry-sdk-node/src/sdk.ts
index aa3df3247c1..cce13f112c0 100644
--- a/experimental/packages/opentelemetry-sdk-node/src/sdk.ts
+++ b/experimental/packages/opentelemetry-sdk-node/src/sdk.ts
@@ -14,15 +14,12 @@
* limitations under the License.
*/
-import { TextMapPropagator } from '@opentelemetry/api';
+import { ContextManager, TextMapPropagator } from '@opentelemetry/api';
import { metrics } from '@opentelemetry/api-metrics';
-import { ContextManager } from '@opentelemetry/api';
-import { MeterProvider, MetricReader } from '@opentelemetry/sdk-metrics-base';
import {
InstrumentationOption,
- registerInstrumentations,
+ registerInstrumentations
} from '@opentelemetry/instrumentation';
-import { NodeTracerConfig, NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { awsEc2Detector } from '@opentelemetry/resource-detector-aws';
import { gcpDetector } from '@opentelemetry/resource-detector-gcp';
import {
@@ -30,9 +27,18 @@ import {
envDetector,
processDetector,
Resource,
- ResourceDetectionConfig,
+ ResourceDetectionConfig
} from '@opentelemetry/resources';
-import { BatchSpanProcessor, SpanProcessor } from '@opentelemetry/sdk-trace-base';
+import { MeterProvider, MetricReader } from '@opentelemetry/sdk-metrics-base';
+import {
+ BatchSpanProcessor,
+ SpanProcessor
+} from '@opentelemetry/sdk-trace-base';
+import {
+ NodeTracerConfig,
+ NodeTracerProvider
+} from '@opentelemetry/sdk-trace-node';
+import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
import { NodeSDKConfiguration } from './types';
/** This class represents everything needed to register a fully configured OpenTelemetry Node.js SDK */
@@ -52,6 +58,7 @@ export class NodeSDK {
private _tracerProvider?: NodeTracerProvider;
private _meterProvider?: MeterProvider;
+ private _serviceName?: string;
/**
* Create a new NodeJS SDK instance
@@ -59,6 +66,9 @@ export class NodeSDK {
public constructor(configuration: Partial = {}) {
this._resource = configuration.resource ?? new Resource({});
+
+ this._serviceName = configuration.serviceName;
+
this._autoDetectResources = configuration.autoDetectResources ?? true;
if (configuration.spanProcessor || configuration.traceExporter) {
@@ -115,7 +125,9 @@ export class NodeSDK {
}
/** Detect resource attributes */
- public async detectResources(config?: ResourceDetectionConfig): Promise {
+ public async detectResources(
+ config?: ResourceDetectionConfig
+ ): Promise {
const internalConfig: ResourceDetectionConfig = {
detectors: [awsEc2Detector, gcpDetector, envDetector, processDetector],
...config,
@@ -137,6 +149,12 @@ export class NodeSDK {
await this.detectResources();
}
+ this._resource = this._serviceName === undefined
+ ? this._resource
+ : this._resource.merge(new Resource(
+ {[SemanticResourceAttributes.SERVICE_NAME]: this._serviceName}
+ ));
+
if (this._tracerProviderConfig) {
const tracerProvider = new NodeTracerProvider({
...this._tracerProviderConfig.tracerConfig,
diff --git a/experimental/packages/opentelemetry-sdk-node/src/types.ts b/experimental/packages/opentelemetry-sdk-node/src/types.ts
index ea93ddae167..bb46bcaffb7 100644
--- a/experimental/packages/opentelemetry-sdk-node/src/types.ts
+++ b/experimental/packages/opentelemetry-sdk-node/src/types.ts
@@ -14,26 +14,27 @@
* limitations under the License.
*/
-import { SpanAttributes, TextMapPropagator, Sampler } from '@opentelemetry/api';
import type { ContextManager } from '@opentelemetry/api';
+import { Attributes, Sampler, TextMapPropagator } from '@opentelemetry/api';
import { InstrumentationOption } from '@opentelemetry/instrumentation';
-import { MetricReader } from '@opentelemetry/sdk-metrics-base';
import { Resource } from '@opentelemetry/resources';
+import { MetricReader } from '@opentelemetry/sdk-metrics-base';
import {
SpanExporter,
- SpanProcessor,
SpanLimits,
+ SpanProcessor
} from '@opentelemetry/sdk-trace-base';
export interface NodeSDKConfiguration {
autoDetectResources: boolean;
contextManager: ContextManager;
- defaultAttributes: SpanAttributes;
+ defaultAttributes: Attributes;
textMapPropagator: TextMapPropagator;
metricReader: MetricReader;
instrumentations: InstrumentationOption[];
resource: Resource;
sampler: Sampler;
+ serviceName?: string;
spanProcessor: SpanProcessor;
traceExporter: SpanExporter;
spanLimits: SpanLimits;
diff --git a/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts b/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
index 2237828534f..d45d4a9812f 100644
--- a/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
+++ b/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
@@ -428,4 +428,76 @@ describe('Node SDK', () => {
});
});
});
+
+ describe('configureServiceName', async () => {
+ it('should configure service name via config', async () => {
+ const sdk = new NodeSDK({
+ serviceName: 'config-set-name',
+ });
+
+ await sdk.start();
+ const resource = sdk['_resource'];
+
+ assertServiceResource(resource, {
+ name: 'config-set-name',
+ });
+ });
+
+ it('should configure service name via OTEL_SERVICE_NAME env var', async () => {
+ process.env.OTEL_SERVICE_NAME='env-set-name';
+ const sdk = new NodeSDK();
+
+ await sdk.start();
+ const resource = sdk['_resource'];
+
+ assertServiceResource(resource, {
+ name: 'env-set-name',
+ });
+ delete process.env.OTEL_SERVICE_NAME;
+ });
+
+ it('should favor config set service name over OTEL_SERVICE_NAME env set service name', async () => {
+ process.env.OTEL_SERVICE_NAME='env-set-name';
+ const sdk = new NodeSDK({
+ serviceName: 'config-set-name',
+ });
+
+ await sdk.start();
+ const resource = sdk['_resource'];
+
+ assertServiceResource(resource, {
+ name: 'config-set-name',
+ });
+ delete process.env.OTEL_SERVICE_NAME;
+ });
+
+
+ it('should configure service name via OTEL_RESOURCE_ATTRIBUTES env var', async () => {
+ process.env.OTEL_RESOURCE_ATTRIBUTES = 'service.name=resource-env-set-name';
+ const sdk = new NodeSDK();
+
+ await sdk.start();
+ const resource = sdk['_resource'];
+
+ assertServiceResource(resource, {
+ name: 'resource-env-set-name',
+ });
+ delete process.env.OTEL_RESOURCE_ATTRIBUTES;
+ });
+
+ 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';
+ const sdk = new NodeSDK({
+ serviceName: 'config-set-name',
+ });
+
+ await sdk.start();
+ const resource = sdk['_resource'];
+
+ assertServiceResource(resource, {
+ name: 'config-set-name',
+ });
+ delete process.env.OTEL_RESOURCE_ATTRIBUTES;
+ });
+ });
});
diff --git a/experimental/packages/opentelemetry-sdk-node/test/util/resource-assertions.ts b/experimental/packages/opentelemetry-sdk-node/test/util/resource-assertions.ts
index 206c9bcf86a..331fed6e8ec 100644
--- a/experimental/packages/opentelemetry-sdk-node/test/util/resource-assertions.ts
+++ b/experimental/packages/opentelemetry-sdk-node/test/util/resource-assertions.ts
@@ -232,7 +232,7 @@ export const assertServiceResource = (
resource: Resource,
validations: {
name: string;
- instanceId: string;
+ instanceId?: string;
namespace?: string;
version?: string;
}