From 5d442ebc2e110464c5c5d6c8222ba7c215e0c966 Mon Sep 17 00:00:00 2001 From: Marius Oehler Date: Thu, 5 Mar 2020 16:35:08 +0100 Subject: [PATCH] Closes #587 - Using InspectITContext during metric recording and ignoring isTag (#594) --- .../UserInstrumentationWithMetricsTest.yml | 4 +- .../context/InspectitContextImpl.java | 17 ++--- .../hook/MethodHookGenerator.java | 35 ++++++---- .../hook/actions/MetricsRecorder.java | 28 +++----- .../hook/actions/model/MetricAccessor.java | 4 +- .../context/InspectitContextImplTest.java | 26 +++---- .../hook/MethodHookGeneratorTest.java | 68 +++++++++++++++++++ .../hook/actions/MetricsRecorderTest.java | 51 ++++++++------ 8 files changed, 149 insertions(+), 84 deletions(-) diff --git a/inspectit-ocelot-agent/src/system-test/resources/config/UserInstrumentationWithMetricsTest.yml b/inspectit-ocelot-agent/src/system-test/resources/config/UserInstrumentationWithMetricsTest.yml index d62f8d189f..c1c4616587 100644 --- a/inspectit-ocelot-agent/src/system-test/resources/config/UserInstrumentationWithMetricsTest.yml +++ b/inspectit-ocelot-agent/src/system-test/resources/config/UserInstrumentationWithMetricsTest.yml @@ -36,11 +36,11 @@ inspectit: scopes: UserInstrumentationWithMetricsTest-invocationCount : true entry: - method_name: {action: get_method_fqn} + current_method_name: {action: get_method_fqn} metrics: '[my/invocation]': value: 42 - data-tags: {method_name: method_name, user_tag: user_tag} + data-tags: {method_name: current_method_name, user_tag: user_tag} record_method_duration: scopes: diff --git a/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/context/InspectitContextImpl.java b/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/context/InspectitContextImpl.java index f0eb0d17f8..dc66933869 100644 --- a/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/context/InspectitContextImpl.java +++ b/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/context/InspectitContextImpl.java @@ -347,20 +347,10 @@ private boolean isInDifferentThreadThanParentOrIsParentClosed() { public Scope enterFullTagScope() { TagContextBuilder builder = Tags.getTagger().emptyBuilder(); dataTagsStream() - .forEach(e -> builder.put(TagKey.create(e.getKey()), TagValue.create(e.getValue().toString()))); + .forEach(e -> builder.putLocal(TagKey.create(e.getKey()), TagValue.create(e.getValue().toString()))); return builder.buildScoped(); } - /** - * Returns map of tags currently present in {@link #getData()}. - * - * @return the tag stream - * @see #enterFullTagScope() - */ - public Map getFullTagMap() { - return dataTagsStream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - private Stream> dataTagsStream() { return getDataAsStream() .filter(e -> propagation.isTag(e.getKey())) @@ -368,8 +358,11 @@ private Stream> dataTagsStream() { } /** + * Returns the most recent value for data, which either was inherited form the parent context, + * set via {@link #setData(String, Object)} or changed due to an up-propagation. + * * @param key the name of the data to query - * @return the most recent value for data, which either was inherited form the parent context, set via {@link #setData(String, Object)} or changed due to an up-propagation. + * @return the data element which is related to the given key or `null` if it doesn't exist */ @Override public Object getData(String key) { diff --git a/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/MethodHookGenerator.java b/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/MethodHookGenerator.java index bee65a6caf..e2ee4c0744 100644 --- a/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/MethodHookGenerator.java +++ b/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/MethodHookGenerator.java @@ -1,5 +1,6 @@ package rocks.inspectit.ocelot.core.instrumentation.hook; +import com.google.common.annotations.VisibleForTesting; import io.opencensus.stats.StatsRecorder; import io.opencensus.trace.Sampler; import io.opencensus.trace.samplers.Samplers; @@ -173,20 +174,12 @@ private List buildTracingExitActions(RuleTracingSettings tracing) { } private Optional buildMetricsRecorder(MethodHookConfiguration config) { - Collection metrics = config.getMetrics(); - if (!metrics.isEmpty()) { - List metricAccessors = metrics.stream() - .map(metricConfig -> { - String value = metricConfig.getValue(); - VariableAccessor valueAccessor; - try { - valueAccessor = variableAccessorFactory.getConstantAccessor(Double.parseDouble(value)); - } catch (NumberFormatException e) { - valueAccessor = variableAccessorFactory.getVariableAccessor(value); - } - return new MetricAccessor(metricConfig.getMetric(), valueAccessor, metricConfig.getConstantTags(), metricConfig.getDataTags()); - }) + Collection metricRecordingSettings = config.getMetrics(); + if (!metricRecordingSettings.isEmpty()) { + List metricAccessors = metricRecordingSettings.stream() + .map(this::buildMetricAccessor) .collect(Collectors.toList()); + MetricsRecorder recorder = new MetricsRecorder(metricAccessors, commonTagsManager, metricsManager, statsRecorder); return Optional.of(recorder); } else { @@ -194,6 +187,22 @@ private Optional buildMetricsRecorder(MethodHookConfiguration confi } } + @VisibleForTesting + MetricAccessor buildMetricAccessor(MetricRecordingSettings metricSettings) { + String value = metricSettings.getValue(); + VariableAccessor valueAccessor; + try { + valueAccessor = variableAccessorFactory.getConstantAccessor(Double.parseDouble(value)); + } catch (NumberFormatException e) { + valueAccessor = variableAccessorFactory.getVariableAccessor(value); + } + + Map tagAccessors = metricSettings.getDataTags().entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, entry -> variableAccessorFactory.getVariableAccessor(entry.getValue()))); + + return new MetricAccessor(metricSettings.getMetric(), valueAccessor, metricSettings.getConstantTags(), tagAccessors); + } + private List buildActionCalls(List calls, MethodReflectionInformation methodInfo) { List result = new ArrayList<>(); diff --git a/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/MetricsRecorder.java b/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/MetricsRecorder.java index 8b238c22ec..c4bd910def 100644 --- a/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/MetricsRecorder.java +++ b/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/MetricsRecorder.java @@ -5,12 +5,12 @@ import io.opencensus.tags.*; import lombok.Value; import lombok.extern.slf4j.Slf4j; +import rocks.inspectit.ocelot.core.instrumentation.context.InspectitContextImpl; import rocks.inspectit.ocelot.core.instrumentation.hook.actions.model.MetricAccessor; import rocks.inspectit.ocelot.core.metrics.MeasuresAndViewsManager; import rocks.inspectit.ocelot.core.tags.CommonTagsManager; import java.util.List; -import java.util.Map; import java.util.Optional; /** @@ -42,39 +42,32 @@ public class MetricsRecorder implements IHookAction { @Override public void execute(ExecutionContext context) { - // get all available data from the context and collect in a map - Map contextTags = null; - // then iterate all metrics and enter new scope for metric collection for (MetricAccessor metricAccessor : metrics) { Object value = metricAccessor.getVariableAccessor().get(context); if (value != null) { if (value instanceof Number) { - // resolve context tags on the first need for it - if (contextTags == null) { - contextTags = context.getInspectitContext().getFullTagMap(); - } - // only record metrics where a value is present // this allows to disable the recording of a metric depending on the results of action executions MeasureMap measureMap = statsRecorder.newMeasureMap(); metricsManager.tryRecordingMeasurement(metricAccessor.getName(), measureMap, (Number) value); - TagContext tagContext = getTagContext(contextTags, metricAccessor); + TagContext tagContext = getTagContext(context, metricAccessor); measureMap.record(tagContext); } } } } - private TagContext getTagContext(Map contextTags, MetricAccessor metricAccessor) { + private TagContext getTagContext(ExecutionContext context, MetricAccessor metricAccessor) { + InspectitContextImpl inspectitContext = context.getInspectitContext(); + // create builder TagContextBuilder builder = Tags.getTagger().emptyBuilder(); // first common tags to allow overwrite by constant or data tags commonTagsManager.getCommonTagKeys() - .forEach(commonTagKey -> Optional.ofNullable(contextTags.get(commonTagKey.getName())) - .ifPresent(value -> builder.putLocal(commonTagKey, TagValue.create(value.toString()))) - //TODO if not present in the context do we pull the value from the common tag map + .forEach(commonTagKey -> Optional.ofNullable(inspectitContext.getData(commonTagKey.getName())) + .ifPresent(value -> builder.putLocal(commonTagKey, TagValue.create(value.toString()))) ); // then constant tags to allow overwrite by data @@ -82,10 +75,9 @@ private TagContext getTagContext(Map contextTags, MetricAccessor .forEach((key, value) -> builder.putLocal(TagKey.create(key), TagValue.create(value))); // go over data tags and match the value to the key from the contextTags (if available) - metricAccessor.getDataTags() - .forEach((key, dataLink) -> Optional.ofNullable(contextTags.get(dataLink)) - .ifPresent(value -> builder.putLocal(TagKey.create(key), TagValue.create(value.toString()))) - ); + metricAccessor.getDataTagAccessors() + .forEach((key, accessor) -> Optional.ofNullable(accessor.get(context)) + .ifPresent(tagValue -> builder.putLocal(TagKey.create(key), TagValue.create(tagValue.toString())))); // build and return return builder.build(); diff --git a/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/model/MetricAccessor.java b/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/model/MetricAccessor.java index 9f9ec5ca7d..824dabac79 100644 --- a/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/model/MetricAccessor.java +++ b/inspectit-ocelot-core/src/main/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/model/MetricAccessor.java @@ -30,8 +30,8 @@ public class MetricAccessor { private final Map constantTags; /** - * Data tags keys and values. + * VariableAccessors for the data tags. */ - private final Map dataTags; + private final Map dataTagAccessors; } diff --git a/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/context/InspectitContextImplTest.java b/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/context/InspectitContextImplTest.java index 08e31097da..78dd32409b 100644 --- a/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/context/InspectitContextImplTest.java +++ b/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/context/InspectitContextImplTest.java @@ -850,12 +850,11 @@ void verifyLocalValuesPublishedCorrectly() { .containsEntry("global", "globalValue"); } - Map fullTagMap = ctx.getFullTagMap(); - assertThat(fullTagMap).hasSize(2) - .containsEntry("local", "localValue") - .containsEntry("global", "globalValue"); + assertThat(ctx.getData("local")).isEqualTo("localValue"); + assertThat(ctx.getData("global")).isEqualTo("globalValue"); ctx.close(); + assertThat(InspectitContextImpl.INSPECTIT_KEY.get()).isNull(); } @@ -893,13 +892,12 @@ void verifyUpPropagatedValuesOnlyAvailableInFullTagScope() { .containsEntry("nestedKey2", "nestedValue2"); } - Map fullTagMap = ctx.getFullTagMap(); - assertThat(fullTagMap).hasSize(3) - .containsEntry("rootKey1", "nestedValue1") - .containsEntry("rootKey2", "rootValue2") - .containsEntry("nestedKey2", "nestedValue2"); + assertThat(ctx.getData("rootKey1")).isEqualTo("nestedValue1"); + assertThat(ctx.getData("rootKey2")).isEqualTo("rootValue2"); + assertThat(ctx.getData("nestedKey2")).isEqualTo("nestedValue2"); ctx.close(); + assertThat(InspectitContextImpl.INSPECTIT_KEY.get()).isNull(); } @@ -931,12 +929,10 @@ void verifyOnlyPrimitiveDataUsedAsTag() { .containsEntry("d4", "2.0"); } - Map fullTagMap = ctx.getFullTagMap(); - assertThat(fullTagMap).hasSize(4) - .containsEntry("d1", "string") - .containsEntry("d2", 1) - .containsEntry("d3", 2L) - .containsEntry("d4", 2.0d); + assertThat(ctx.getData("d1")).isEqualTo("string"); + assertThat(ctx.getData("d2")).isEqualTo(1); + assertThat(ctx.getData("d3")).isEqualTo(2L); + assertThat(ctx.getData("d4")).isEqualTo(2.0D); ctx.close(); } diff --git a/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/hook/MethodHookGeneratorTest.java b/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/hook/MethodHookGeneratorTest.java index baf8efb731..6b2957bed1 100644 --- a/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/hook/MethodHookGeneratorTest.java +++ b/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/hook/MethodHookGeneratorTest.java @@ -9,11 +9,17 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import rocks.inspectit.ocelot.config.model.instrumentation.rules.MetricRecordingSettings; import rocks.inspectit.ocelot.core.instrumentation.config.model.MethodHookConfiguration; import rocks.inspectit.ocelot.core.instrumentation.context.ContextManager; +import rocks.inspectit.ocelot.core.instrumentation.hook.actions.model.MetricAccessor; import rocks.inspectit.ocelot.core.testutils.Dummy; +import java.util.Collections; + import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; +import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) public class MethodHookGeneratorTest { @@ -24,6 +30,9 @@ public class MethodHookGeneratorTest { @InjectMocks MethodHookGenerator generator; + @Mock + VariableAccessorFactory variableAccessorFactory; + @Nested class BuildHook { @@ -79,6 +88,65 @@ void verifyDeclaringClassCorrect() { assertThat(result.getMethodInformation().getDeclaringClass()).isSameAs(Dummy.class); } + } + + @Nested + class BuildMetricAccessor { + + @Test + public void valueOnly() { + VariableAccessor mockAccessor = mock(VariableAccessor.class); + when(variableAccessorFactory.getConstantAccessor(1D)).thenReturn(mockAccessor); + MetricRecordingSettings settings = MetricRecordingSettings.builder().metric("name").value("1.0").build(); + + MetricAccessor accessor = generator.buildMetricAccessor(settings); + + assertThat(accessor.getVariableAccessor()).isSameAs(mockAccessor); + assertThat(accessor.getConstantTags()).isEmpty(); + assertThat(accessor.getDataTagAccessors()).isEmpty(); + } + @Test + public void dataValueOnly() { + VariableAccessor mockAccessor = mock(VariableAccessor.class); + when(variableAccessorFactory.getVariableAccessor("data-key")).thenReturn(mockAccessor); + MetricRecordingSettings settings = MetricRecordingSettings.builder().metric("name").value("data-key").build(); + + MetricAccessor accessor = generator.buildMetricAccessor(settings); + + assertThat(accessor.getVariableAccessor()).isSameAs(mockAccessor); + assertThat(accessor.getConstantTags()).isEmpty(); + assertThat(accessor.getDataTagAccessors()).isEmpty(); + } + + @Test + public void valueAndConstantTag() { + VariableAccessor mockAccessor = mock(VariableAccessor.class); + when(variableAccessorFactory.getConstantAccessor(1D)).thenReturn(mockAccessor); + MetricRecordingSettings settings = MetricRecordingSettings.builder().metric("name").value("1.0") + .constantTags(Collections.singletonMap("tag-key", "tag-key")).build(); + + MetricAccessor accessor = generator.buildMetricAccessor(settings); + + assertThat(accessor.getVariableAccessor()).isSameAs(mockAccessor); + assertThat(accessor.getConstantTags()).containsOnly(entry("tag-key", "tag-key")); + assertThat(accessor.getDataTagAccessors()).isEmpty(); + } + + @Test + public void valueAndDataTag() { + VariableAccessor mockAccessorA = mock(VariableAccessor.class); + doReturn(mockAccessorA).when(variableAccessorFactory).getConstantAccessor(1D); + VariableAccessor mockAccessorB = mock(VariableAccessor.class); + doReturn(mockAccessorB).when(variableAccessorFactory).getVariableAccessor("tag-value"); + MetricRecordingSettings settings = MetricRecordingSettings.builder().metric("name").value("1.0") + .dataTags(Collections.singletonMap("tag-key", "tag-value")).build(); + + MetricAccessor accessor = generator.buildMetricAccessor(settings); + + assertThat(accessor.getVariableAccessor()).isSameAs(mockAccessorA); + assertThat(accessor.getConstantTags()).isEmpty(); + assertThat(accessor.getDataTagAccessors()).containsOnly(entry("tag-key", mockAccessorB)); + } } } diff --git a/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/MetricsRecorderTest.java b/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/MetricsRecorderTest.java index a32e2cd59e..ec7ed3654e 100644 --- a/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/MetricsRecorderTest.java +++ b/inspectit-ocelot-core/src/test/java/rocks/inspectit/ocelot/core/instrumentation/hook/actions/MetricsRecorderTest.java @@ -24,6 +24,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.Map; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; @@ -54,7 +55,6 @@ void setupMock() { when(commonTagsManager.getCommonTagKeys()).thenReturn(Collections.emptyList()); when(statsRecorder.newMeasureMap()).thenReturn(measureMap); when(executionContext.getInspectitContext()).thenReturn(inspectitContext); - when(inspectitContext.getFullTagMap()).thenReturn(Collections.emptyMap()); } @Nested @@ -109,8 +109,8 @@ void verifyInvalidDataTypeHandled() { @Test void commonTagsIncluded() { + when(inspectitContext.getData("common")).thenReturn("overwrite"); when(commonTagsManager.getCommonTagKeys()).thenReturn(Collections.singletonList(TagKey.create("common"))); - when(inspectitContext.getFullTagMap()).thenReturn(Collections.singletonMap("common", "overwrite")); VariableAccessor variableAccess = Mockito.mock(VariableAccessor.class); when(variableAccess.get(any())).thenReturn(100L); @@ -123,6 +123,7 @@ void commonTagsIncluded() { TagContext expected = Tags.getTagger().emptyBuilder().putLocal(TagKey.create("common"), TagValue.create("overwrite")).build(); verify(measureMap, times(1)).record(eq(expected)); verify(metricsManager, times(1)).tryRecordingMeasurement(eq("my_metric"), same(measureMap), eq((Number) 100L)); + verifyNoMoreInteractions(inspectitContext); } @Test @@ -143,10 +144,12 @@ void constantTags() { @Test void dataTagsNotAvailable() { + VariableAccessor mockAccessor = mock(VariableAccessor.class); + when(mockAccessor.get(any())).thenReturn(null); VariableAccessor variableAccess = Mockito.mock(VariableAccessor.class); when(variableAccess.get(any())).thenReturn(100L); - MetricAccessor metricAccessor = new MetricAccessor("my_metric", variableAccess, Collections.emptyMap(), Collections.singletonMap("data", "tag")); + MetricAccessor metricAccessor = new MetricAccessor("my_metric", variableAccess, Collections.emptyMap(), Collections.singletonMap("data", mockAccessor)); MetricsRecorder rec = new MetricsRecorder(Collections.singletonList(metricAccessor), commonTagsManager, metricsManager, statsRecorder); rec.execute(executionContext); @@ -159,12 +162,13 @@ void dataTagsNotAvailable() { @Test void dataTags() { - when(inspectitContext.getFullTagMap()).thenReturn(Collections.singletonMap("tag", "value")); + VariableAccessor mockAccessor = mock(VariableAccessor.class); + when(mockAccessor.get(any())).thenReturn("value"); VariableAccessor variableAccess = Mockito.mock(VariableAccessor.class); when(variableAccess.get(any())).thenReturn(100L); - MetricAccessor metricAccessor = new MetricAccessor("my_metric", variableAccess, Collections.emptyMap(), Collections.singletonMap("data", "tag")); + MetricAccessor metricAccessor = new MetricAccessor("my_metric", variableAccess, Collections.emptyMap(), Collections.singletonMap("data", mockAccessor)); MetricsRecorder rec = new MetricsRecorder(Collections.singletonList(metricAccessor), commonTagsManager, metricsManager, statsRecorder); rec.execute(executionContext); @@ -177,23 +181,26 @@ void dataTags() { @Test void multipleAccessorsMixedTags() { - HashMap contextTags = new HashMap<>(); - contextTags.put("t1", "data1"); - contextTags.put("t2", 12L); - contextTags.put("t3", Boolean.FALSE); - when(inspectitContext.getFullTagMap()).thenReturn(contextTags); + VariableAccessor mockAccessorA = mock(VariableAccessor.class); + when(mockAccessorA.get(any())).thenReturn("data1"); + VariableAccessor mockAccessorB = mock(VariableAccessor.class); + when(mockAccessorB.get(any())).thenReturn(12L); + VariableAccessor mockAccessorC = mock(VariableAccessor.class); + when(mockAccessorC.get(any())).thenReturn(Boolean.FALSE); + VariableAccessor mockAccessorD = mock(VariableAccessor.class); + when(mockAccessorD.get(any())).thenReturn(null); VariableAccessor dataA = Mockito.mock(VariableAccessor.class); VariableAccessor dataB = Mockito.mock(VariableAccessor.class); when(dataA.get(any())).thenReturn(100.0); when(dataB.get(any())).thenReturn(200.0); - HashMap dataTags1 = new HashMap<>(); - dataTags1.put("existing", "t1"); - dataTags1.put("not_existing", "t4"); + HashMap dataTags1 = new HashMap<>(); + dataTags1.put("existing", mockAccessorA); + dataTags1.put("not_existing", mockAccessorD); MetricAccessor metricAccessorA = new MetricAccessor("my_metric1", dataA, Collections.singletonMap("cA", "100"), dataTags1); - HashMap dataTags2 = new HashMap<>(); - dataTags2.put("existing1", "t2"); - dataTags2.put("existing2", "t3"); + HashMap dataTags2 = new HashMap<>(); + dataTags2.put("existing1", mockAccessorB); + dataTags2.put("existing2", mockAccessorC); MetricAccessor metricAccessorB = new MetricAccessor("my_metric2", dataB, Collections.singletonMap("cA", "200"), dataTags2); MetricsRecorder rec = new MetricsRecorder(Arrays.asList(metricAccessorA, metricAccessorB), commonTagsManager, metricsManager, statsRecorder); @@ -202,12 +209,12 @@ void multipleAccessorsMixedTags() { InOrder inOrder = inOrder(measureMap, metricsManager); // first recording - inOrder.verify(metricsManager, times(1)).tryRecordingMeasurement(eq("my_metric1"), same(measureMap), eq((Number) 100.0d)); + inOrder.verify(metricsManager).tryRecordingMeasurement(eq("my_metric1"), same(measureMap), eq((Number) 100.0d)); TagContext expected1 = Tags.getTagger().emptyBuilder() .putLocal(TagKey.create("cA"), TagValue.create("100")) .putLocal(TagKey.create("existing"), TagValue.create("data1")) .build(); - inOrder.verify(measureMap, times(1)).record(eq(expected1)); + inOrder.verify(measureMap).record(eq(expected1)); // second recording inOrder.verify(metricsManager, times(1)).tryRecordingMeasurement(eq("my_metric2"), same(measureMap), eq((Number) 200.0d)); TagContext expected2 = Tags.getTagger().emptyBuilder() @@ -215,19 +222,20 @@ void multipleAccessorsMixedTags() { .putLocal(TagKey.create("existing1"), TagValue.create("12")) .putLocal(TagKey.create("existing2"), TagValue.create("false")) .build(); - inOrder.verify(measureMap, times(1)).record(eq(expected2)); + inOrder.verify(measureMap).record(eq(expected2)); // and no more inOrder.verifyNoMoreInteractions(); } @Test void dataOverwritesConstant() { - when(inspectitContext.getFullTagMap()).thenReturn(Collections.singletonMap("tag", "value")); + VariableAccessor mockAccessor = mock(VariableAccessor.class); + when(mockAccessor.get(any())).thenReturn("value"); VariableAccessor variableAccess = Mockito.mock(VariableAccessor.class); when(variableAccess.get(any())).thenReturn(100L); - MetricAccessor metricAccessor = new MetricAccessor("my_metric", variableAccess, Collections.singletonMap("data", "constant"), Collections.singletonMap("data", "tag")); + MetricAccessor metricAccessor = new MetricAccessor("my_metric", variableAccess, Collections.singletonMap("data", "constant"), Collections.singletonMap("data", mockAccessor)); MetricsRecorder rec = new MetricsRecorder(Collections.singletonList(metricAccessor), commonTagsManager, metricsManager, statsRecorder); rec.execute(executionContext); @@ -237,6 +245,5 @@ void dataOverwritesConstant() { verify(metricsManager, times(1)).tryRecordingMeasurement(eq("my_metric"), same(measureMap), any(Number.class)); verify(metricsManager, times(1)).tryRecordingMeasurement(eq("my_metric"), same(measureMap), eq((Number) 100L)); } - } }