Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/opentelemetry-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js",
"scripts": {
"test": "nyc ts-mocha -p tsconfig.json test/**/*.test.ts --exclude 'test/platform/browser/**/*.ts'",
"test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/platform/browser/**/*.ts'",
Comment thread
mwear marked this conversation as resolved.
Outdated
"test:browser": "nyc karma start --single-run",
"tdd": "npm run tdd:node",
"tdd:node": "npm run test -- --watch-extensions ts --watch",
Expand Down
10 changes: 10 additions & 0 deletions packages/opentelemetry-core/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,13 @@ export interface ShimWrapped {
__unwrap: Function;
__original: Function;
}

/**
* An instrumentation library consists of the name and version used to
* obtain a tracer or meter from a provider. This metadata is made available
* on ReadableSpan and MetricRecord for use by the export pipeline.
*/
export interface InstrumentationLibrary {
Comment thread
mwear marked this conversation as resolved.
readonly name: string;
readonly version: string;
}
77 changes: 57 additions & 20 deletions packages/opentelemetry-exporter-collector/src/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
} from './CollectorExporterBase';
import { COLLECTOR_SPAN_KIND_MAPPING, opentelemetryProto } from './types';
import ValueType = opentelemetryProto.common.v1.ValueType;
import { InstrumentationLibrary } from '@opentelemetry/core';

/**
* Converts attributes
Expand Down Expand Up @@ -202,11 +203,10 @@ export function toCollectorExportTraceServiceRequest<
collectorExporterBase: CollectorExporterBase<T>,
name = ''
): opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest {
const spansToBeSent: opentelemetryProto.trace.v1.Span[] = spans.map(span =>
toCollectorSpan(span)
);
const resource: Resource =
spans.length > 0 ? spans[0].resource : Resource.empty();
const groupedSpans: Map<
Resource,
Map<core.InstrumentationLibrary, ReadableSpan[]>
> = groupSpans(spans);
Comment thread
mwear marked this conversation as resolved.
Outdated

const additionalAttributes = Object.assign(
{},
Expand All @@ -215,23 +215,60 @@ export function toCollectorExportTraceServiceRequest<
'service.name': collectorExporterBase.serviceName,
}
);
const protoResource: opentelemetryProto.resource.v1.Resource = toCollectorResource(
resource,
additionalAttributes
);
const instrumentationLibrarySpans: opentelemetryProto.trace.v1.InstrumentationLibrarySpans = {
spans: spansToBeSent,
instrumentationLibrary: {
name: name || `${core.SDK_INFO.NAME} - ${core.SDK_INFO.LANGUAGE}`,
version: core.SDK_INFO.VERSION,
},
};
const resourceSpan: opentelemetryProto.trace.v1.ResourceSpans = {
resource: protoResource,
instrumentationLibrarySpans: [instrumentationLibrarySpans],

return {
resourceSpans: toCollectorResourceSpans(groupedSpans, additionalAttributes),
};
}

/**
* Takes an array of spans and groups them by resource and instrumentation
* library
* @param spans spans
*/
export function groupSpans(
spans: ReadableSpan[]
): Map<Resource, Map<core.InstrumentationLibrary, ReadableSpan[]>> {
return spans.reduce((spanMap, span) => {
//group by resource
let resourceSpans = spanMap.get(span.resource);
if (!resourceSpans) {
resourceSpans = new Map<core.InstrumentationLibrary, ReadableSpan[]>();
spanMap.set(span.resource, resourceSpans);
}
//group by instrumentation library
let libSpans = resourceSpans.get(span.instrumentationLibrary);
if (!libSpans) {
libSpans = new Array<ReadableSpan>();
resourceSpans.set(span.instrumentationLibrary, libSpans);
}
libSpans.push(span);
return spanMap;
}, new Map<Resource, Map<core.InstrumentationLibrary, ReadableSpan[]>>());
}

