Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2

### :bug: Bug Fixes

* fix(opentelemetry-resources): the custom value from env variable for service.instance.id should take priority over random uuid as backup [#6345](https://github.com/open-telemetry/opentelemetry-js/pull/6345) @maryliag

### :books: Documentation

### :house: Internal
Expand Down
24 changes: 24 additions & 0 deletions experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,30 @@ describe('Node SDK', () => {
assertServiceInstanceIdIsUUID(resource);
await sdk.shutdown();
});

it('should configure service instance id with service instance id from env variable taking priority over random UUID', async () => {
process.env.OTEL_RESOURCE_ATTRIBUTES =
'service.instance.id=custom-service,service.name=my-service';
const sdk = new NodeSDK({
autoDetectResources: true,
resourceDetectors: [
processDetector,
envDetector,
hostDetector,
serviceInstanceIdDetector,
],
});

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

assertServiceResource(resource, {
name: 'my-service',
instanceId: 'custom-service',
});
await sdk.shutdown();
});
});

describe('A disabled SDK should be no-op', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,32 @@ import { ATTR_SERVICE_INSTANCE_ID } from '../../../semconv';
import { randomUUID } from 'crypto';
import { ResourceDetectionConfig } from '../../../config';
import { DetectedResource, ResourceDetector } from '../../../types';
import { getStringFromEnv, getStringListFromEnv } from '@opentelemetry/core';

/**
* ServiceInstanceIdDetector detects the resources related to the service instance ID.
*/
class ServiceInstanceIdDetector implements ResourceDetector {
detect(_config?: ResourceDetectionConfig): DetectedResource {
let serviceInstanceID;
if (
getStringFromEnv('OTEL_RESOURCE_ATTRIBUTES')?.includes(
'service.instance.id'
)
) {
const resources = getStringListFromEnv('OTEL_RESOURCE_ATTRIBUTES') || [];
for (const resource of resources) {
const [key, value] = resource.split('=');
if (key === 'service.instance.id') {
serviceInstanceID = value;
break;
}
}
}

return {
attributes: {
[ATTR_SERVICE_INSTANCE_ID]: randomUUID(),
[ATTR_SERVICE_INSTANCE_ID]: serviceInstanceID ?? randomUUID(),
},
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { serviceInstanceIdDetector } from '../../../src';
import { resourceFromDetectedResource } from '../../../src/ResourceImpl';
import { ATTR_SERVICE_INSTANCE_ID } from '../../../src/semconv';
import { describeNode } from '../../util';
import * as assert from 'assert';

describeNode('serviceInstanceIdDetector on Node.js', () => {
afterEach(() => {
delete process.env.OTEL_RESOURCE_ATTRIBUTES;
delete process.env.OTEL_NODE_RESOURCE_DETECTORS;
});

it('should return custom value from env', async () => {
process.env.OTEL_RESOURCE_ATTRIBUTES = 'service.instance.id=custom-service';
const resource = resourceFromDetectedResource(
serviceInstanceIdDetector.detect()
);
assert.strictEqual(
resource.attributes[ATTR_SERVICE_INSTANCE_ID],
'custom-service'
);
});

it('should return custom value from env even with resource detector for random', async () => {
process.env.OTEL_RESOURCE_ATTRIBUTES = 'service.instance.id=custom-service';
process.env.OTEL_NODE_RESOURCE_DETECTORS = 'serviceinstance';
const resource = resourceFromDetectedResource(
serviceInstanceIdDetector.detect()
);
assert.strictEqual(
resource.attributes[ATTR_SERVICE_INSTANCE_ID],
'custom-service'
);
});

it('should return random value', async () => {
process.env.OTEL_NODE_RESOURCE_DETECTORS = 'serviceinstance';
const resource = resourceFromDetectedResource(
serviceInstanceIdDetector.detect()
);

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[ATTR_SERVICE_INSTANCE_ID]?.toString() || ''
),
true
);
});
});