Skip to content

Commit

Permalink
Merge branch 'main' into root-span-sampler
Browse files Browse the repository at this point in the history
  • Loading branch information
vmarchaud authored May 13, 2021
2 parents 97cfd51 + 3f82ff4 commit f65c5c8
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 75 deletions.
29 changes: 15 additions & 14 deletions packages/opentelemetry-sdk-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![NPM Published Version][npm-img]][npm-url]
[![dependencies][dependencies-image]][dependencies-url]
[![devDependencies][devDependencies-image]][devDependencies-url]
[![devDependencies][devdependencies-image]][devdependencies-url]
[![Apache License][license-image]][license-image]

This package provides the full OpenTelemetry SDK for Node.js including tracing and metrics.
Expand Down Expand Up @@ -34,13 +34,16 @@ $ npm install @opentelemetry/auto-instrumentations-node

Before any other module in your application is loaded, you must initialize the SDK.
If you fail to initialize the SDK or initialize it too late, no-op implementations will be provided to any library which acquires a tracer or meter from the API.

This example uses Jaeger and Prometheus, but exporters exist for [other tracing backends][other-tracing-backends].

```javascript
const opentelemetry = require("@opentelemetry/sdk-node");
const { JaegerExporter } = require("@opentelemetry/exporter-jaeger");
const { PrometheusExporter } = require("@opentelemetry/exporter-prometheus");
const { getNodeAutoInstrumentations } = require("@opentelemetry/auto-instrumentations-node");
const {
getNodeAutoInstrumentations,
} = require("@opentelemetry/auto-instrumentations-node");

const jaegerExporter = new JaegerExporter({
serviceName: 'my-service',
Expand All @@ -59,22 +62,21 @@ const sdk = new opentelemetry.NodeSDK({

// You can optionally detect resources asynchronously from the environment.
// Detected resources are merged with the resources provided in the SDK configuration.
sdk
.start()
.then(() => {
// Resources have been detected and SDK is started
})
sdk.start().then(() => {
// Resources have been detected and SDK is started
});

// You can also use the shutdown method to gracefully shut down the SDK before process shutdown
// or on some operating system signal.
const process = require("process");
process.on("SIGTERM", () => {
sdk.shutdown()
sdk
.shutdown()
.then(
() => console.log("SDK shut down successfully"),
(err) => console.log("Error shutting down SDK", err),
(err) => console.log("Error shutting down SDK", err)
)
.finally(() => process.exit(0))
.finally(() => process.exit(0));
});
```

Expand Down Expand Up @@ -126,7 +128,7 @@ Configure a custom sampler. By default all traces will be sampled.

Configure a trace exporter. If an exporter OR span processor is not configured, the tracing SDK will not be initialized and registered. If an exporter is configured, it will be used with a [BatchSpanProcessor](../opentelemetry-tracing/src/export/BatchSpanProcessor.ts).

### traceParams
### spanLimits