function toCollectorInstrumentationLibrarySpans(
instrumentationLibrary: InstrumentationLibrary,
spans: ReadableSpan[]
): opentelemetryProto.trace.v1.InstrumentationLibrarySpans {
return {
resourceSpans: [resourceSpan],
spans: spans.map(toCollectorSpan),
instrumentationLibrary,
};
}

function toCollectorResourceSpans(
groupedSpans: Map<Resource, Map<core.InstrumentationLibrary, ReadableSpan[]>>,
baseAttributes: Attributes
): opentelemetryProto.trace.v1.ResourceSpans[] {
return Array.from(groupedSpans, ([resource, libSpans]) => {
return {
resource: toCollectorResource(resource, baseAttributes),
instrumentationLibrarySpans: Array.from(
libSpans,
([instrumentationLibrary, spans]) =>
toCollectorInstrumentationLibrarySpans(instrumentationLibrary, spans)
),
};
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@
import { Attributes, TimedEvent } from '@opentelemetry/api';
import * as assert from 'assert';
import * as transform from '../../src/transform';
import { ensureSpanIsCorrect, mockedReadableSpan } from '../helper';
import {
ensureSpanIsCorrect,
mockedReadableSpan,
mockedResources,
mockedInstrumentationLibraries,
multiResourceTrace,
multiInstrumentationLibraryTrace,
} from '../helper';
import { Resource } from '@opentelemetry/resources';

describe('transform', () => {
Expand Down Expand Up @@ -119,4 +126,41 @@ describe('transform', () => {
});
});
});

describe('groupSpans', () => {
it('should group by resource', () => {
const [resource1, resource2] = mockedResources;
const [instrumentationLibrary] = mockedInstrumentationLibraries;
const [span1, span2, span3] = multiResourceTrace;

const expected = new Map([
[resource1, new Map([[instrumentationLibrary, [span1]]])],
[resource2, new Map([[instrumentationLibrary, [span2, span3]]])],
]);

const result = transform.groupSpans(multiResourceTrace);

assert.deepStrictEqual(result, expected);
});

it('should group by instrumentation library', () => {
const [resource] = mockedResources;
const [lib1, lib2] = mockedInstrumentationLibraries;
const [span1, span2, span3] = multiInstrumentationLibraryTrace;

const expected = new Map([
[
resource,
new Map([
[lib1, [span1, span2]],
[lib2, [span3]],
]),
],
]);

const result = transform.groupSpans(multiInstrumentationLibraryTrace);

assert.deepStrictEqual(result, expected);
});
});
});
111 changes: 111 additions & 0 deletions packages/opentelemetry-exporter-collector/test/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Resource } from '@opentelemetry/resources';
import * as assert from 'assert';
import { opentelemetryProto } from '../src/types';
import * as collectorTypes from '../src/types';
import { InstrumentationLibrary } from '@opentelemetry/core';
import * as grpc from 'grpc';

if (typeof Buffer === 'undefined') {
Expand Down Expand Up @@ -106,8 +107,118 @@ export const mockedReadableSpan: ReadableSpan = {
version: 1,
cost: 112.12,
}),
instrumentationLibrary: { name: 'default', version: '0.0.1' },
};

export const mockedResources: Resource[] = [
new Resource({ name: 'resource 1' }),
new Resource({ name: 'resource 2' }),
];

export const mockedInstrumentationLibraries: InstrumentationLibrary[] = [
{
name: 'lib1',
version: '0.0.1',
},
{
name: 'lib2',
version: '0.0.2',
},
];

