Skip to content

Commit

Permalink
Incorporated mwear's changes
Browse files Browse the repository at this point in the history
  • Loading branch information
davidwitten committed Jun 25, 2020
1 parent 4fdce55 commit b232bba
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 63 deletions.
125 changes: 95 additions & 30 deletions packages/opentelemetry-exporter-collector/src/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,14 +214,12 @@ export function toCollectorTraceState(
* Prepares trace service request to be sent to collector
* @param spans spans
* @param collectorTraceExporterBase
* @param [name] Instrumentation Library Name
*/
export function toCollectorExportTraceServiceRequest<
T extends CollectorExporterConfigBase
>(
spans: ReadableSpan[],
collectorTraceExporterBase: CollectorTraceExporterBase<T>,
name = ''
collectorTraceExporterBase: CollectorTraceExporterBase<T>
): opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest {
const groupedSpans: Map<
Resource,
Expand Down Expand Up @@ -267,6 +265,56 @@ export function groupSpansByResourceAndLibrary(
}, new Map<Resource, Map<core.InstrumentationLibrary, ReadableSpan[]>>());
}

/**
* Takes an array of metrics and groups them by resource and instrumentation
* library
* @param metrics metrics
*/
export function groupMetricsByResourceAndLibrary(
metrics: MetricRecord[]
): Map<Resource, Map<core.InstrumentationLibrary, MetricRecord[]>> {
return metrics.reduce((metricMap, metric) => {
//group by resource
let resourceMetrics = metricMap.get(metric.resource);
if (!resourceMetrics) {
resourceMetrics = new Map<core.InstrumentationLibrary, MetricRecord[]>();
metricMap.set(metric.resource, resourceMetrics);
}
//group by instrumentation library
let libMetrics = resourceMetrics.get(metric.instrumentationLibrary);
if (!libMetrics) {
libMetrics = new Array<MetricRecord>();
resourceMetrics.set(metric.instrumentationLibrary, libMetrics);
}
libMetrics.push(metric);
return metricMap;
}, new Map<Resource, Map<core.InstrumentationLibrary, MetricRecord[]>>());
}

/**
* Convert to InstrumentationLibraryMetrics
* @param instrumentationLibrary
* @param metrics
* @param startTime
*/
function toCollectorInstrumentationLibraryMetrics(
instrumentationLibrary: core.InstrumentationLibrary,
metrics: MetricRecord[],
startTime: number
): opentelemetryProto.metrics.v1.InstrumentationLibraryMetrics {
return {
metrics: metrics.map(metric => {
return toCollectorMetric(metric, startTime);
}),
instrumentationLibrary,
};
}

/**
* Convert to InstrumentationLibrarySpans
* @param instrumentationLibrary
* @param spans
*/
function toCollectorInstrumentationLibrarySpans(
instrumentationLibrary: core.InstrumentationLibrary,
spans: ReadableSpan[]
Expand Down Expand Up @@ -382,51 +430,39 @@ export function toCollectorMetric(
* @param metrics metrics
* @param startTime start time of the metric in nanoseconds
* @param collectorMetricExporterBase
* @param [name] Instrumentation Library Name
*/
export function toCollectorExportMetricServiceRequest<
T extends CollectorExporterConfigBase
>(
metrics: MetricRecord[],
startTime: number,
collectorMetricExporterBase: CollectorMetricExporterBase<T>,
name = ''
collectorMetricExporterBase: CollectorMetricExporterBase<T>
): opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest {
const metricsToBeSent: opentelemetryProto.metrics.v1.Metric[] = metrics.map(
metric => toCollectorMetric(metric, startTime)
);

const resource: Resource =
metrics.length > 0 ? metrics[0].resource : Resource.empty();
const groupedMetrics: Map<
Resource,
Map<core.InstrumentationLibrary, MetricRecord[]>
> = groupMetricsByResourceAndLibrary(metrics);
const additionalAttributes = Object.assign(
{},
collectorMetricExporterBase.attributes || {},
{
'service.name': collectorMetricExporterBase.serviceName,
}
);
const protoResource: opentelemetryProto.resource.v1.Resource = toCollectorResource(
resource,
additionalAttributes
);

const instrumentationLibraryMetrics: opentelemetryProto.metrics.v1.InstrumentationLibraryMetrics = {
metrics: metricsToBeSent,
instrumentationLibrary: {
name: name || `${core.SDK_INFO.NAME} - ${core.SDK_INFO.LANGUAGE}`,
version: core.SDK_INFO.VERSION,
},
};

const resourceMetric: opentelemetryProto.metrics.v1.ResourceMetrics = {
resource: protoResource,
instrumentationLibraryMetrics: [instrumentationLibraryMetrics],
};
return {
resourceMetrics: [resourceMetric],
resourceMetrics: toCollectorResourceMetrics(
groupedMetrics,
additionalAttributes,
startTime
),
};
}

/**
* Returns a list of resource spans which will be exported to the collector
* @param groupedSpans
* @param baseAttributes
*/
function toCollectorResourceSpans(
groupedSpans: Map<Resource, Map<core.InstrumentationLibrary, ReadableSpan[]>>,
baseAttributes: Attributes
Expand All @@ -442,3 +478,32 @@ function toCollectorResourceSpans(
};
});
}