Configure tracing parameters. These are the same trace parameters used to [configure a tracer](../opentelemetry-tracing/src/types.ts#L71).

Expand All @@ -145,9 +147,8 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-sdk-node
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-sdk-node
[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-sdk-node&type=dev
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-sdk-node&type=dev
[devdependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-sdk-node&type=dev
[devdependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-sdk-node&type=dev
[npm-url]: https://www.npmjs.com/package/@opentelemetry/sdk-node
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fsdk-node.svg

[other-tracing-backends]: https://github.com/open-telemetry/opentelemetry-js#trace-exporters
4 changes: 2 additions & 2 deletions packages/opentelemetry-sdk-node/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ export class NodeSDK {
if (configuration.sampler) {
tracerProviderConfig.sampler = configuration.sampler;
}
if (configuration.traceParams) {
tracerProviderConfig.traceParams = configuration.traceParams;
if (configuration.spanLimits) {
tracerProviderConfig.spanLimits = configuration.spanLimits;
}

const spanProcessor =
Expand Down
4 changes: 2 additions & 2 deletions packages/opentelemetry-sdk-node/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { Resource } from '@opentelemetry/resources';
import {
SpanExporter,
SpanProcessor,
TraceParams,
SpanLimits,
} from '@opentelemetry/tracing';

export interface NodeSDKConfiguration {
Expand All @@ -38,5 +38,5 @@ export interface NodeSDKConfiguration {
sampler: Sampler;
spanProcessor: SpanProcessor;
traceExporter: SpanExporter;
traceParams: TraceParams;
spanLimits: SpanLimits;
}
56 changes: 56 additions & 0 deletions packages/opentelemetry-tracing/src/BasicTracerProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ import { BatchSpanProcessor } from './export/BatchSpanProcessor';
export type PROPAGATOR_FACTORY = () => TextMapPropagator;
export type EXPORTER_FACTORY = () => SpanExporter;

export enum ForceFlushState {
'resolved',
'timeout',
'error',
'unresolved',
}

/**
* This class represents a basic tracer provider which platform libraries can extend
*/
Expand Down Expand Up @@ -140,6 +147,55 @@ export class BasicTracerProvider implements TracerProvider {
}
}

forceFlush(): Promise<void> {
const timeout = this._config.forceFlushTimeoutMillis;
const promises = this._registeredSpanProcessors.map(
(spanProcessor: SpanProcessor) => {
return new Promise(resolve => {
let state: ForceFlushState;
const timeoutInterval = setTimeout(() => {
resolve(
new Error(
`Span processor did not completed within timeout period of ${timeout} ms`
)
);
state = ForceFlushState.timeout;
}, timeout);

spanProcessor
.forceFlush()
.then(() => {
clearTimeout(timeoutInterval);
if (state !== ForceFlushState.timeout) {
state = ForceFlushState.resolved;
resolve(state);
}
})
.catch(error => {
clearTimeout(timeoutInterval);
state = ForceFlushState.error;
resolve(error);
});
});
}
);

return new Promise<void>((resolve, reject) => {
Promise.all(promises)
.then(results => {
const errors = results.filter(
result => result !== ForceFlushState.resolved
);
if (errors.length > 0) {
reject(errors);
} else {
resolve();
}
})
.catch(error => reject([error]));
});
}

shutdown() {
return this.activeSpanProcessor.shutdown();
}
Expand Down
10 changes: 5 additions & 5 deletions packages/opentelemetry-tracing/src/Span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { ReadableSpan } from './export/ReadableSpan';
import { TimedEvent } from './TimedEvent';
import { Tracer } from './Tracer';
import { SpanProcessor } from './SpanProcessor';
import { TraceParams } from './types';
import { SpanLimits } from './types';
import { SpanAttributeValue, Context } from '@opentelemetry/api';
import { ExceptionEventName } from './enums';

Expand All @@ -56,7 +56,7 @@ export class Span implements api.Span, ReadableSpan {
private _ended = false;
private _duration: api.HrTime = [-1, -1];
private readonly _spanProcessor: SpanProcessor;
private readonly _traceParams: TraceParams;
private readonly _spanLimits: SpanLimits;

/** Constructs a new Span instance. */
constructor(
Expand All @@ -77,7 +77,7 @@ export class Span implements api.Span, ReadableSpan {
this.startTime = timeInputToHrTime(startTime);
this.resource = parentTracer.resource;
this.instrumentationLibrary = parentTracer.instrumentationLibrary;
this._traceParams = parentTracer.getActiveTraceParams();
this._spanLimits = parentTracer.getSpanLimits();
this._spanProcessor = parentTracer.getActiveSpanProcessor();
this._spanProcessor.onStart(this, context);
}
Expand All @@ -100,7 +100,7 @@ export class Span implements api.Span, ReadableSpan {

if (
Object.keys(this.attributes).length >=
this._traceParams.numberOfAttributesPerSpan! &&
this._spanLimits.attributeCountLimit! &&
!Object.prototype.hasOwnProperty.call(this.attributes, key)
) {
return this;
Expand Down Expand Up @@ -129,7 +129,7 @@ export class Span implements api.Span, ReadableSpan {
startTime?: api.TimeInput
): this {
if (this._isSpanEnded()) return this;
if (this.events.length >= this._traceParams.numberOfEventsPerSpan!) {
if (this.events.length >= this._spanLimits.eventCountLimit!) {
api.diag.warn('Dropping extra events.');
this.events.shift();
}
Expand Down
12 changes: 6 additions & 6 deletions packages/opentelemetry-tracing/src/Tracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ import {
import { Resource } from '@opentelemetry/resources';
import { BasicTracerProvider } from './BasicTracerProvider';
import { Span } from './Span';
import { TraceParams, TracerConfig } from './types';
import { SpanLimits, TracerConfig } from './types';
import { mergeConfig } from './utility';

/**
* This class represents a basic tracer.
*/
export class Tracer implements api.Tracer {
private readonly _sampler: api.Sampler;
private readonly _traceParams: TraceParams;
private readonly _spanLimits: SpanLimits;
private readonly _idGenerator: IdGenerator;
readonly resource: Resource;
readonly instrumentationLibrary: InstrumentationLibrary;
Expand All @@ -47,7 +47,7 @@ export class Tracer implements api.Tracer {
) {
const localConfig = mergeConfig(config);
this._sampler = localConfig.sampler;
this._traceParams = localConfig.traceParams;
this._spanLimits = localConfig.spanLimits;
this._idGenerator = config.idGenerator || new RandomIdGenerator();
this.resource = _tracerProvider.resource;
this.instrumentationLibrary = instrumentationLibrary;
Expand Down Expand Up @@ -126,9 +126,9 @@ export class Tracer implements api.Tracer {
return span;
}

/** Returns the active {@link TraceParams}. */
getActiveTraceParams(): TraceParams {
return this._traceParams;
/** Returns the active {@link SpanLimits}. */
getSpanLimits(): SpanLimits {
return this._spanLimits;
}

getActiveSpanProcessor() {
Expand Down
11 changes: 6 additions & 5 deletions packages/opentelemetry-tracing/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@ const FALLBACK_OTEL_TRACES_SAMPLER = TracesSamplerValues.AlwaysOn;
/**
* Default configuration. For fields with primitive values, any user-provided
* value will override the corresponding default value. For fields with
* non-primitive values (like `traceParams`), the user-provided value will be
* non-primitive values (like `spanLimits`), the user-provided value will be
* used to extend the default value.
*/
export const DEFAULT_CONFIG = {
sampler: buildSamplerFromEnv(env),
traceParams: {
numberOfAttributesPerSpan: getEnv().OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT,
numberOfLinksPerSpan: getEnv().OTEL_SPAN_LINK_COUNT_LIMIT,
numberOfEventsPerSpan: getEnv().OTEL_SPAN_EVENT_COUNT_LIMIT,
forceFlushTimeoutMillis: 30000,
spanLimits: {
attributeCountLimit: getEnv().OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT,
linkCountLimit: getEnv().OTEL_SPAN_LINK_COUNT_LIMIT,
eventCountLimit: getEnv().OTEL_SPAN_EVENT_COUNT_LIMIT,
},
};

Expand Down
24 changes: 15 additions & 9 deletions packages/opentelemetry-tracing/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export interface TracerConfig {
*/
sampler?: Sampler;

/** Trace Parameters */
traceParams?: TraceParams;
/** Span Limits */
spanLimits?: SpanLimits;

/** Resource associated with trace telemetry */
resource?: Resource;
Expand All @@ -40,6 +40,12 @@ export interface TracerConfig {
* The default idGenerator generates random ids
*/
idGenerator?: IdGenerator;

/**
* How long the forceFlush can run before it is cancelled.
* The default value is 30000ms
*/
forceFlushTimeoutMillis?: number;
}

/**
Expand All @@ -56,13 +62,13 @@ export interface SDKRegistrationConfig {
}

/** Global configuration of trace service */
export interface TraceParams {
/** numberOfAttributesPerSpan is number of attributes per span */
numberOfAttributesPerSpan?: number;
/** numberOfLinksPerSpan is number of links per span */
numberOfLinksPerSpan?: number;
/** numberOfEventsPerSpan is number of message events per span */
numberOfEventsPerSpan?: number;
export interface SpanLimits {
/** attributeCountLimit is number of attributes per span */
attributeCountLimit?: number;
/** linkCountLimit is number of links per span */
linkCountLimit?: number;
/** eventCountLimit is number of message events per span */
eventCountLimit?: number;
}

/** Interface configuration for a buffer. */
Expand Down
6 changes: 3 additions & 3 deletions packages/opentelemetry-tracing/src/utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ export function mergeConfig(userConfig: TracerConfig) {
userConfig
);

target.traceParams = Object.assign(
target.spanLimits = Object.assign(
{},
DEFAULT_CONFIG.traceParams,
userConfig.traceParams || {}
DEFAULT_CONFIG.spanLimits,
userConfig.spanLimits || {}
);

return target;
Expand Down
Loading

0 comments on commit f65c5c8

Please sign in to comment.