-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Propose new API for aggregating metrics #54
base: master
Are you sure you want to change the base?
Changes from 3 commits
8551294
30e7680
962b408
1ed7da3
5f8b8a5
f0c1af6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
|
@@ -297,6 +308,141 @@ test('context is preserved across flush() calls', async () => { | |
} | ||
}); | ||
|
||
test('putMetricWithDimensions metric only', async () => { | ||
// 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 () => { | ||
// arrange | ||
const logger = createLoggerWithDefaultDimensions(); | ||
|
||
// act | ||
logger.putMetricWithDimensions({ | ||
metrics: { "MyMetric": 100 }, | ||
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 }] | ||
}); | ||
|
||
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: { | ||
Metric1: 100, | ||
}, | ||
namespace: "My Namespace", | ||
dimensions: [ | ||
yaozhaoy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ 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([ | ||
{ ...DEFAULT_DIMENSIONS, client }, | ||
{ ...DEFAULT_DIMENSIONS, pageType }, | ||
{ ...DEFAULT_DIMENSIONS, client, pageType }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the part I'm not certain of. One question I have is what are users most likely to do? Do users prefer the default dimensions are included most of the time or are users overwriting them more often than not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a tough one 😄 I don't use the default dimensions and having One way to see it could be to keep the same behaviour that For people that don't use the default dimensions, I would expect to either set There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jaredcnance any thoughts on this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now I’m leaning towards the proposal as is. I think it may make sense to offer a global configuration to disable default dimensions entirely. I suspect you either want them or you don’t and you may want that applied uniformly. |
||
]); | ||
}); | ||
|
||
test('putMetricWithDimensions without default dimensions', async () => { | ||
// arrange | ||
const logger = createLoggerWithDefaultDimensions(); | ||
const client = 'client'; | ||
const pageType = 'pageType'; | ||
|
||
// act | ||
logger.putMetricWithDimensions({ | ||
metrics: { | ||
Metric1: 100 | ||
}, | ||
namespace: "My-Namespace", | ||
dimensions: [ | ||
{ client }, | ||
{ pageType }, | ||
{ client, pageType }, | ||
], | ||
stripDefaultDimensions: true | ||
}); | ||
|
||
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) => { | ||
expect(sink.events).toHaveLength(1); | ||
const dimensionSets = sink.events[0].getDimensions(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type declaration doesn't allow the definition of the "unit" (e.g. count, milliseconds, etc.).
I was hoping to set something like:
Also, multiple metrics may apply to the same dimensions, shouldn't we define this as an array of metric items as discussed in #46?
Example:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah agree on unit. The idea here was that the key would be used as the metric name which naturally supports multiple distinct metrics. I don’t recall exactly why I proposed it this way, probably because it was less verbose and easier to read but once you add units to the mix it breaks down. Happy to go with this.