Skip to content

Commit 40f6268

Browse files
committed
Optimize tag sorting with caching
Signed-off-by: HYEONSEOK1 <[email protected]>
1 parent 124baac commit 40f6268

File tree

1 file changed

+36
-13
lines changed

1 file changed

+36
-13
lines changed

Diff for: micrometer-core/src/main/java/io/micrometer/core/instrument/observation/DefaultMeterObservationHandler.java

+36-13
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@
1616
package io.micrometer.core.instrument.observation;
1717

1818
import io.micrometer.common.KeyValue;
19+
import io.micrometer.common.KeyValues;
1920
import io.micrometer.core.instrument.*;
21+
import io.micrometer.core.instrument.Timer;
2022
import io.micrometer.observation.Observation;
2123

24+
import java.util.AbstractMap;
2225
import java.util.ArrayList;
2326
import java.util.Arrays;
2427
import java.util.List;
28+
import java.util.Map;
29+
import java.util.concurrent.ConcurrentHashMap;
2530

2631
/**
2732
* Handler for {@link Timer.Sample} and {@link Counter}.
@@ -45,6 +50,8 @@ public class DefaultMeterObservationHandler implements MeterObservationHandler<O
4550

4651
private final boolean shouldCreateLongTaskTimer;
4752

53+
private final ConcurrentHashMap<Map.Entry<String, KeyValues>, Tags> tagCache = new ConcurrentHashMap<>();
54+
4855
/**
4956
* Creates the handler with the default configuration.
5057
* @param meterRegistry the MeterRegistry to use
@@ -71,8 +78,9 @@ public DefaultMeterObservationHandler(MeterRegistry meterRegistry, IgnoredMeters
7178
@Override
7279
public void onStart(Observation.Context context) {
7380
if (shouldCreateLongTaskTimer) {
74-
LongTaskTimer.Sample longTaskSample = LongTaskTimer.builder(context.getName() + ".active")
75-
.tags(createTags(context))
81+
String name = context.getName() + ".active";
82+
LongTaskTimer.Sample longTaskSample = LongTaskTimer.builder(name)
83+
.tags(getOrCreateTags(name, context.getLowCardinalityKeyValues()))
7684
.register(meterRegistry)
7785
.start();
7886
context.put(LongTaskTimer.Sample.class, longTaskSample);
@@ -84,10 +92,11 @@ public void onStart(Observation.Context context) {
8492

8593
@Override
8694
public void onStop(Observation.Context context) {
87-
List<Tag> tags = createTags(context);
88-
tags.add(Tag.of("error", getErrorValue(context)));
8995
Timer.Sample sample = context.getRequired(Timer.Sample.class);
90-
sample.stop(Timer.builder(context.getName()).tags(tags).register(this.meterRegistry));
96+
String name = context.getName();
97+
sample.stop(Timer.builder(name)
98+
.tags(getOrCreateTags(name, context.getLowCardinalityKeyValues(), getErrorValue(context)))
99+
.register(this.meterRegistry));
91100

92101
if (shouldCreateLongTaskTimer) {
93102
LongTaskTimer.Sample longTaskSample = context.getRequired(LongTaskTimer.Sample.class);
@@ -97,8 +106,9 @@ public void onStop(Observation.Context context) {
97106

98107
@Override
99108
public void onEvent(Observation.Event event, Observation.Context context) {
100-
Counter.builder(context.getName() + "." + event.getName())
101-
.tags(createTags(context))
109+
String name = context.getName() + "." + event.getName();
110+
Counter.builder(name)
111+
.tags(getOrCreateTags(name, context.getLowCardinalityKeyValues()))
102112
.register(meterRegistry)
103113
.increment();
104114
}
@@ -108,12 +118,25 @@ private String getErrorValue(Observation.Context context) {
108118
return error != null ? error.getClass().getSimpleName() : "none";
109119
}
110120

111-
private List<Tag> createTags(Observation.Context context) {
112-
List<Tag> tags = new ArrayList<>();
113-
for (KeyValue keyValue : context.getLowCardinalityKeyValues()) {
114-
tags.add(Tag.of(keyValue.getKey(), keyValue.getValue()));
115-
}
116-
return tags;
121+
private Tags getOrCreateTags(String name, KeyValues lowCardinalityKeyValues) {
122+
return getOrCreateTags(name, lowCardinalityKeyValues, null);
123+
}
124+
125+
private Tags getOrCreateTags(String name, KeyValues lowCardinalityKeyValues, String errorValue) {
126+
Map.Entry<String, KeyValues> key = new AbstractMap.SimpleEntry<>(name, lowCardinalityKeyValues);
127+
128+
return tagCache.computeIfAbsent(key, k -> {
129+
List<Tag> tagList = new ArrayList<>();
130+
for (KeyValue keyValue : lowCardinalityKeyValues) {
131+
tagList.add(Tag.of(keyValue.getKey(), keyValue.getValue()));
132+
}
133+
134+
if (errorValue != null) {
135+
tagList.add(Tag.of("error", errorValue));
136+
}
137+
138+
return Tags.of(tagList);
139+
});
117140
}
118141

119142
/**

0 commit comments

Comments
 (0)