-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add MetricsBehavior flag and allow setting no totalime (#30)
Currently the only way to make it so that no `totaltime` timeseries data for a metric is emitted is to set it at the `MetricsFactory` level with `TotaltimeType.NONE`. However, many observability services (e.g. Lightstep, Datadog, Cloudwatch) charge per dimension and timeseries, so there may be cases where you want to more easily specify no `totaltime` for some metrics but not for others in order to reduce usage. This adds a new `MetricsBehavior` enum that can be specified per metric. For now, the only options for this are `DEFAULT` and `NO_TOTALTIME` (which, as the name suggests, means it won't include `totaltime`). In the future we may want to add an option e.g. to not include "prescient"/"environment" dimensions, among other possibilities.
- Loading branch information
Showing
3 changed files
with
160 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
133 changes: 133 additions & 0 deletions
133
kotlin/goodmetrics/src/test/kotlin/goodmetrics/MetricsFactoryTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package goodmetrics | ||
|
||
import kotlin.test.BeforeTest | ||
import kotlin.test.Test | ||
import kotlin.test.assertEquals | ||
|
||
internal class MetricsFactoryTest { | ||
private val emittedMetrics: MutableList<Metrics> = mutableListOf() | ||
private var nowNanos = 0L | ||
|
||
@BeforeTest | ||
fun before() { | ||
nowNanos = 0 | ||
emittedMetrics.clear() | ||
} | ||
|
||
@Test | ||
fun testDistributionTotaltimeType() { | ||
val metricsFactory = MetricsFactory( | ||
sink = emittedMetrics::add, | ||
timeSource = { nowNanos }, | ||
totaltimeType = MetricsFactory.TotaltimeType.DistributionMicroseconds | ||
) | ||
|
||
metricsFactory.record("test") { metrics -> | ||
metrics.dimension("a_dimension", "a") | ||
metrics.measure("a_measurement", 0) | ||
metrics.distribution("a_distribution", 1) | ||
} | ||
assertEquals(1, emittedMetrics.size) | ||
val metric = emittedMetrics[0] | ||
metric.assertPresence( | ||
dimensions = setOf("a_dimension"), | ||
measurements = setOf("a_measurement"), | ||
distributions = setOf("totaltime", "a_distribution") | ||
) | ||
} | ||
|
||
@Test | ||
fun testDistributionTotaltimeTypeNoTotaltimeBehavior() { | ||
val metricsFactory = MetricsFactory( | ||
sink = emittedMetrics::add, | ||
timeSource = { nowNanos }, | ||
totaltimeType = MetricsFactory.TotaltimeType.DistributionMicroseconds | ||
) | ||
|
||
metricsFactory.recordWithBehavior("test", metricsBehavior = MetricsBehavior.NO_TOTALTIME) { metrics -> | ||
metrics.dimension("a_dimension", "a") | ||
metrics.measure("a_measurement", 0) | ||
metrics.distribution("a_distribution", 1) | ||
} | ||
assertEquals(1, emittedMetrics.size) | ||
val metric = emittedMetrics[0] | ||
metric.assertPresence( | ||
dimensions = setOf("a_dimension"), | ||
measurements = setOf("a_measurement"), | ||
distributions = setOf("a_distribution") | ||
) | ||
} | ||
|
||
@Test | ||
fun testMeasurementTotaltimeType() { | ||
val metricsFactory = MetricsFactory( | ||
sink = emittedMetrics::add, | ||
timeSource = { nowNanos }, | ||
totaltimeType = MetricsFactory.TotaltimeType.MeasurementMicroseconds | ||
) | ||
|
||
metricsFactory.record("test") { metrics -> | ||
metrics.dimension("a_dimension", "a") | ||
metrics.measure("a_measurement", 0) | ||
metrics.distribution("a_distribution", 1) | ||
} | ||
assertEquals(1, emittedMetrics.size) | ||
val metric = emittedMetrics[0] | ||
metric.assertPresence( | ||
dimensions = setOf("a_dimension"), | ||
measurements = setOf("totaltime", "a_measurement"), | ||
distributions = setOf("a_distribution") | ||
) | ||
} | ||
|
||
@Test | ||
fun testMeasurementTotaltimeTypeNoTotaltimeBehavior() { | ||
val metricsFactory = MetricsFactory( | ||
sink = emittedMetrics::add, | ||
timeSource = { nowNanos }, | ||
totaltimeType = MetricsFactory.TotaltimeType.MeasurementMicroseconds | ||
) | ||
|
||
metricsFactory.recordWithBehavior("test", metricsBehavior = MetricsBehavior.NO_TOTALTIME) { metrics -> | ||
metrics.dimension("a_dimension", "a") | ||
metrics.measure("a_measurement", 0) | ||
metrics.distribution("a_distribution", 1) | ||
} | ||
assertEquals(1, emittedMetrics.size) | ||
val metric = emittedMetrics[0] | ||
metric.assertPresence( | ||
dimensions = setOf("a_dimension"), | ||
measurements = setOf("a_measurement"), | ||
distributions = setOf("a_distribution") | ||
) | ||
} | ||
|
||
@Test | ||
fun testNoTotaltimeType() { | ||
val metricsFactory = MetricsFactory( | ||
sink = emittedMetrics::add, | ||
timeSource = { nowNanos }, | ||
totaltimeType = MetricsFactory.TotaltimeType.None | ||
) | ||
|
||
metricsFactory.record("test") { metrics -> | ||
metrics.dimension("a_dimension", "a") | ||
metrics.measure("a_measurement", 0) | ||
metrics.distribution("a_distribution", 1) | ||
} | ||
assertEquals(1, emittedMetrics.size) | ||
val metric = emittedMetrics[0] | ||
metric.assertPresence( | ||
dimensions = setOf("a_dimension"), | ||
measurements = setOf("a_measurement"), | ||
distributions = setOf("a_distribution") | ||
) | ||
} | ||
} | ||
|
||
fun Metrics.assertPresence(dimensions: Set<String>, measurements: Set<String>, distributions: Set<String>) { | ||
val view = getView() | ||
assertEquals(dimensions, view.dimensions.keys) | ||
assertEquals(measurements, view.measurements.keys) | ||
assertEquals(distributions, view.distributions.keys) | ||
} |