diff --git a/packages/opentelemetry-metrics/package.json b/packages/opentelemetry-metrics/package.json index ebf791c0a2d..a7db5104296 100644 --- a/packages/opentelemetry-metrics/package.json +++ b/packages/opentelemetry-metrics/package.json @@ -41,11 +41,13 @@ "devDependencies": { "@types/mocha": "^5.2.7", "@types/node": "^12.6.9", + "@types/sinon": "^7.0.13", "codecov": "^3.5.0", "gts": "^1.1.0", "mocha": "^6.2.0", "nyc": "^14.1.1", "rimraf": "^3.0.0", + "sinon": "^7.5.0", "ts-mocha": "^6.0.0", "ts-node": "^8.3.0", "tslint-consistent-codestyle": "^1.15.1", diff --git a/packages/opentelemetry-metrics/src/export/ConsoleMetricExporter.ts b/packages/opentelemetry-metrics/src/export/ConsoleMetricExporter.ts new file mode 100644 index 00000000000..5702d7258b7 --- /dev/null +++ b/packages/opentelemetry-metrics/src/export/ConsoleMetricExporter.ts @@ -0,0 +1,58 @@ +/*! + * Copyright 2019, 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 { MetricExporter, ReadableMetric } from './types'; +import { ExportResult } from '@opentelemetry/base'; + +/** + * This is implementation of {@link MetricExporter} that prints metrics data to + * the console. This class can be used for diagnostic purposes. + */ +export class ConsoleMetricExporter implements MetricExporter { + export( + metrics: ReadableMetric[], + resultCallback: (result: ExportResult) => void + ): void { + for (const metric of metrics) { + const descriptor = metric.descriptor; + const timeseries = metric.timeseries; + console.log({ + name: descriptor.name, + description: descriptor.description, + }); + + for (const ts of timeseries) { + const labels = descriptor.labelKeys + .map((k, i) => [k, ts.labelValues[i]]) + .reduce( + (p, c) => ({ + ...p, + [c[0] as string]: typeof c[1] === 'string' ? c[1] : c[1].value, + }), + {} + ); + for (const point of ts.points) { + console.log({ labels, value: point.value }); + } + } + } + return resultCallback(ExportResult.SUCCESS); + } + + shutdown(): void { + // By default does nothing + } +} diff --git a/packages/opentelemetry-metrics/src/index.ts b/packages/opentelemetry-metrics/src/index.ts index 6c1d1c23b9c..71f30b58c44 100644 --- a/packages/opentelemetry-metrics/src/index.ts +++ b/packages/opentelemetry-metrics/src/index.ts @@ -17,4 +17,5 @@ export * from './Handle'; export * from './Meter'; export * from './Metric'; +export * from './export/ConsoleMetricExporter'; export * from './export/types'; diff --git a/packages/opentelemetry-metrics/test/export/ConsoleMetricExporter.test.ts b/packages/opentelemetry-metrics/test/export/ConsoleMetricExporter.test.ts new file mode 100644 index 00000000000..ac4d12794d5 --- /dev/null +++ b/packages/opentelemetry-metrics/test/export/ConsoleMetricExporter.test.ts @@ -0,0 +1,61 @@ +/*! + * Copyright 2019, 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 sinon from 'sinon'; +import { ConsoleMetricExporter, Meter, GaugeMetric } from '../../src'; + +describe('ConsoleMetricExporter', () => { + let consoleExporter: ConsoleMetricExporter; + let previousConsoleLog: any; + + beforeEach(() => { + previousConsoleLog = console.log; + console.log = () => {}; + consoleExporter = new ConsoleMetricExporter(); + }); + + afterEach(() => { + console.log = previousConsoleLog; + }); + + describe('.export()', () => { + it('should export information about metrics', () => { + const spyConsole = sinon.spy(console, 'log'); + + const meter = new Meter(); + meter.addExporter(consoleExporter); + const gauge = meter.createGauge('gauge', { + description: 'a test description', + labelKeys: ['key1', 'key2'], + }) as GaugeMetric; + const handle = gauge.getHandle( + meter.labels({ key1: 'labelValue1', key2: 'labelValue2' }) + ); + handle.set(10); + const [descriptor, timeseries] = spyConsole.args; + assert.deepStrictEqual(descriptor, [ + { description: 'a test description', name: 'gauge' }, + ]); + assert.deepStrictEqual(timeseries, [ + { + labels: { key1: 'labelValue1', key2: 'labelValue2' }, + value: 10, + }, + ]); + }); + }); +});