Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -18,6 +18,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2

* feat(configuration): bump config schema to v1.1.0; rename `without_scope_info` → `scope_info_enabled` and `without_target_info/development` → `target_info_enabled/development` on the Prometheus pull exporter (semantics inverted), rename `with_resource_constant_labels` → `resource_constant_labels`. Validate `file_format` per the configuration versioning spec: accept any minor version of major `1` (e.g. `1.0`, `1.1`), warn when the minor version is newer than supported, and reject other major versions. [#6781](https://github.com/open-telemetry/opentelemetry-js/pull/6781) @MikeGoldsmith
* feat(sdk-node): wire up `id_generator` from declarative config [#6782](https://github.com/open-telemetry/opentelemetry-js/pull/6782) @MikeGoldsmith
* feat(sdk-node): wire up `tracer_provider.sampler` from declarative config (always_on, always_off, trace_id_ratio_based, parent_based); experimental sampler variants warn and fall back to default [#6506](https://github.com/open-telemetry/opentelemetry-js/issues/6506) @MikeGoldsmith
* feat(propagator-env-carrier): empty name normalization [#6827](https://github.com/open-telemetry/opentelemetry-js/pull/6827) @pellared

### :bug: Bug Fixes
Expand Down
4 changes: 3 additions & 1 deletion experimental/packages/opentelemetry-sdk-node/src/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from '@opentelemetry/api';
import {
getIdGeneratorFromConfiguration,
getSamplerFromConfiguration,
getInstanceID,
createLoggerProviderFromConfig,
getMeterReadersFromConfiguration,
Expand Down Expand Up @@ -168,11 +169,12 @@ function create(
const spanProcessors = getSpanProcessorsFromConfiguration(config);
if (spanProcessors) {
const idGenerator = getIdGeneratorFromConfiguration(config);
// TODO (6506): support sampler configuration from config
const sampler = getSamplerFromConfiguration(config);
const tracerProvider = new TracerProvider({
resource,
spanProcessors,
idGenerator,
sampler,
spanLimits: createSpanLimitsFromConfig(
config.tracer_provider?.limits,
config.attribute_limits
Expand Down
32 changes: 31 additions & 1 deletion experimental/packages/opentelemetry-sdk-node/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,27 @@ export function getInstanceID(config: ConfigurationModel): string | undefined {

const DEFAULT_RATIO = 1;

const EXPERIMENTAL_SAMPLER_KEYS = [
'jaeger_remote/development',
'probability/development',
'composite/development',
];

/**
* Returns the {@link Sampler} configured under `tracer_provider.sampler` in
* the declarative configuration, or `undefined` if none is set (in which case
* the SDK applies its default sampler).
*/
export function getSamplerFromConfiguration(
config: ConfigurationModel
): Sampler | undefined {
const samplerConfig = config.tracer_provider?.sampler;
if (!samplerConfig) {
return undefined;
}
return buildSamplerFromConfig(samplerConfig);
}

/**
* Builds a {@link Sampler} from a {@link SamplerConfigModel} data model.
* This allows sampler construction from declarative configuration.
Expand Down Expand Up @@ -1309,7 +1330,16 @@ export function buildSamplerFromConfig(
: undefined,
});
}
diag.error('Unknown sampler config, defaulting to ParentBased(AlwaysOn).');
const experimentalKeys = EXPERIMENTAL_SAMPLER_KEYS.filter(
k => samplerConfig[k] !== undefined
);
if (experimentalKeys.length > 0) {
diag.warn(
`Experimental sampler type(s) ${experimentalKeys.join(', ')} are not yet supported; defaulting to ParentBased(AlwaysOn).`
);
} else {
diag.error('Unknown sampler config, defaulting to ParentBased(AlwaysOn).');
}
Comment thread
MikeGoldsmith marked this conversation as resolved.
Outdated
return new ParentBasedSampler({ root: new AlwaysOnSampler() });
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@
*/

import * as assert from 'assert';
import * as sinon from 'sinon';
import { diag } from '@opentelemetry/api';
import type { ConfigurationModel } from '@opentelemetry/configuration';
import {
AlwaysOffSampler,
AlwaysOnSampler,
ParentBasedSampler,
TraceIdRatioBasedSampler,
} from '@opentelemetry/sdk-trace';
import { buildSamplerFromConfig } from '../src/utils';
import {
buildSamplerFromConfig,
getSamplerFromConfiguration,
} from '../src/utils';

describe('buildSamplerFromConfig()', () => {
it('should return AlwaysOnSampler for always_on config', () => {
Expand Down Expand Up @@ -106,4 +112,63 @@ describe('buildSamplerFromConfig()', () => {
'ParentBased{root=AlwaysOnSampler, remoteParentSampled=AlwaysOnSampler, remoteParentNotSampled=AlwaysOffSampler, localParentSampled=AlwaysOnSampler, localParentNotSampled=AlwaysOffSampler}'
);
});

it('warns and defaults for experimental sampler variants', () => {
const warnStub = sinon.stub(diag, 'warn');
try {
const sampler = buildSamplerFromConfig({
'probability/development': { ratio: 0.1 },
});
assert.ok(sampler instanceof ParentBasedSampler);
assert.ok(
warnStub.args.some(args =>
String(args[0]).includes(
'Experimental sampler type(s) probability/development'
)
)
);
} finally {
warnStub.restore();
}
});
});

describe('getSamplerFromConfiguration()', () => {
it('returns undefined when tracer_provider.sampler is omitted', () => {
assert.strictEqual(
getSamplerFromConfiguration({} as ConfigurationModel),
undefined
);
assert.strictEqual(
getSamplerFromConfiguration({
tracer_provider: { processors: [] },
} as ConfigurationModel),
undefined
);
});

it('returns the sampler defined under tracer_provider.sampler', () => {
const sampler = getSamplerFromConfiguration({
tracer_provider: {
processors: [],
sampler: { always_off: {} },
},
} as ConfigurationModel);
assert.ok(sampler instanceof AlwaysOffSampler);
});

it('builds a parent_based sampler from configuration', () => {
const sampler = getSamplerFromConfiguration({
tracer_provider: {
processors: [],
sampler: {
parent_based: { root: { trace_id_ratio_based: { ratio: 0.25 } } },
},
},
} as ConfigurationModel);
assert.ok(sampler instanceof ParentBasedSampler);
assert.ok(
sampler.toString().startsWith('ParentBased{root=TraceIdRatioBased{0.25}')
);
});
});