Skip to content
Draft
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
1 change: 1 addition & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2
* feat(opentelemetry-sdk-node): set instrumentation and propagators for experimental start [#6148](https://github.com/open-telemetry/opentelemetry-js/pull/6148) @maryliag
* refactor(configuration): set console exporter as empty object [#6164](https://github.com/open-telemetry/opentelemetry-js/pull/6164) @maryliag
* feat(instrumentation-http, instrumentation-fetch, instrumentation-xml-http-request): support "QUERY" as a known HTTP method
* feat(instrumentation): add support for "_latest_experimental" semantic conventions opt-in value [6224](https://github.com/open-telemetry/opentelemetry-js/pull/6224) @pichlermarc

### :bug: Bug Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ export enum SemconvStability {
OLD = 0x2,
/** Emit both stable and old semantic conventions. */
DUPLICATE = 0x1 | 0x2,
/**
* Emit both stable and latest in-development semantic conventions.
* @experimental this flag is not yet supported by any semconv specification, and thus may change or be removed in the future.
*/
LATEST_EXPERIMENTAL = 0x4 | 0x1,
}

// Common namespaces mentioned in semantic-conventions docs, but allow
Expand Down Expand Up @@ -90,12 +95,21 @@ export function semconvStabilityFromStr(
.map(v => v.trim())
.filter(s => s !== '');
for (const entry of entries ?? []) {
if (entry.toLowerCase() === namespace + '/dup') {
// DUPLICATE takes highest precedence.
semconvStability = SemconvStability.DUPLICATE;
const normalizedEntry = entry.toLowerCase();
if (normalizedEntry === namespace + '_latest_exerimental') {
// LATEST_EXPERIMENTAL takes highest precedence, always set it.
semconvStability = SemconvStability.LATEST_EXPERIMENTAL;
// Highest precedence, no need to read the others.
break;
} else if (entry.toLowerCase() === namespace) {
semconvStability = SemconvStability.STABLE;
} else if (normalizedEntry === namespace + '/dup') {
// DUPLICATE takes precedence over STABLE and OLD.
// Don't break here in case LATEST_EXPERIMENTAL appears later.
semconvStability = SemconvStability.DUPLICATE;
} else if (normalizedEntry === namespace) {
// Only set STABLE if we haven't already found DUPLICATE.
if (semconvStability === SemconvStability.OLD) {
semconvStability = SemconvStability.STABLE;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,38 @@ import { inspect } from 'util';
import * as assert from 'assert';
import { SemconvStability, semconvStabilityFromStr } from '../../src';

describe('SemconvStability', function () {
it('should have correct bitwise flag values', function () {
// STABLE is 0x1
assert.strictEqual(SemconvStability.STABLE, 0x1);

// OLD is 0x2
assert.strictEqual(SemconvStability.OLD, 0x2);

// DUPLICATE is 0x3 (STABLE | OLD)
assert.strictEqual(SemconvStability.DUPLICATE, 0x3);
assert.strictEqual(
SemconvStability.DUPLICATE & SemconvStability.STABLE,
SemconvStability.STABLE
);
assert.strictEqual(
SemconvStability.DUPLICATE & SemconvStability.OLD,
SemconvStability.OLD
);

// LATEST_EXPERIMENTAL is 0x5 (0x4 | STABLE)
assert.strictEqual(SemconvStability.LATEST_EXPERIMENTAL, 0x5);
assert.strictEqual(
SemconvStability.LATEST_EXPERIMENTAL & SemconvStability.STABLE,
SemconvStability.STABLE
);
assert.strictEqual(
SemconvStability.LATEST_EXPERIMENTAL & SemconvStability.OLD,
0
);
});
});

describe('semconvStabilityFromStr', function () {
const table = [
{ namespace: 'http', str: undefined, expected: SemconvStability.OLD },
Expand Down Expand Up @@ -73,6 +105,117 @@ describe('semconvStabilityFromStr', function () {
str: 'just,bogus,values',
expected: SemconvStability.OLD,
},

// LATEST_EXPERIMENTAL tests for http namespace
{
namespace: 'http',
str: 'http_latest_exerimental',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
{
namespace: 'http',
str: 'HTTP_latest_exerimental',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
{
namespace: 'http',
str: ', http_latest_exerimental,bar',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
{
namespace: 'http',
str: ', http_latest_exerimental\t ,blah',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
// LATEST_EXPERIMENTAL takes precedence over DUPLICATE
{
namespace: 'http',
str: 'http/dup,http_latest_exerimental',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
{
namespace: 'http',
str: 'http_latest_exerimental,http/dup',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
// LATEST_EXPERIMENTAL takes precedence over STABLE
{
namespace: 'http',
str: 'http,http_latest_exerimental',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
{
namespace: 'http',
str: 'http_latest_exerimental,http',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},

// LATEST_EXPERIMENTAL tests for database namespace
{
namespace: 'database',
str: 'database_latest_exerimental',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
{
namespace: 'database',
str: 'DATABASE_latest_exerimental',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
{
namespace: 'database',
str: ', database_latest_exerimental,bar',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
{
namespace: 'database',
str: ', database_latest_exerimental\t ,blah',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
// LATEST_EXPERIMENTAL takes precedence over DUPLICATE
{
namespace: 'database',
str: 'database/dup,database_latest_exerimental',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
{
namespace: 'database',
str: 'database_latest_exerimental,database/dup',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
// LATEST_EXPERIMENTAL takes precedence over STABLE
{
namespace: 'database',
str: 'database,database_latest_exerimental',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
{
namespace: 'database',
str: 'database_latest_exerimental,database',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},

// Namespace isolation: http_latest_exerimental doesn't affect database namespace
{
namespace: 'database',
str: 'http_latest_exerimental',
expected: SemconvStability.OLD,
},
{
namespace: 'http',
str: 'database_latest_exerimental',
expected: SemconvStability.OLD,
},
// Mixed namespaces: only the matching namespace applies
{
namespace: 'http',
str: 'database,http_latest_exerimental',
expected: SemconvStability.LATEST_EXPERIMENTAL,
},
{
namespace: 'database',
str: 'http_latest_exerimental,database/dup',
expected: SemconvStability.DUPLICATE,
},
];
for (const { namespace, str, expected } of table) {
it(`str: ${inspect(str)}`, function () {
Expand Down