export const basicTrace: ReadableSpan[] = [
{
name: 'span1',
kind: 0,
spanContext: {
traceId: '1f1008dc8e270e85c40a0d7c3939b278',
spanId: '5e107261f64fa53e',
traceFlags: TraceFlags.SAMPLED,
},
parentSpanId: '78a8915098864388',
startTime: [1574120165, 429803070],
endTime: [1574120165, 438688070],
ended: true,
status: { code: 0 },
attributes: {},
links: [],
events: [],
duration: [0, 8885000],
resource: mockedResources[0],
instrumentationLibrary: mockedInstrumentationLibraries[0],
},
{
name: 'span2',
kind: 0,
spanContext: {
traceId: '1f1008dc8e270e85c40a0d7c3939b278',
spanId: 'f64fa53e5e107261',
traceFlags: TraceFlags.SAMPLED,
},
parentSpanId: '78a8915098864388',
startTime: [1575120165, 439803070],
endTime: [1575120165, 448688070],
ended: true,
status: { code: 0 },
attributes: {},
links: [],
events: [],
duration: [0, 8775000],
resource: mockedResources[0],
instrumentationLibrary: mockedInstrumentationLibraries[0],
},
{
name: 'span3',
kind: 0,
spanContext: {
traceId: '1f1008dc8e270e85c40a0d7c3939b278',
spanId: '07261f64fa53e5e1',
traceFlags: TraceFlags.SAMPLED,
},
parentSpanId: 'a891578098864388',
startTime: [1575120165, 439803070],
endTime: [1575120165, 448688070],
ended: true,
status: { code: 0 },
attributes: {},
links: [],
events: [],
duration: [0, 8775000],
resource: mockedResources[0],
instrumentationLibrary: mockedInstrumentationLibraries[0],
},
];

export const multiResourceTrace: ReadableSpan[] = [
{
...basicTrace[0],
resource: mockedResources[0],
},
{
...basicTrace[1],
resource: mockedResources[1],
},
{
...basicTrace[2],
resource: mockedResources[1],
},
];

export const multiInstrumentationLibraryTrace: ReadableSpan[] = [
{
...basicTrace[0],
instrumentationLibrary: mockedInstrumentationLibraries[0],
},
{
...basicTrace[1],
instrumentationLibrary: mockedInstrumentationLibraries[0],
},
{
...basicTrace[2],
instrumentationLibrary: mockedInstrumentationLibraries[1],
},
];

export function ensureExportedEventsAreCorrect(
events: opentelemetryProto.trace.v1.Span.Event[]
) {
Expand Down
8 changes: 8 additions & 0 deletions packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ describe('JaegerExporter', () => {
events: [],
duration: [32, 800000000],
resource: Resource.empty(),
instrumentationLibrary: {
name: 'default',
version: '0.0.1',
},
};

exporter.export([readableSpan], (result: ExportResult) => {
Expand Down Expand Up @@ -194,6 +198,10 @@ describe('JaegerExporter', () => {
events: [],
duration: [32, 800000000],
resource: Resource.empty(),
instrumentationLibrary: {
name: 'default',
version: '0.0.1',
},
};
exporter.export([readableSpan], () => {});
});
Expand Down
16 changes: 16 additions & 0 deletions packages/opentelemetry-exporter-jaeger/test/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ describe('transform', () => {
version: 1,
cost: 112.12,
}),
instrumentationLibrary: {
name: 'default',
version: '0.0.1',
},
};

const thriftSpan = spanToThrift(readableSpan);
Expand Down Expand Up @@ -169,6 +173,10 @@ describe('transform', () => {
events: [],
duration: [32, 800000000],
resource: Resource.empty(),
instrumentationLibrary: {
name: 'default',
version: '0.0.1',
},
};

const thriftSpan = spanToThrift(readableSpan);
Expand Down Expand Up @@ -234,6 +242,10 @@ describe('transform', () => {
events: [],
duration: [32, 800000000],
resource: Resource.empty(),
instrumentationLibrary: {
name: 'default',
version: '0.0.1',
},
};

const thriftSpan = spanToThrift(readableSpan);
Expand Down Expand Up @@ -273,6 +285,10 @@ describe('transform', () => {
events: [],
duration: [32, 800000000],
resource: Resource.empty(),
instrumentationLibrary: {
name: 'default',
version: '0.0.1',
},
};

const thriftSpan = spanToThrift(readableSpan);
Expand Down
Loading