diff --git a/packages/opentelemetry-sdk-trace-base/src/Span.ts b/packages/opentelemetry-sdk-trace-base/src/Span.ts index 39a8b30308..a923c1d565 100644 --- a/packages/opentelemetry-sdk-trace-base/src/Span.ts +++ b/packages/opentelemetry-sdk-trace-base/src/Span.ts @@ -363,12 +363,18 @@ export class Span implements APISpan, ReadableSpan { private _isSpanEnded(): boolean { if (this._ended) { - diag.warn( - `Can not execute the operation on ended Span {traceId: ${this._spanContext.traceId}, spanId: ${this._spanContext.spanId}}` - ); + const error = new Error(`Operation attempted on ended Span {traceId: ${this._spanContext.traceId}, spanId: ${this._spanContext.spanId}}`); + + diag.warn( + `Cannot execute the operation on ended Span {traceId: ${this._spanContext.traceId}, spanId: ${this._spanContext.spanId}}. Change log level to debug for stack trace.`, + error // Pass the error object as the second argument + ); + + // Optionally, you can still log the stack trace for additional context + diag.debug(`Stack trace for ended span operation: ${error.stack}`); } return this._ended; - } +} // Utility function to truncate given value within size // for value type of string, will truncate to given limit diff --git a/packages/opentelemetry-sdk-trace-base/test/common/Span.test.ts b/packages/opentelemetry-sdk-trace-base/test/common/Span.test.ts index ef06a1d884..7a236a65a0 100644 --- a/packages/opentelemetry-sdk-trace-base/test/common/Span.test.ts +++ b/packages/opentelemetry-sdk-trace-base/test/common/Span.test.ts @@ -250,6 +250,32 @@ describe('Span', () => { assert.ok(span.isRecording() === false); }); }); + it('should log a warning and a debug message when span is ended', () => { + const span = new Span( + tracer, + ROOT_CONTEXT, + name, + spanContext, + SpanKind.CLIENT + ); + span.end(); // End the span to set it to ended state + + const warnStub = sinon.spy(diag, 'warn'); + const debugStub = sinon.spy(diag, 'debug'); + + // Call the method that checks if the span is ended + span['_isSpanEnded'](); + + // Assert that the warning log was called with the expected message and an Error object + sinon.assert.calledOnce(warnStub); + sinon.assert.calledWith(warnStub, sinon.match(/Cannot execute the operation on ended Span/), sinon.match.instanceOf(Error)); + + // Assert that the debug log was called and contains a stack trace + sinon.assert.calledOnce(debugStub); + const debugMessage = debugStub.getCall(0).args[0]; + assert.ok(debugMessage.startsWith('Stack trace for ended span operation:')); + }); + }); describe('setAttribute', () => { describe('when default options set', () => {