feat(api): add attributes argument to recordException API (#4071)
Co-authored-by: Marc Pichler <marc.pichler@dynatrace.com>
This commit is contained in:
parent
c84637f264
commit
cd4998a4b5
|
|
@ -11,6 +11,7 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/
|
|||
|
||||
### :rocket: (Enhancement)
|
||||
|
||||
* feat(api): add attributes argument to recordException API [#4071](https://github.com/open-telemetry/opentelemetry-js/pull/4071)
|
||||
* feat(sdk-metrics): implement MetricProducer specification [#4007](https://github.com/open-telemetry/opentelemetry-js/pull/4007)
|
||||
* feat: update PeriodicExportingMetricReader and PrometheusExporter to accept optional metric producers [#4077](https://github.com/open-telemetry/opentelemetry-js/pull/4077) @aabmass
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
## Unreleased
|
||||
|
||||
### :rocket: (Enhancement)
|
||||
|
||||
* feat(api): add attributes argument to recordException API [#4071](https://github.com/open-telemetry/opentelemetry-js/pull/4071)
|
||||
|
||||
## 1.4.1
|
||||
|
||||
### :bug: (Bug Fix)
|
||||
|
|
|
|||
|
|
@ -71,5 +71,9 @@ export class NonRecordingSpan implements Span {
|
|||
}
|
||||
|
||||
// By default does nothing
|
||||
recordException(_exception: Exception, _time?: TimeInput): void {}
|
||||
recordException(
|
||||
_exception: Exception,
|
||||
_attributesOrStartTime?: SpanAttributes | TimeInput,
|
||||
_time?: TimeInput
|
||||
): void {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,4 +126,17 @@ export interface Span {
|
|||
* use the current time.
|
||||
*/
|
||||
recordException(exception: Exception, time?: TimeInput): void;
|
||||
|
||||
/**
|
||||
* Sets exception as a span event
|
||||
* @param exception the exception the only accepted values are string or Error
|
||||
* @param [attributes] the attributes that will be added to the error event.
|
||||
* @param [time] the time to set as Span's event time. If not provided,
|
||||
* use the current time.
|
||||
*/
|
||||
recordException(
|
||||
exception: Exception,
|
||||
attributes?: SpanAttributes,
|
||||
time?: TimeInput
|
||||
): void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -272,7 +272,18 @@ export class Span implements APISpan, ReadableSpan {
|
|||
return this._ended === false;
|
||||
}
|
||||
|
||||
recordException(exception: Exception, time?: TimeInput): void {
|
||||
recordException(
|
||||
exception: Exception,
|
||||
attributesOrStartTime?: SpanAttributes | TimeInput,
|
||||
timeStamp?: TimeInput
|
||||
): void {
|
||||
if (isTimeInput(attributesOrStartTime)) {
|
||||
if (!isTimeInput(timeStamp)) {
|
||||
timeStamp = attributesOrStartTime;
|
||||
}
|
||||
attributesOrStartTime = undefined;
|
||||
}
|
||||
|
||||
const attributes: SpanAttributes = {};
|
||||
if (typeof exception === 'string') {
|
||||
attributes[SemanticAttributes.EXCEPTION_MESSAGE] = exception;
|
||||
|
|
@ -290,13 +301,16 @@ export class Span implements APISpan, ReadableSpan {
|
|||
attributes[SemanticAttributes.EXCEPTION_STACKTRACE] = exception.stack;
|
||||
}
|
||||
}
|
||||
if (attributesOrStartTime) {
|
||||
Object.assign(attributes, sanitizeAttributes(attributesOrStartTime));
|
||||
}
|
||||
|
||||
// these are minimum requirements from spec
|
||||
if (
|
||||
attributes[SemanticAttributes.EXCEPTION_TYPE] ||
|
||||
attributes[SemanticAttributes.EXCEPTION_MESSAGE]
|
||||
) {
|
||||
this.addEvent(ExceptionEventName, attributes, time);
|
||||
this.addEvent(ExceptionEventName, attributes, timeStamp);
|
||||
} else {
|
||||
diag.warn(`Failed to record an exception ${exception}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1203,6 +1203,77 @@ describe('Span', () => {
|
|||
const event = span.events[0];
|
||||
assert.deepStrictEqual(event.time, [0, 123]);
|
||||
});
|
||||
|
||||
it('should record an exception with provided time as a 3rd arg', () => {
|
||||
const span = new Span(
|
||||
tracer,
|
||||
ROOT_CONTEXT,
|
||||
name,
|
||||
spanContext,
|
||||
SpanKind.CLIENT
|
||||
);
|
||||
// @ts-expect-error writing readonly property. performance time origin is mocked to return ms value of [1,1]
|
||||
span['_performanceOffset'] = 0;
|
||||
assert.strictEqual(span.events.length, 0);
|
||||
span.recordException('boom', undefined, [0, 123]);
|
||||
const event = span.events[0];
|
||||
assert.deepStrictEqual(event.time, [0, 123]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when attributes are provided', () => {
|
||||
it('should sanitized and merge attributes when provided', () => {
|
||||
const span = new Span(
|
||||
tracer,
|
||||
ROOT_CONTEXT,
|
||||
name,
|
||||
spanContext,
|
||||
SpanKind.CLIENT
|
||||
);
|
||||
// @ts-expect-error writing readonly property. performance time origin is mocked to return ms value of [1,1]
|
||||
span['_performanceOffset'] = 0;
|
||||
assert.strictEqual(span.events.length, 0);
|
||||
const exception = { code: 'Error', message: 'boom', stack: 'bar' };
|
||||
span.recordException(exception, {
|
||||
...validAttributes,
|
||||
...invalidAttributes,
|
||||
} as unknown as SpanAttributes);
|
||||
const event = span.events[0];
|
||||
assert.deepStrictEqual(event.attributes, {
|
||||
[SemanticAttributes.EXCEPTION_TYPE]: 'Error',
|
||||
[SemanticAttributes.EXCEPTION_MESSAGE]: 'boom',
|
||||
[SemanticAttributes.EXCEPTION_STACKTRACE]: 'bar',
|
||||
...validAttributes,
|
||||
});
|
||||
});
|
||||
|
||||
it('should prioritize the provided attributes over generated', () => {
|
||||
const span = new Span(
|
||||
tracer,
|
||||
ROOT_CONTEXT,
|
||||
name,
|
||||
spanContext,
|
||||
SpanKind.CLIENT
|
||||
);
|
||||
// @ts-expect-error writing readonly property. performance time origin is mocked to return ms value of [1,1]
|
||||
span['_performanceOffset'] = 0;
|
||||
assert.strictEqual(span.events.length, 0);
|
||||
const exception = { code: 'Error', message: 'boom', stack: 'bar' };
|
||||
span.recordException(exception, {
|
||||
[SemanticAttributes.EXCEPTION_TYPE]: 'OverrideError',
|
||||
[SemanticAttributes.EXCEPTION_MESSAGE]: 'override-boom',
|
||||
[SemanticAttributes.EXCEPTION_STACKTRACE]: 'override-bar',
|
||||
...validAttributes,
|
||||
...invalidAttributes,
|
||||
} as unknown as SpanAttributes);
|
||||
const event = span.events[0];
|
||||
assert.deepStrictEqual(event.attributes, {
|
||||
...validAttributes,
|
||||
[SemanticAttributes.EXCEPTION_TYPE]: 'OverrideError',
|
||||
[SemanticAttributes.EXCEPTION_MESSAGE]: 'override-boom',
|
||||
[SemanticAttributes.EXCEPTION_STACKTRACE]: 'override-bar',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when exception code is numeric', () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue