/* * 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 * as assert from 'assert'; import * as transform from '../../src/transformMetrics'; import { mockCounter, mockDoubleCounter, mockObserver, ensureCounterIsCorrect, ensureDoubleCounterIsCorrect, ensureObserverIsCorrect, ensureValueRecorderIsCorrect, mockValueRecorder, mockedResources, mockedInstrumentationLibraries, multiResourceMetricsGet, multiInstrumentationLibraryMetricsGet, mockSumObserver, mockUpDownSumObserver, ensureSumObserverIsCorrect, ensureUpDownSumObserverIsCorrect, } from '../helper'; import { BoundCounter, BoundObserver, BoundValueRecorder, Metric, SumAggregator, } from '@opentelemetry/metrics'; import { hrTimeToNanoseconds } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; import * as api from '@opentelemetry/api'; describe('transformMetrics', () => { describe('toCollectorMetric', async () => { let counter: Metric & api.Counter; let doubleCounter: Metric & api.Counter; let observer: Metric & api.ValueObserver; let sumObserver: Metric & api.SumObserver; let upDownSumObserver: Metric & api.UpDownSumObserver; let recorder: Metric & api.ValueRecorder; beforeEach(() => { counter = mockCounter(); doubleCounter = mockDoubleCounter(); let count1 = 0; let count2 = 0; let count3 = 0; function getValue(count: number) { if (count % 2 == 0) { return 3; } return -1; } observer = mockObserver(observerResult => { count1++; observerResult.observe(getValue(count1), {}); }); sumObserver = mockSumObserver(observerResult => { count2++; observerResult.observe(getValue(count2), {}); }); upDownSumObserver = mockUpDownSumObserver(observerResult => { count3++; observerResult.observe(getValue(count3), {}); }); recorder = mockValueRecorder(); // Counter counter.add(1); // Double Counter doubleCounter.add(8); // ValueRecorder recorder.record(7); recorder.record(14); }); it('should convert metric', async () => { const counterMetric = (await counter.getMetricRecord())[0]; ensureCounterIsCorrect( transform.toCollectorMetric(counterMetric, 1592602232694000000), hrTimeToNanoseconds(await counterMetric.aggregator.toPoint().timestamp) ); const doubleCounterMetric = (await doubleCounter.getMetricRecord())[0]; ensureDoubleCounterIsCorrect( transform.toCollectorMetric(doubleCounterMetric, 1592602232694000000), hrTimeToNanoseconds(doubleCounterMetric.aggregator.toPoint().timestamp) ); await observer.getMetricRecord(); await observer.getMetricRecord(); const observerMetric = (await observer.getMetricRecord())[0]; ensureObserverIsCorrect( transform.toCollectorMetric(observerMetric, 1592602232694000000), hrTimeToNanoseconds(observerMetric.aggregator.toPoint().timestamp), -1 ); // collect 3 times await sumObserver.getMetricRecord(); await sumObserver.getMetricRecord(); const sumObserverMetric = (await sumObserver.getMetricRecord())[0]; ensureSumObserverIsCorrect( transform.toCollectorMetric(sumObserverMetric, 1592602232694000000), hrTimeToNanoseconds(sumObserverMetric.aggregator.toPoint().timestamp), 3 ); // collect 3 times await upDownSumObserver.getMetricRecord(); await upDownSumObserver.getMetricRecord(); const upDownSumObserverMetric = ( await upDownSumObserver.getMetricRecord() )[0]; ensureUpDownSumObserverIsCorrect( transform.toCollectorMetric( upDownSumObserverMetric, 1592602232694000000 ), hrTimeToNanoseconds( upDownSumObserverMetric.aggregator.toPoint().timestamp ), -1 ); const recorderMetric = (await recorder.getMetricRecord())[0]; ensureValueRecorderIsCorrect( transform.toCollectorMetric(recorderMetric, 1592602232694000000), hrTimeToNanoseconds(recorderMetric.aggregator.toPoint().timestamp), [0, 100], [0, 2, 0] ); }); it('should convert metric labels value to string', () => { const metric = transform.toCollectorMetric( { descriptor: { name: 'name', description: 'description', unit: 'unit', metricKind: 0, valueType: 0, }, labels: { foo: (1 as unknown) as string }, aggregator: new SumAggregator(), resource: new Resource({}), instrumentationLibrary: { name: 'x', version: 'y' }, }, 1592602232694000000 ); const collectorMetric = metric.intSum?.dataPoints[0]; assert.strictEqual(collectorMetric?.labels[0].value, '1'); }); }); describe('groupMetricsByResourceAndLibrary', () => { it('should group by resource', async () => { const [resource1, resource2] = mockedResources; const [library] = mockedInstrumentationLibraries; const [metric1, metric2, metric3] = multiResourceMetricsGet( observerResult => { observerResult.observe(1, {}); } ); const expected = new Map([ [resource1, new Map([[library, [metric1, metric3]]])], [resource2, new Map([[library, [metric2]]])], ]); const result = transform.groupMetricsByResourceAndLibrary( multiResourceMetricsGet(observerResult => { observerResult.observe(1, {}); }) ); assert.deepStrictEqual(result, expected); }); it('should group by instrumentation library', async () => { const [resource] = mockedResources; const [lib1, lib2] = mockedInstrumentationLibraries; const [ metric1, metric2, metric3, ] = multiInstrumentationLibraryMetricsGet(observerResult => {}); const expected = new Map([ [ resource, new Map([ [lib1, [metric1, metric3]], [lib2, [metric2]], ]), ], ]); const result = transform.groupMetricsByResourceAndLibrary( multiInstrumentationLibraryMetricsGet(observerResult => {}) ); assert.deepStrictEqual(result, expected); }); }); });