Skip to content

Commit 16cea7d

Browse files
committed
Add TagReplacingFilter
Signed-off-by: etki <[email protected]>
1 parent 6367990 commit 16cea7d

File tree

3 files changed

+426
-16
lines changed

3 files changed

+426
-16
lines changed

micrometer-core/src/main/java/io/micrometer/core/instrument/config/MeterFilter.java

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import io.micrometer.common.lang.Nullable;
1919
import io.micrometer.core.instrument.*;
20+
import io.micrometer.core.instrument.config.filter.TagReplacingFilter;
2021
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
2122

2223
import java.time.Duration;
@@ -120,22 +121,7 @@ public Meter.Id map(Meter.Id id) {
120121
* @return A filter that replaces tag values.
121122
*/
122123
static MeterFilter replaceTagValues(String tagKey, Function<String, String> replacement, String... exceptions) {
123-
return new MeterFilter() {
124-
@Override
125-
public Meter.Id map(Meter.Id id) {
126-
List<Tag> tags = stream(id.getTagsAsIterable().spliterator(), false).map(t -> {
127-
if (!t.getKey().equals(tagKey))
128-
return t;
129-
for (String exception : exceptions) {
130-
if (t.getValue().equals(exception))
131-
return t;
132-
}
133-
return Tag.of(tagKey, replacement.apply(t.getValue()));
134-
}).collect(toList());
135-
136-
return id.replaceTags(tags);
137-
}
138-
};
124+
return TagReplacingFilter.classicValueReplacing(tagKey, replacement, exceptions);
139125
}
140126

141127
/**
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package io.micrometer.core.instrument.config.filter;
2+
3+
import io.micrometer.common.lang.NonNull;
4+
import io.micrometer.core.instrument.Meter;
5+
import io.micrometer.core.instrument.Tag;
6+
import io.micrometer.core.instrument.config.MeterFilter;
7+
8+
import java.util.*;
9+
import java.util.function.BiFunction;
10+
import java.util.function.BiPredicate;
11+
import java.util.function.Function;
12+
13+
public class TagReplacingFilter implements MeterFilter {
14+
private final BiPredicate<String, String> filter;
15+
private final BiFunction<String, String, Tag> replacer;
16+
private final int expectedTagCount;
17+
18+
TagReplacingFilter(BiPredicate<String, String> filter, BiFunction<String, String, Tag> replacer, int expectedTagCount) {
19+
this.replacer = replacer;
20+
this.filter = filter;
21+
this.expectedTagCount = expectedTagCount;
22+
}
23+
24+
@NonNull
25+
@Override
26+
public Meter.Id map(@NonNull Meter.Id id) {
27+
Iterator<Tag> iterator = id.getTagsAsIterable().iterator();
28+
29+
if (!iterator.hasNext()) {
30+
// fast path avoiding list allocation completely
31+
return id;
32+
}
33+
34+
List<Tag> replacement = new ArrayList<>(expectedTagCount);
35+
36+
boolean intercepted = false;
37+
while (iterator.hasNext()) {
38+
Tag tag = iterator.next();
39+
String key = tag.getKey();
40+
String value = tag.getValue();
41+
42+
if (filter.test(key, value)) {
43+
replacement.add(replacer.apply(key, value));
44+
intercepted = true;
45+
} else {
46+
replacement.add(tag);
47+
}
48+
}
49+
50+
return intercepted ? id.replaceTags(replacement) : id;
51+
}
52+
53+
public static MeterFilter of(BiPredicate<String, String> filter, BiFunction<String, String, Tag> replacer, int expectedSize) {
54+
return new TagReplacingFilter(filter, replacer, expectedSize);
55+
}
56+
57+
public static MeterFilter of(BiPredicate<String, String> filter, BiFunction<String, String, Tag> replacer) {
58+
return new TagReplacingFilter(filter, replacer, FilterSupport.DEFAULT_TAG_COUNT_EXPECTATION);
59+
}
60+
61+
public static MeterFilter classicValueReplacing(String key, Function<String, String> replacer, Collection<String> exceptions, int expectedSize) {
62+
return of(new ClassicFilter(key, new HashSet<>(exceptions)), new ValueReplacer(replacer), expectedSize);
63+
}
64+
65+
public static MeterFilter classicValueReplacing(String key, Function<String, String> replacer, Collection<String> exceptions) {
66+
return classicValueReplacing(key, replacer, exceptions, FilterSupport.DEFAULT_TAG_COUNT_EXPECTATION);
67+
}
68+
69+
public static MeterFilter classicValueReplacing(String key, Function<String, String> replacer, String... exceptions) {
70+
return classicValueReplacing(key, replacer, Arrays.asList(exceptions));
71+
}
72+
73+
private static class ClassicFilter implements BiPredicate<String, String> {
74+
private final String matcher;
75+
private final Set<String> exceptions;
76+
77+
public ClassicFilter(String matcher, Set<String> exceptions) {
78+
this.matcher = matcher;
79+
this.exceptions = exceptions;
80+
}
81+
82+
@Override
83+
public boolean test(String key, String value) {
84+
return key.equals(matcher) && !exceptions.contains(value);
85+
}
86+
}
87+
88+
private static class ValueReplacer implements BiFunction<String, String, Tag> {
89+
private final Function<String, String> delegate;
90+
91+
public ValueReplacer(Function<String, String> delegate) {
92+
this.delegate = delegate;
93+
}
94+
95+
@Override
96+
public Tag apply(String key, String value) {
97+
return Tag.of(key, delegate.apply(value));
98+
}
99+
}
100+
}

0 commit comments

Comments
 (0)