forked from newrelic/node-newrelic
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2921ce8
commit 5926ea7
Showing
6 changed files
with
277 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
const { ROOT_CONTEXT } = require('@opentelemetry/api') | ||
|
||
/** | ||
* @see https://open-telemetry.github.io/opentelemetry-js/interfaces/_opentelemetry_api.ContextManager.html | ||
*/ | ||
class ContextManager { | ||
#agent | ||
|
||
#localStorage | ||
|
||
constructor(agent) { | ||
if (!agent) { | ||
agent = require('../../../index').agent | ||
} | ||
|
||
this.#agent = agent | ||
this.#localStorage = agent._contextManager._asyncLocalStorage | ||
} | ||
|
||
active() { | ||
// TODO: get current span(segment?) from agent and prefer it | ||
const storedContext = this.#localStorage.getStore() | ||
return storedContext || ROOT_CONTEXT | ||
} | ||
|
||
bind(context, target) { | ||
return boundContext.bind(this) | ||
|
||
function boundContext(...args) { | ||
return this.with(context, target, this, ...args) | ||
} | ||
} | ||
|
||
/** | ||
* Runs the callback within the provided context, optionally | ||
* bound with a provided `this`. | ||
* | ||
* @param context | ||
* @param callback | ||
* @param thisRef | ||
* @param args | ||
*/ | ||
with(context, callback, thisRef, ...args) { | ||
return this.#agent._contextManager.runInContext(context, callback, thisRef, args) | ||
} | ||
|
||
enable() { | ||
return this | ||
} | ||
disable() { | ||
return this | ||
} | ||
} | ||
|
||
module.exports = ContextManager |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
/** | ||
* @see https://open-telemetry.github.io/opentelemetry-js/interfaces/_opentelemetry_sdk_trace_base.SpanProcessor.html | ||
*/ | ||
class NoopSpanProcessor { | ||
async forceFlush() {} | ||
onStart() {} | ||
onEnd() {} | ||
async shutdown() {} | ||
} | ||
|
||
class MultiSpanProcessor { | ||
#processors = [] | ||
|
||
constructor(processors) { | ||
for (const p of processors) { | ||
this.#processors.push(p) | ||
} | ||
} | ||
|
||
forceFlush() { | ||
return Promise.all(this.#processors.map((p) => p.forceFlush())) | ||
} | ||
|
||
onStart(span, context) { | ||
for (const p of this.#processors) { | ||
p.onStart(span, context) | ||
} | ||
} | ||
|
||
onEnd(span) { | ||
for (const p of this.#processors) { | ||
p.onEnd(span) | ||
} | ||
} | ||
|
||
shutdown() { | ||
return Promise.all(this.#processors.map((p) => p.shutdown())) | ||
} | ||
} | ||
|
||
module.exports = { NoopSpanProcessor, MultiSpanProcessor } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
const { | ||
context: otelContextApi, | ||
propagation: otelPropagatorApi, | ||
trace: otelTraceApi | ||
} = require('@opentelemetry/api') | ||
const { W3CTraceContextPropagator } = require('@opentelemetry/core') | ||
|
||
const ContextManager = require('./context-manager') | ||
const Tracer = require('./tracer') | ||
const { NoopSpanProcessor, MultiSpanProcessor } = require('./span-processors') | ||
|
||
/** | ||
* @see https://opentelemetry.io/docs/specs/otel/trace/api/#tracerprovider | ||
* @see https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_sdk_trace_node.NodeTracerProvider.html | ||
*/ | ||
class NRTracerProvider { | ||
#config | ||
#resource | ||
|
||
#tracers | ||
#contextManager | ||
#processors = [] | ||
#activeProcessor | ||
|
||
/** | ||
* | ||
* @param {object} config https://open-telemetry.github.io/opentelemetry-js/interfaces/_opentelemetry_sdk_trace_base.TracerConfig.html | ||
*/ | ||
constructor(config = {}) { | ||
this.#config = config | ||
this.#resource = config.resource | ||
this.#tracers = new Map() | ||
this.#contextManager = new ContextManager() | ||
this.addSpanProcessor(new NoopSpanProcessor()) | ||
} | ||
|
||
/** | ||
* @param processor | ||
* | ||
* @see https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_sdk_trace_base.BasicTracerProvider.html#addSpanProcessor | ||
*/ | ||
addSpanProcessor(processor) { | ||
this.#processors.push(processor) | ||
this.#activeProcessor = new MultiSpanProcessor(this.#processors) | ||
} | ||
|
||
/** | ||
* @see https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_sdk_trace_base.BasicTracerProvider.html#getActiveSpanProcessor | ||
*/ | ||
getActiveSpanProcessor() { | ||
return this.#activeProcessor | ||
} | ||
|
||
/** | ||
* Retrieve a tracer, or return a new one if none found. | ||
* | ||
* @param {string} name Tracer scope name. | ||
* @param {string} [version] A semver style version string representing the | ||
* version of the scoped entity being traced. | ||
* @param {object} [options] Additional options. | ||
* @param {string} [options.schemaUrl] Schema URL to be emitted in telemetry. | ||
* | ||
* @returns {Tracer} The found, or created, tracer. | ||
* | ||
* @see https://opentelemetry.io/docs/specs/otel/trace/api/#get-a-tracer | ||
* @see https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_sdk_trace_base.BasicTracerProvider.html#getTracer | ||
*/ | ||
getTracer(name, version = '0.0.0', options = {}) { | ||
const { schemaUrl } = options | ||
// Key as constructed upstream: https://github.com/open-telemetry/opentelemetry-js/blob/2a4919c1cf99d3403d387d7589836fd9e3018896/packages/opentelemetry-sdk-trace-base/src/BasicTracerProvider.ts#L102 | ||
const key = `${name}@${version}:${schemaUrl || ''}` | ||
if (this.#tracers.has(key) === false) { | ||
// The spec says we _must_ return a fallback tracer rather than | ||
// returning `null` or throwing an error when the provided name is empty. | ||
const tracer = new Tracer({ name, version, schemaUrl }, this.#config, this) | ||
this.#tracers.set(key, tracer) | ||
return tracer | ||
} | ||
return this.#tracers.get(key) | ||
} | ||
|
||
/** | ||
* The constructor sets up some basic class fields. This, as highlighted in | ||
* the documenation, is meant to be invoked subsequent to class instantiation | ||
* as a means to establish more specific configuration. | ||
* | ||
* @param {object} [config] | ||
* | ||
* @see https://github.com/open-telemetry/opentelemetry-js/blob/9de31518e76a38050f1a5676124fffd259085263/packages/opentelemetry-sdk-trace-node/README.md | ||
*/ | ||
register(config = {}) { | ||
otelContextApi.setGlobalContextManager(this.#contextManager) | ||
if (otelTraceApi.setGlobalTracerProvider(this) === false) { | ||
// https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_api.TraceAPI.html#setGlobalTracerProvider | ||
// The default tracer provider defined by the API is a | ||
// `ProxyTracerProvider` instance. That class provides a unique method, | ||
// `setDelegate`, that we can use instead. | ||
otelTraceApi.getTracerProvider().setDelegate(this) | ||
} | ||
|
||
if (config.propagator) { | ||
otelPropagatorApi.setGlobalPropagator(config.propagator) | ||
} else { | ||
otelPropagatorApi.setGlobalPropagator(new W3CTraceContextPropagator()) | ||
} | ||
} | ||
|
||
forceFlush() { | ||
// TODO: invoke the agent's flush | ||
return this.#activeProcessor.forceFlush() | ||
} | ||
|
||
shutdown() { | ||
return this.#activeProcessor.shutdown() | ||
} | ||
} | ||
|
||
module.exports = NRTracerProvider |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
/** | ||
* @see https://opentelemetry.io/docs/specs/otel/trace/api/#tracer | ||
* @see https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_sdk_trace_base.Tracer.html | ||
*/ | ||
class Tracer { | ||
#config | ||
#instrumentationLibrary | ||
#tracerProvider | ||
|
||
constructor(instrumentationLibrary, config, tracerProvider) { | ||
this.#config = config | ||
this.#instrumentationLibrary = instrumentationLibrary | ||
this.#tracerProvider = tracerProvider | ||
} | ||
|
||
get instrumentationLibrary() { | ||
return this.#instrumentationLibrary | ||
} | ||
} | ||
|
||
module.exports = Tracer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters