opentelemetry-js/experimental/packages/otlp-transformer/test/trace.test.ts

297 lines
9.7 KiB
TypeScript

/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { SpanKind, SpanStatusCode } from '@opentelemetry/api';
import { TraceState, hexToBase64 } from '@opentelemetry/core';
import { Resource } from '@opentelemetry/resources';
import { ReadableSpan } from '@opentelemetry/sdk-trace-base';
import * as assert from 'assert';
import {
createExportTraceServiceRequest,
ESpanKind,
EStatusCode,
} from '../src';
function createExpectedSpanJson(useHex: boolean) {
const traceId = useHex
? '00000000000000000000000000000001'
: hexToBase64('00000000000000000000000000000001');
const spanId = useHex ? '0000000000000002' : hexToBase64('0000000000000002');
const parentSpanId = useHex
? '0000000000000001'
: hexToBase64('0000000000000001');
const linkSpanId = useHex
? '0000000000000003'
: hexToBase64('0000000000000003');
const linkTraceId = useHex
? '00000000000000000000000000000002'
: hexToBase64('00000000000000000000000000000002');
return {
resourceSpans: [
{
resource: {
attributes: [
{
key: 'resource-attribute',
value: { stringValue: 'resource attribute value' },
},
],
droppedAttributesCount: 0,
},
schemaUrl: undefined,
scopeSpans: [
{
scope: { name: 'myLib', version: '0.1.0' },
spans: [
{
traceId: traceId,
spanId: spanId,
parentSpanId: parentSpanId,
traceState: 'span=bar',
name: 'span-name',
kind: ESpanKind.SPAN_KIND_CLIENT,
links: [
{
droppedAttributesCount: 0,
spanId: linkSpanId,
traceId: linkTraceId,
traceState: 'link=foo',
attributes: [
{
key: 'link-attribute',
value: {
stringValue: 'string value',
},
},
],
},
],
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
startTimeUnixNano: 1640715557342725388,
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
endTimeUnixNano: 1640715558642725388,
events: [
{
droppedAttributesCount: 0,
attributes: [
{
key: 'event-attribute',
value: {
stringValue: 'some string value',
},
},
],
name: 'some event',
timeUnixNano: 1640715558542725400,
},
],
attributes: [
{
key: 'string-attribute',
value: { stringValue: 'some attribute value' },
},
],
droppedAttributesCount: 0,
droppedEventsCount: 0,
droppedLinksCount: 0,
status: {
code: EStatusCode.STATUS_CODE_OK,
message: undefined,
},
},
],
schemaUrl: 'http://url.to.schema',
},
],
},
],
};
}
describe('Trace', () => {
describe('createExportTraceServiceRequest', () => {
let resource: Resource;
let span: ReadableSpan;
beforeEach(() => {
resource = new Resource({
'resource-attribute': 'resource attribute value',
});
span = {
spanContext: () => ({
spanId: '0000000000000002',
traceFlags: 1,
traceId: '00000000000000000000000000000001',
isRemote: false,
traceState: new TraceState('span=bar'),
}),
parentSpanId: '0000000000000001',
attributes: { 'string-attribute': 'some attribute value' },
duration: [1, 300000000],
endTime: [1640715558, 642725388],
ended: true,
events: [
{
name: 'some event',
time: [1640715558, 542725388],
attributes: {
'event-attribute': 'some string value',
},
},
],
instrumentationLibrary: {
name: 'myLib',
version: '0.1.0',
schemaUrl: 'http://url.to.schema',
},
kind: SpanKind.CLIENT,
links: [
{
context: {
spanId: '0000000000000003',
traceId: '00000000000000000000000000000002',
traceFlags: 1,
isRemote: false,
traceState: new TraceState('link=foo'),
},
attributes: {
'link-attribute': 'string value',
},
},
],
name: 'span-name',
resource,
startTime: [1640715557, 342725388],
status: {
code: SpanStatusCode.OK,
},
droppedAttributesCount: 0,
droppedEventsCount: 0,
droppedLinksCount: 0,
};
});
it('returns null on an empty list', () => {
assert.deepStrictEqual(createExportTraceServiceRequest([], true), {
resourceSpans: [],
});
});
it('serializes a span with useHex = true', () => {
const exportRequest = createExportTraceServiceRequest([span], true);
assert.ok(exportRequest);
assert.deepStrictEqual(exportRequest, createExpectedSpanJson(true));
});
it('serializes a span with useHex = false', () => {
const exportRequest = createExportTraceServiceRequest([span], false);
assert.ok(exportRequest);
assert.deepStrictEqual(exportRequest, createExpectedSpanJson(false));
});
it('serializes a span without a parent with useHex = true', () => {
(span as any).parentSpanId = undefined;
const exportRequest = createExportTraceServiceRequest([span], true);
assert.ok(exportRequest);
assert.strictEqual(
exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].parentSpanId,
undefined
);
});
it('serializes a span without a parent with useHex = false', () => {
(span as any).parentSpanId = undefined;
const exportRequest = createExportTraceServiceRequest([span], false);
assert.ok(exportRequest);
assert.strictEqual(
exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].parentSpanId,
undefined
);
});
describe('status code', () => {
it('error', () => {
span.status.code = SpanStatusCode.ERROR;
span.status.message = 'error message';
const exportRequest = createExportTraceServiceRequest([span], true);
assert.ok(exportRequest);
const spanStatus =
exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].status;
assert.strictEqual(spanStatus?.code, EStatusCode.STATUS_CODE_ERROR);
assert.strictEqual(spanStatus?.message, 'error message');
});
it('unset', () => {
span.status.code = SpanStatusCode.UNSET;
const exportRequest = createExportTraceServiceRequest([span], true);
assert.ok(exportRequest);
assert.strictEqual(
exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].status.code,
EStatusCode.STATUS_CODE_UNSET
);
});
});
describe('span kind', () => {
it('consumer', () => {
(span as any).kind = SpanKind.CONSUMER;
const exportRequest = createExportTraceServiceRequest([span], true);
assert.ok(exportRequest);
assert.strictEqual(
exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].kind,
ESpanKind.SPAN_KIND_CONSUMER
);
});
it('internal', () => {
(span as any).kind = SpanKind.INTERNAL;
const exportRequest = createExportTraceServiceRequest([span], true);
assert.ok(exportRequest);
assert.strictEqual(
exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].kind,
ESpanKind.SPAN_KIND_INTERNAL
);
});
it('producer', () => {
(span as any).kind = SpanKind.PRODUCER;
const exportRequest = createExportTraceServiceRequest([span], true);
assert.ok(exportRequest);
assert.strictEqual(
exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].kind,
ESpanKind.SPAN_KIND_PRODUCER
);
});
it('server', () => {
(span as any).kind = SpanKind.SERVER;
const exportRequest = createExportTraceServiceRequest([span], true);
assert.ok(exportRequest);
assert.strictEqual(
exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].kind,
ESpanKind.SPAN_KIND_SERVER
);
});
it('unspecified', () => {
(span as any).kind = undefined;
const exportRequest = createExportTraceServiceRequest([span], true);
assert.ok(exportRequest);
assert.strictEqual(
exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].kind,
ESpanKind.SPAN_KIND_UNSPECIFIED
);
});
});
});
});