feat(sdk-trace-base): add tracerFactory option to TracerConfig #5853
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Which problem is this PR solving?
Allows a different Tracer/Span implementation to be used by the TracerProvider and the SDKs in cases where behavior needs to be customized by passing a
tracerFactory
option toNodeSDK
andBasicTracerProvider
. This allows customizing this one component of otel without having to write my own SDK and BasicTracerProvider and support code.I observed significant increases in CPU usage from garbage collection/memory pressure in an application when increasing the percentage of traces that were recorded (even if not sampled). Doing some memory benchmarking/profiling, it turns out that creating a single 20 attribute span (200B data) allocates 4.8KiB across 111 objects while a NonRecordingSpan takes 1.4 KiB across 40 objects. With optimization, I was able to reduce this to 650B across 18 objects per Span. Unfortunately, these optimizations are unlikely to be broadly applicable or acceptable to this project as the bulk of the improvement came from removing attribute sanitization (previously identified in #4558), runtime type checking of attributes, and the enforcement of limits on attribute count or size (and the other optimizations are objectively quite ugly). These will have to stay as custom implementations of Tracer/Span.
There was no way for me to inject a custom Tracer implementation without fully reimplementing NodeSDK, so this adds an optional way to pass a tracerFactory through the sdk and the tracer provider like:
You can see the intended usage (and full benchmarks/code) in https://github.com/schleyfox/otel-js-lightweight-tracer
Short description of the changes
Adds an optional
tracerFactory
function toTracerConfig
that is used byBasicTracerProvider
to construct aTracer
.Notes
From a naming perspective, it seems silly to have a tracerFactory that gets passed to a tracerProvider, ideally, you'd just inject a custom
tracerProvider
like you would asampler
ortraceExporter
, but that's awkward because constructing the tracerProvider depends on theresource
andspanProcessors
that are created when the sdk is started.Code ref
The TracerProvider also handles not just the creation of Tracers, but also their caching/management. Logic that I had no desire to reimplement (subclassing BasicTracingProvider would work, but also seems misaligned with the direction in #5283)
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Checklist: