From 855129467b038e8a40aac5e26cccc91baa479e99 Mon Sep 17 00:00:00 2001 From: Jared Nance Date: Wed, 19 Aug 2020 08:29:27 -0700 Subject: [PATCH 1/5] Propose new API for aggregating metrics --- src/logger/MetricsLogger.ts | 11 ++++++++ src/logger/__tests__/MetricsLogger.test.ts | 30 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/logger/MetricsLogger.ts b/src/logger/MetricsLogger.ts index fe5ee84..d22a549 100644 --- a/src/logger/MetricsLogger.ts +++ b/src/logger/MetricsLogger.ts @@ -19,6 +19,13 @@ import { IEnvironment } from '../environment/IEnvironment'; import { MetricsContext } from './MetricsContext'; import { Unit } from './Unit'; +type Metrics = { [key: string]: number | number[]; }; +type MetricWithDimensions = { + metrics: Metrics, + namespace?: string | undefined, + dimensions?: Array> | undefined, +}; + /** * An async metrics logger. * Use this interface to publish logs to CloudWatch Logs @@ -114,6 +121,10 @@ export class MetricsLogger { return this; } + public putMetricWithDimensions(metricWithDimensions: MetricWithDimensions): MetricsLogger { + return this; + } + /** * Creates a new logger using the same contextual data as * the previous logger. This allows you to flush the instances diff --git a/src/logger/__tests__/MetricsLogger.test.ts b/src/logger/__tests__/MetricsLogger.test.ts index 984ca79..fb3c899 100644 --- a/src/logger/__tests__/MetricsLogger.test.ts +++ b/src/logger/__tests__/MetricsLogger.test.ts @@ -297,6 +297,36 @@ test('context is preserved across flush() calls', async () => { } }); +test('putMetricWithDimensions example', async () => { + // this metric will use the default namespace and dimensions + logger.putMetricWithDimensions({ + metrics: { "MyMetric": 100 } + }); + + // this metric will use the default dimensions + logger.putMetricWithDimensions({ + metrics: { "MyMetric": 100 }, + namespace: "My Namespace" + }); + + // publish multiple metrics along multiple dimensions + const client = 'client'; + const pageType = 'pageType'; + logger.putMetricWithDimensions({ + metrics: { + Metric1: 100, + Metric2: 200, + }, + namespace: "My Namespace", + dimensions: [ + { client }, + { pageType }, + { client, pageType }, + ] + }); +}); + + const expectDimension = (key: string, value: string) => { expect(sink.events).toHaveLength(1); const dimensionSets = sink.events[0].getDimensions(); From 30e76804a4eebb377d585986ae121d0328b7226c Mon Sep 17 00:00:00 2001 From: Jared Nance Date: Wed, 19 Aug 2020 19:30:05 -0700 Subject: [PATCH 2/5] add proposal for stripDefaultDimensions --- src/logger/MetricsLogger.ts | 1 + src/logger/__tests__/MetricsLogger.test.ts | 54 ++++++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/logger/MetricsLogger.ts b/src/logger/MetricsLogger.ts index d22a549..b2e0009 100644 --- a/src/logger/MetricsLogger.ts +++ b/src/logger/MetricsLogger.ts @@ -24,6 +24,7 @@ type MetricWithDimensions = { metrics: Metrics, namespace?: string | undefined, dimensions?: Array> | undefined, + stripDefaultDimensions?: boolean | undefined; }; /** diff --git a/src/logger/__tests__/MetricsLogger.test.ts b/src/logger/__tests__/MetricsLogger.test.ts index fb3c899..06441b4 100644 --- a/src/logger/__tests__/MetricsLogger.test.ts +++ b/src/logger/__tests__/MetricsLogger.test.ts @@ -297,25 +297,40 @@ test('context is preserved across flush() calls', async () => { } }); -test('putMetricWithDimensions example', async () => { +test('putMetricWithDimensions metric only', async () => { // this metric will use the default namespace and dimensions logger.putMetricWithDimensions({ metrics: { "MyMetric": 100 } }); +}); +test('putMetricWithDimensions single metric with namespace', async () => { // this metric will use the default dimensions logger.putMetricWithDimensions({ metrics: { "MyMetric": 100 }, namespace: "My Namespace" }); +}); + + +test('putMetricWithDimensions with single dimensions and default namespace', async () => { + const client = 'client'; + logger.putMetricWithDimensions({ + metrics: { + Metric1: 100 + }, + dimensions: [ + { client } + ] + }); +}); - // publish multiple metrics along multiple dimensions +test('putMetricWithDimensions along multiple dimensions', async () => { const client = 'client'; const pageType = 'pageType'; logger.putMetricWithDimensions({ metrics: { Metric1: 100, - Metric2: 200, }, namespace: "My Namespace", dimensions: [ @@ -326,6 +341,39 @@ test('putMetricWithDimensions example', async () => { }); }); +test('putMetricWithDimensions without default dimensions', async () => { + const client = 'client'; + const pageType = 'pageType'; + logger.putMetricWithDimensions({ + metrics: { + Metric1: 100 + }, + namespace: "My Namespace", + dimensions: [ + { client }, + { pageType }, + { client, pageType }, + ], + stripDefaultDimensions: true + }); +}); + +test('putMetricWithDimensions with multiple metrics along multiple dimensions', async () => { + const client = 'client'; + const pageType = 'pageType'; + logger.putMetricWithDimensions({ + metrics: { + Metric1: 100, + Metric2: [100, 200], + }, + namespace: "My Namespace", + dimensions: [ + { client }, + { pageType }, + { client, pageType }, + ] + }); +}); const expectDimension = (key: string, value: string) => { expect(sink.events).toHaveLength(1); From 962b408347bd38745380e426e0aedd466988099e Mon Sep 17 00:00:00 2001 From: Jared Nance Date: Wed, 19 Aug 2020 19:51:14 -0700 Subject: [PATCH 3/5] add examples --- src/logger/__tests__/MetricsLogger.test.ts | 124 ++++++++++++++++----- 1 file changed, 96 insertions(+), 28 deletions(-) diff --git a/src/logger/__tests__/MetricsLogger.test.ts b/src/logger/__tests__/MetricsLogger.test.ts index 06441b4..74a8580 100644 --- a/src/logger/__tests__/MetricsLogger.test.ts +++ b/src/logger/__tests__/MetricsLogger.test.ts @@ -7,6 +7,7 @@ import { IEnvironment } from '../../environment/IEnvironment'; import { ISink } from '../../sinks/Sink'; import { MetricsContext } from '../MetricsContext'; import { MetricsLogger } from '../MetricsLogger'; +import { Constants } from '../../Constants'; const createSink = () => new TestSink(); const createEnvironment = (sink: ISink) => { @@ -21,6 +22,16 @@ const createEnvironment = (sink: ISink) => { }; const createLogger = (env: EnvironmentProvider) => new MetricsLogger(env); +const DEFAULT_DIMENSIONS = { Foo: 'Bar' }; +const createLoggerWithDefaultDimensions = (): MetricsLogger => { + const context = MetricsContext.empty(); + context.setDefaultDimensions(DEFAULT_DIMENSIONS); + + const sink = createSink(); + const env = createEnvironment(sink); + return new MetricsLogger(() => Promise.resolve(env), context); +} + let sink: TestSink; let environment: IEnvironment; let logger: MetricsLogger; @@ -298,38 +309,80 @@ test('context is preserved across flush() calls', async () => { }); test('putMetricWithDimensions metric only', async () => { - // this metric will use the default namespace and dimensions + // arrange + const logger = createLoggerWithDefaultDimensions(); + + // act logger.putMetricWithDimensions({ metrics: { "MyMetric": 100 } }); + + await logger.flush(); + + // assert + expect(sink.events).toHaveLength(1); + const evt = sink.events[0]; + expect(evt.metrics.size).toBe(1); + expect(evt.metrics.get("MyMetric")).toBe(100); + // everything else should be defaults + expect(evt.namespace).toBe(Constants.DEFAULT_NAMESPACE); + expect(evt.getDimensions()[0]).toBe(DEFAULT_DIMENSIONS); }); test('putMetricWithDimensions single metric with namespace', async () => { - // this metric will use the default dimensions + // arrange + const logger = createLoggerWithDefaultDimensions(); + + // act logger.putMetricWithDimensions({ metrics: { "MyMetric": 100 }, - namespace: "My Namespace" + namespace: "My-Namespace" }); + + // act + await logger.flush(); + + // assert + expect(sink.events).toHaveLength(1); + const evt = sink.events[0]; + expect(evt.metrics.size).toBe(1); + expect(evt.metrics.get("MyMetric")).toBe(100); + expect(evt.namespace).toBe("My-Namespace"); + expect(evt.getDimensions()[0]).toBe(DEFAULT_DIMENSIONS); }); test('putMetricWithDimensions with single dimensions and default namespace', async () => { + // arrange + const logger = createLoggerWithDefaultDimensions(); const client = 'client'; + + // act logger.putMetricWithDimensions({ - metrics: { - Metric1: 100 - }, - dimensions: [ - { client } - ] + metrics: { Metric1: 100 }, + dimensions: [{ client }] }); + + await logger.flush(); + + // assert + expect(sink.events).toHaveLength(1); + const evt = sink.events[0]; + expect(evt.metrics.size).toBe(1); + expect(evt.metrics.get("MyMetric")).toBe(100); + expect(evt.namespace).toBe(Constants.DEFAULT_NAMESPACE); + expect(evt.getDimensions()).toBe([{ ...DEFAULT_DIMENSIONS, client }]); }); test('putMetricWithDimensions along multiple dimensions', async () => { + // arrange + const logger = createLoggerWithDefaultDimensions(); const client = 'client'; const pageType = 'pageType'; + + // act logger.putMetricWithDimensions({ - metrics: { + metrics: { Metric1: 100, }, namespace: "My Namespace", @@ -339,16 +392,34 @@ test('putMetricWithDimensions along multiple dimensions', async () => { { client, pageType }, ] }); + + await logger.flush(); + + // assert + expect(sink.events).toHaveLength(1); + const evt = sink.events[0]; + expect(evt.metrics.size).toBe(1); + expect(evt.metrics.get("MyMetric")).toBe(100); + expect(evt.namespace).toBe("My-Namespace"); + expect(evt.getDimensions()[0]).toBe([ + { ...DEFAULT_DIMENSIONS, client }, + { ...DEFAULT_DIMENSIONS, pageType }, + { ...DEFAULT_DIMENSIONS, client, pageType }, + ]); }); test('putMetricWithDimensions without default dimensions', async () => { + // arrange + const logger = createLoggerWithDefaultDimensions(); const client = 'client'; const pageType = 'pageType'; + + // act logger.putMetricWithDimensions({ - metrics: { + metrics: { Metric1: 100 }, - namespace: "My Namespace", + namespace: "My-Namespace", dimensions: [ { client }, { pageType }, @@ -356,23 +427,20 @@ test('putMetricWithDimensions without default dimensions', async () => { ], stripDefaultDimensions: true }); -}); -test('putMetricWithDimensions with multiple metrics along multiple dimensions', async () => { - const client = 'client'; - const pageType = 'pageType'; - logger.putMetricWithDimensions({ - metrics: { - Metric1: 100, - Metric2: [100, 200], - }, - namespace: "My Namespace", - dimensions: [ - { client }, - { pageType }, - { client, pageType }, - ] - }); + await logger.flush(); + + // assert + expect(sink.events).toHaveLength(1); + const evt = sink.events[0]; + expect(evt.metrics.size).toBe(1); + expect(evt.metrics.get("MyMetric")).toBe(100); + expect(evt.namespace).toBe("My-Namespace"); + expect(evt.getDimensions()[0]).toBe([ + { client }, + { pageType }, + { client, pageType }, + ]); }); const expectDimension = (key: string, value: string) => { From 5f8b8a5dc6cfbe69b8d25f3c1e6563917859deba Mon Sep 17 00:00:00 2001 From: Jared Nance Date: Mon, 2 Nov 2020 21:48:51 -0600 Subject: [PATCH 4/5] Apply PR feedback --- src/logger/MetricsLogger.ts | 19 +++++++-- src/logger/__tests__/MetricsLogger.test.ts | 49 ++++++++++++++++------ 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/logger/MetricsLogger.ts b/src/logger/MetricsLogger.ts index b2e0009..675b31a 100644 --- a/src/logger/MetricsLogger.ts +++ b/src/logger/MetricsLogger.ts @@ -19,11 +19,16 @@ import { IEnvironment } from '../environment/IEnvironment'; import { MetricsContext } from './MetricsContext'; import { Unit } from './Unit'; -type Metrics = { [key: string]: number | number[]; }; -type MetricWithDimensions = { - metrics: Metrics, +type Metrics = { name: string, value: number, unit?: Unit }; +type MetricsWithDimensions = { + metrics: Metrics[], namespace?: string | undefined, dimensions?: Array> | undefined, + + /** + * Do not apply default dimensions such as ServiceName and ServiceType. + * The default behavior is to include the default dimensions. + */ stripDefaultDimensions?: boolean | undefined; }; @@ -122,7 +127,13 @@ export class MetricsLogger { return this; } - public putMetricWithDimensions(metricWithDimensions: MetricWithDimensions): MetricsLogger { + /** + * Add a collection of metrics to be aggregated on a different set of dimensions + * than the default dimension set. + * + * @param metricWithDimensions + */ + public putMetricWithDimensions(metricWithDimensions: MetricsWithDimensions): MetricsLogger { return this; } diff --git a/src/logger/__tests__/MetricsLogger.test.ts b/src/logger/__tests__/MetricsLogger.test.ts index 74a8580..c0b7549 100644 --- a/src/logger/__tests__/MetricsLogger.test.ts +++ b/src/logger/__tests__/MetricsLogger.test.ts @@ -314,7 +314,7 @@ test('putMetricWithDimensions metric only', async () => { // act logger.putMetricWithDimensions({ - metrics: { "MyMetric": 100 } + metrics: [{ name: "MyMetric", value: 100 }] }); await logger.flush(); @@ -329,13 +329,36 @@ test('putMetricWithDimensions metric only', async () => { expect(evt.getDimensions()[0]).toBe(DEFAULT_DIMENSIONS); }); +test('putMetricWithDimensions metric and unit', async () => { + // arrange + const logger = createLoggerWithDefaultDimensions(); + + // act + logger.putMetricWithDimensions({ + metrics: [{ name: "MyMetric", value: 100, unit: Unit.Bytes }] + }); + + await logger.flush(); + + // assert + expect(sink.events).toHaveLength(1); + const evt = sink.events[0]; + expect(evt.metrics.size).toBe(1); + const resultMetric = evt.metrics.get("MyMetric"); + expect(resultMetric.values).toBe([100]); + expect(resultMetric.unit).toBe('Bytes'); + // everything else should be defaults + expect(evt.namespace).toBe(Constants.DEFAULT_NAMESPACE); + expect(evt.getDimensions()[0]).toBe(DEFAULT_DIMENSIONS); +}); + test('putMetricWithDimensions single metric with namespace', async () => { // arrange const logger = createLoggerWithDefaultDimensions(); // act logger.putMetricWithDimensions({ - metrics: { "MyMetric": 100 }, + metrics: [{ name: "MyMetric", value: 100 }], namespace: "My-Namespace" }); @@ -346,7 +369,8 @@ test('putMetricWithDimensions single metric with namespace', async () => { expect(sink.events).toHaveLength(1); const evt = sink.events[0]; expect(evt.metrics.size).toBe(1); - expect(evt.metrics.get("MyMetric")).toBe(100); + const resultMetric = evt.metrics.get("MyMetric"); + expect(resultMetric.values).toBe([100]); expect(evt.namespace).toBe("My-Namespace"); expect(evt.getDimensions()[0]).toBe(DEFAULT_DIMENSIONS); }); @@ -359,7 +383,7 @@ test('putMetricWithDimensions with single dimensions and default namespace', asy // act logger.putMetricWithDimensions({ - metrics: { Metric1: 100 }, + metrics: [{ name: "MyMetric", value: 100 }], dimensions: [{ client }] }); @@ -369,7 +393,8 @@ test('putMetricWithDimensions with single dimensions and default namespace', asy expect(sink.events).toHaveLength(1); const evt = sink.events[0]; expect(evt.metrics.size).toBe(1); - expect(evt.metrics.get("MyMetric")).toBe(100); + const resultMetric = evt.metrics.get("MyMetric"); + expect(resultMetric.values).toBe([100]); expect(evt.namespace).toBe(Constants.DEFAULT_NAMESPACE); expect(evt.getDimensions()).toBe([{ ...DEFAULT_DIMENSIONS, client }]); }); @@ -382,9 +407,7 @@ test('putMetricWithDimensions along multiple dimensions', async () => { // act logger.putMetricWithDimensions({ - metrics: { - Metric1: 100, - }, + metrics: [{ name: "MyMetric", value: 100 }], namespace: "My Namespace", dimensions: [ { client }, @@ -399,7 +422,8 @@ test('putMetricWithDimensions along multiple dimensions', async () => { expect(sink.events).toHaveLength(1); const evt = sink.events[0]; expect(evt.metrics.size).toBe(1); - expect(evt.metrics.get("MyMetric")).toBe(100); + const resultMetric = evt.metrics.get("MyMetric"); + expect(resultMetric.values).toBe([100]); expect(evt.namespace).toBe("My-Namespace"); expect(evt.getDimensions()[0]).toBe([ { ...DEFAULT_DIMENSIONS, client }, @@ -416,9 +440,7 @@ test('putMetricWithDimensions without default dimensions', async () => { // act logger.putMetricWithDimensions({ - metrics: { - Metric1: 100 - }, + metrics: [{ name: "MyMetric", value: 100 }], namespace: "My-Namespace", dimensions: [ { client }, @@ -434,7 +456,8 @@ test('putMetricWithDimensions without default dimensions', async () => { expect(sink.events).toHaveLength(1); const evt = sink.events[0]; expect(evt.metrics.size).toBe(1); - expect(evt.metrics.get("MyMetric")).toBe(100); + const resultMetric = evt.metrics.get("MyMetric"); + expect(resultMetric.values).toBe([100]); expect(evt.namespace).toBe("My-Namespace"); expect(evt.getDimensions()[0]).toBe([ { client }, From f0c1af6b5374d77e702c90b66db3e831daedaf3e Mon Sep 17 00:00:00 2001 From: Jared Nance Date: Mon, 2 Nov 2020 22:45:15 -0600 Subject: [PATCH 5/5] Allow multiple metric directives in the metric context --- src/logger/MetricValues.ts | 6 ++-- src/logger/MetricsContext.ts | 68 ++++++++++++++++++++++++------------ src/logger/MetricsLogger.ts | 7 +++- 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/logger/MetricValues.ts b/src/logger/MetricValues.ts index d7c9ba0..87b885d 100644 --- a/src/logger/MetricValues.ts +++ b/src/logger/MetricValues.ts @@ -16,11 +16,11 @@ import { Unit } from '..'; */ export class MetricValues { - public values: number[]; + public values: number[] = []; public unit: string; - constructor(value: number, unit?: Unit | string) { - this.values = [value]; + constructor(value: number | number[], unit?: Unit | string) { + this.values = this.values.concat(value); this.unit = unit || 'None'; } diff --git a/src/logger/MetricsContext.ts b/src/logger/MetricsContext.ts index 430c179..cf5997a 100644 --- a/src/logger/MetricsContext.ts +++ b/src/logger/MetricsContext.ts @@ -23,6 +23,12 @@ interface IProperties { } type Metrics = Map; +type DimensionSet = Record; +type MetricsDirective = { + namespace: string; + dimensions: DimensionSet[] + metrics: Metrics +} export class MetricsContext { /** @@ -32,11 +38,10 @@ export class MetricsContext { return new MetricsContext(); } - public namespace: string; public properties: IProperties; - public metrics: Metrics = new Map(); public meta: Record = {}; - private dimensions: Array>; + private defaultMetricsDirective: MetricsDirective; + private metricDirectives: MetricsDirective[]; private defaultDimensions: Record; private shouldUseDefaultDimensions = true; @@ -57,15 +62,19 @@ export class MetricsContext { dimensions?: Array>, defaultDimensions?: Record, ) { - this.namespace = namespace || Configuration.namespace this.properties = properties || {}; - this.dimensions = dimensions || []; this.meta.Timestamp = new Date().getTime(); this.defaultDimensions = defaultDimensions || {}; + this.defaultMetricsDirective = { + namespace: namespace || Configuration.namespace, + metrics: new Map(), + dimensions: dimensions || [] + }; + this.metricDirectives = [ this.defaultMetricsDirective ]; } public setNamespace(value: string): void { - this.namespace = value; + this.defaultMetricsDirective.namespace = value; } public setProperty(key: string, value: unknown): void { @@ -89,13 +98,13 @@ export class MetricsContext { * @param dimensions */ public putDimensions(incomingDimensionSet: Record): void { - if (this.dimensions.length === 0) { - this.dimensions.push(incomingDimensionSet); + if (this.defaultMetricsDirective.dimensions.length === 0) { + this.defaultMetricsDirective.dimensions.push(incomingDimensionSet); return; } - for (let i = 0; i < this.dimensions.length; i++) { - const existingDimensionSet = this.dimensions[i]; + for (let i = 0; i < this.defaultMetricsDirective.dimensions.length; i++) { + const existingDimensionSet = this.defaultMetricsDirective.dimensions[i]; // check for duplicate dimensions when putting // this is an O(n^2) operation, but since we never expect to have more than @@ -104,20 +113,28 @@ export class MetricsContext { const existingDimensionSetKeys = Object.keys(existingDimensionSet); const incomingDimensionSetKeys = Object.keys(incomingDimensionSet); if (existingDimensionSetKeys.length !== incomingDimensionSetKeys.length) { - this.dimensions.push(incomingDimensionSet); + this.defaultMetricsDirective.dimensions.push(incomingDimensionSet); return; } for (let j = 0; j < existingDimensionSetKeys.length; j++) { if (!incomingDimensionSetKeys.includes(existingDimensionSetKeys[j])) { // we're done now because we know that the dimensions keys are not identical - this.dimensions.push(incomingDimensionSet); + this.defaultMetricsDirective.dimensions.push(incomingDimensionSet); return; } } } } + public putMetricDirective(metrics: Metrics, dimensions: DimensionSet[], namespace?: string): void { + this.metricDirectives.push({ + namespace: namespace || Configuration.namespace, + metrics, + dimensions + }); + } + /** * Overwrite all dimensions. * @@ -125,42 +142,49 @@ export class MetricsContext { */ public setDimensions(dimensionSets: Array>): void { this.shouldUseDefaultDimensions = false; - this.dimensions = dimensionSets; + this.defaultMetricsDirective.dimensions = dimensionSets; } /** - * Get the current dimensions. + * Get the current dimensions on the default metric directive. */ public getDimensions(): Array> { // caller has explicitly called setDimensions if (this.shouldUseDefaultDimensions === false) { - return this.dimensions; + return this.defaultMetricsDirective.dimensions; } // if there are no default dimensions, return the custom dimensions if (Object.keys(this.defaultDimensions).length === 0) { - return this.dimensions; + return this.defaultMetricsDirective.dimensions; } // if default dimensions have been provided, but no custom dimensions, use the defaults - if (this.dimensions.length === 0) { + if (this.defaultMetricsDirective.dimensions.length === 0) { return [this.defaultDimensions]; } // otherwise, merge the dimensions // we do this on the read path because default dimensions // may get updated asynchronously by environment detection - return this.dimensions.map(custom => { + return this.defaultMetricsDirective.dimensions.map(custom => { return { ...this.defaultDimensions, ...custom }; }); } + /** + * Add a metric to the default metric directive. + * + * @param key The name of the metric + * @param value The metric value. Note that percentiles are only supported on positive vales. + * @param unit The metric unit. Must be a valid CloudWatch metric. + */ public putMetric(key: string, value: number, unit?: Unit | string): void { - const currentMetric = this.metrics.get(key); + const currentMetric = this.defaultMetricsDirective.metrics.get(key); if (currentMetric) { currentMetric.addValue(value); } else { - this.metrics.set(key, new MetricValues(value, unit)); + this.defaultMetricsDirective.metrics.set(key, new MetricValues(value, unit)); } } @@ -169,9 +193,9 @@ export class MetricsContext { */ public createCopyWithContext(): MetricsContext { return new MetricsContext( - this.namespace, + this.defaultMetricsDirective.namespace, Object.assign({}, this.properties), - Object.assign([], this.dimensions), + Object.assign([], this.defaultMetricsDirective.dimensions), this.defaultDimensions, ); } diff --git a/src/logger/MetricsLogger.ts b/src/logger/MetricsLogger.ts index 675b31a..ca1552c 100644 --- a/src/logger/MetricsLogger.ts +++ b/src/logger/MetricsLogger.ts @@ -17,9 +17,10 @@ import Configuration from '../config/Configuration'; import { EnvironmentProvider } from '../environment/EnvironmentDetector'; import { IEnvironment } from '../environment/IEnvironment'; import { MetricsContext } from './MetricsContext'; +import { MetricValues } from './MetricValues'; import { Unit } from './Unit'; -type Metrics = { name: string, value: number, unit?: Unit }; +type Metrics = { name: string, value: number | number[], unit?: Unit }; type MetricsWithDimensions = { metrics: Metrics[], namespace?: string | undefined, @@ -134,6 +135,10 @@ export class MetricsLogger { * @param metricWithDimensions */ public putMetricWithDimensions(metricWithDimensions: MetricsWithDimensions): MetricsLogger { + this.context.putMetricDirective( + new Map(metricWithDimensions.metrics.map(m => [m.name, new MetricValues(m.value, m.unit)])), + metricWithDimensions.dimensions || [], + metricWithDimensions.namespace); return this; }