/**
* Returns a list of resource metrics which will be exported to the collector
* @param groupedSpans
* @param baseAttributes
*/
function toCollectorResourceMetrics(
groupedMetrics: Map<
Resource,
Map<core.InstrumentationLibrary, MetricRecord[]>
>,
baseAttributes: Attributes,
startTime: number
): opentelemetryProto.metrics.v1.ResourceMetrics[] {
return Array.from(groupedMetrics, ([resource, libMetrics]) => {
return {
resource: toCollectorResource(resource, baseAttributes),
instrumentationLibraryMetrics: Array.from(
libMetrics,
([instrumentationLibrary, metrics]) =>
toCollectorInstrumentationLibraryMetrics(
instrumentationLibrary,
metrics,
startTime
)
),
};
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('CollectorMetricExporter - web', () => {
const metric1 =
json.resourceMetrics[0].instrumentationLibraryMetrics[0].metrics[0];
const metric2 =
json.resourceMetrics[0].instrumentationLibraryMetrics[0].metrics[1];
json.resourceMetrics[1].instrumentationLibraryMetrics[0].metrics[0];

assert.ok(typeof metric1 !== 'undefined', "metric doesn't exist");
if (metric1) {
Expand Down Expand Up @@ -180,7 +180,7 @@ describe('CollectorMetricExporter - web', () => {
const metric1 =
json.resourceMetrics[0].instrumentationLibraryMetrics[0].metrics[0];
const metric2 =
json.resourceMetrics[0].instrumentationLibraryMetrics[0].metrics[1];
json.resourceMetrics[1].instrumentationLibraryMetrics[0].metrics[0];

assert.ok(typeof metric1 !== 'undefined', "metric doesn't exist");
if (metric1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import {
mockedInstrumentationLibraries,
multiResourceTrace,
multiInstrumentationLibraryTrace,
multiResourceMetrics,
multiInstrumentationLibraryMetrics,
} from '../helper';
import { Resource } from '@opentelemetry/resources';
import { opentelemetryProto } from '../../src/types';
Expand Down Expand Up @@ -193,6 +195,45 @@ describe('transform', () => {
multiInstrumentationLibraryTrace
);

assert.deepStrictEqual(result, expected);
});
});
describe('groupMetricsByResourceAndLibrary', () => {
it('should group by resource', () => {
const [resource1, resource2] = mockedResources;
const [library] = mockedInstrumentationLibraries;
const [metric1, metric2, metric3] = multiResourceMetrics;

const expected = new Map([
[resource1, new Map([[library, [metric1, metric3]]])],
[resource2, new Map([[library, [metric2]]])],
]);

const result = transform.groupMetricsByResourceAndLibrary(
multiResourceMetrics
);

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

it('should group by instrumentation library', () => {
const [resource] = mockedResources;
const [lib1, lib2] = mockedInstrumentationLibraries;
const [metric1, metric2, metric3] = multiInstrumentationLibraryMetrics;
const expected = new Map([
[
resource,
new Map([
[lib1, [metric1, metric3]],
[lib2, [metric2]],
]),
],
]);

const result = transform.groupMetricsByResourceAndLibrary(
multiInstrumentationLibraryMetrics
);

assert.deepStrictEqual(result, expected);
});
});
Expand Down
82 changes: 58 additions & 24 deletions packages/opentelemetry-exporter-collector/test/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ if (typeof Buffer === 'undefined') {
};
}

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',
},
];

const traceIdArr = [
31,
16,
Expand Down Expand Up @@ -152,22 +168,6 @@ export const mockedReadableSpan: ReadableSpan = {
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',
Expand Down Expand Up @@ -246,6 +246,42 @@ export const multiResourceTrace: ReadableSpan[] = [
},
];

export const multiResourceMetrics: MetricRecord[] = [
{
...mockCounter,
resource: mockedResources[0],
instrumentationLibrary: mockedInstrumentationLibraries[0],
},
{
...mockObserver,
resource: mockedResources[1],
instrumentationLibrary: mockedInstrumentationLibraries[0],
},
{
...mockCounter,
resource: mockedResources[0],
instrumentationLibrary: mockedInstrumentationLibraries[0],
},
];

export const multiInstrumentationLibraryMetrics: MetricRecord[] = [
{
...mockCounter,
resource: mockedResources[0],
instrumentationLibrary: mockedInstrumentationLibraries[0],
},
{
...mockObserver,
resource: mockedResources[0],
instrumentationLibrary: mockedInstrumentationLibraries[1],
},
{
...mockCounter,
resource: mockedResources[0],
instrumentationLibrary: mockedInstrumentationLibraries[0],
},
];

export const multiInstrumentationLibraryTrace: ReadableSpan[] = [
{
...basicTrace[0],
Expand Down Expand Up @@ -770,11 +806,7 @@ export function ensureExportMetricsServiceRequestIsSet(
json: collectorTypes.opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest
) {
const resourceMetrics = json.resourceMetrics;
assert.strictEqual(
resourceMetrics && resourceMetrics.length,
1,
'resourceSpans is missing'
);
assert.strictEqual(resourceMetrics.length, 2, 'resourceMetrics is missing');

const resource = resourceMetrics[0].resource;
assert.strictEqual(!!resource, true, 'resource is missing');
Expand All @@ -784,7 +816,7 @@ export function ensureExportMetricsServiceRequestIsSet(
assert.strictEqual(
instrumentationLibraryMetrics && instrumentationLibraryMetrics.length,
1,
'instrumentationLibrarySpans is missing'
'instrumentationLibraryMetrics is missing'
);

const instrumentationLibrary =
Expand All @@ -795,8 +827,10 @@ export function ensureExportMetricsServiceRequestIsSet(
'instrumentationLibrary is missing'
);

const metrics = instrumentationLibraryMetrics[0].metrics;
assert.strictEqual(metrics.length, 2, 'Metrics are missing');
const metric1 = resourceMetrics[0].instrumentationLibraryMetrics[0].metrics;
const metric2 = resourceMetrics[1].instrumentationLibraryMetrics[0].metrics;
assert.strictEqual(metric1.length, 1, 'Metrics are missing');
assert.strictEqual(metric2.length, 1, 'Metrics are missing');
}

export function ensureMetadataIsCorrect(
Expand Down
Loading

0 comments on commit b232bba

Please sign in to comment.