Skip to content

Commit

Permalink
Make LongTaskTimer creation conditional in DefaultMeterObservationHan…
Browse files Browse the repository at this point in the history
…dler (#4755)
  • Loading branch information
jonatan-ivanov authored Feb 28, 2024
1 parent 2d3f77b commit ac2dae0
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 VMware, Inc.
* Copyright 2024 VMware, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,6 +20,7 @@
import io.micrometer.observation.Observation;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
Expand All @@ -42,17 +43,39 @@ public class DefaultMeterObservationHandler implements MeterObservationHandler<O

private final MeterRegistry meterRegistry;

private final boolean shouldCreateLongTaskTimer;

/**
* Creates the handler with the default configuration.
* @param meterRegistry the MeterRegistry to use
*/
public DefaultMeterObservationHandler(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
this.shouldCreateLongTaskTimer = true;
}

/**
* Creates the handler with the defined Meters to use when the handler processes the
* Observations.
* @param meterRegistry the MeterRegistry to use
* @param metersToIgnore the Meters that should not be created when Observations are
* handled
*/
public DefaultMeterObservationHandler(MeterRegistry meterRegistry, IgnoredMeters... metersToIgnore) {
this.meterRegistry = meterRegistry;
this.shouldCreateLongTaskTimer = Arrays.stream(metersToIgnore)
.noneMatch(ignored -> ignored == IgnoredMeters.LONG_TASK_TIMER);
}

@Override
public void onStart(Observation.Context context) {
LongTaskTimer.Sample longTaskSample = LongTaskTimer.builder(context.getName() + ".active")
.tags(createTags(context))
.register(meterRegistry)
.start();
context.put(LongTaskTimer.Sample.class, longTaskSample);
if (shouldCreateLongTaskTimer) {
LongTaskTimer.Sample longTaskSample = LongTaskTimer.builder(context.getName() + ".active")
.tags(createTags(context))
.register(meterRegistry)
.start();
context.put(LongTaskTimer.Sample.class, longTaskSample);
}

Timer.Sample sample = Timer.start(meterRegistry);
context.put(Timer.Sample.class, sample);
Expand All @@ -65,8 +88,10 @@ public void onStop(Observation.Context context) {
Timer.Sample sample = context.getRequired(Timer.Sample.class);
sample.stop(Timer.builder(context.getName()).tags(tags).register(this.meterRegistry));

LongTaskTimer.Sample longTaskSample = context.getRequired(LongTaskTimer.Sample.class);
longTaskSample.stop();
if (shouldCreateLongTaskTimer) {
LongTaskTimer.Sample longTaskSample = context.getRequired(LongTaskTimer.Sample.class);
longTaskSample.stop();
}
}

@Override
Expand All @@ -90,4 +115,10 @@ private List<Tag> createTags(Observation.Context context) {
return tags;
}

public enum IgnoredMeters {

LONG_TASK_TIMER

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright 2024 VMware, Inc.
*
* 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.
*/
package io.micrometer.core.instrument.observation;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.micrometer.observation.Observation;
import io.micrometer.observation.Observation.Event;
import io.micrometer.observation.ObservationRegistry;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.net.SocketTimeoutException;

import static io.micrometer.core.instrument.observation.DefaultMeterObservationHandler.IgnoredMeters.LONG_TASK_TIMER;
import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@link DefaultMeterObservationHandler}. Additional tests can be found in
* {@code MeterRegistryCompatibilityKit}.
*
* @author Jonatan Ivanov
*/
class DefaultMeterObservationHandlerTest {

private ObservationRegistry observationRegistry;

private MeterRegistry meterRegistry;

@BeforeEach
void setUp() {
this.meterRegistry = new SimpleMeterRegistry();
this.observationRegistry = ObservationRegistry.create();
this.observationRegistry.observationConfig()
.observationHandler(new DefaultMeterObservationHandler(this.meterRegistry));
}

@Test
void shouldCreateAllMetersDuringAnObservationWithoutError() {
Observation observation = Observation.createNotStarted("test.observation", observationRegistry)
.lowCardinalityKeyValue("low", "1")
.highCardinalityKeyValue("high", "2")
.start()
.event(Event.of("test.event"));

assertThat(meterRegistry.get("test.observation.active").tags("low", "1").longTaskTimer().activeTasks())
.isEqualTo(1);

observation.stop();

assertThat(meterRegistry.get("test.observation").tags("low", "1", "error", "none").timer().count())
.isEqualTo(1);

assertThat(meterRegistry.get("test.observation.active").tags("low", "1").longTaskTimer().activeTasks())
.isEqualTo(0);

assertThat(meterRegistry.get("test.observation.test.event").tags("low", "1").counter().count()).isEqualTo(1);
}

@Test
void shouldCreateAllMetersDuringAnObservationWithError() {
Observation observation = Observation.createNotStarted("test.observation", observationRegistry)
.lowCardinalityKeyValue("low", "1")
.highCardinalityKeyValue("high", "2")
.start()
.event(Event.of("test.event"));

assertThat(meterRegistry.get("test.observation.active").tags("low", "1").longTaskTimer().activeTasks())
.isEqualTo(1);

observation.error(new SocketTimeoutException("simulated")).stop();

assertThat(meterRegistry.get("test.observation")
.tags("low", "1", "error", "SocketTimeoutException")
.timer()
.count()).isEqualTo(1);

assertThat(meterRegistry.get("test.observation.active").tags("low", "1").longTaskTimer().activeTasks())
.isEqualTo(0);

assertThat(meterRegistry.get("test.observation.test.event").tags("low", "1").counter().count()).isEqualTo(1);
}

@Test
void shouldNotCreateLongTaskTimerIfIgnored() {
this.observationRegistry = ObservationRegistry.create();
this.observationRegistry.observationConfig()
.observationHandler(new DefaultMeterObservationHandler(this.meterRegistry, LONG_TASK_TIMER));

Observation.createNotStarted("test.observation", observationRegistry)
.lowCardinalityKeyValue("low", "1")
.highCardinalityKeyValue("high", "2")
.start()
.event(Event.of("test.event"))
.stop();

assertThat(meterRegistry.get("test.observation").tags("low", "1", "error", "none").timer().count())
.isEqualTo(1);

assertThat(meterRegistry.get("test.observation.test.event").tags("low", "1").counter().count()).isEqualTo(1);

assertThat(meterRegistry.find("test.observation.active").longTaskTimers()).isEmpty();
}

}

0 comments on commit ac2dae0

Please sign in to comment.