|
26 | 26 |
|
27 | 27 | import co.elastic.apm.agent.configuration.MetricsConfiguration; |
28 | 28 | import co.elastic.apm.agent.report.serialize.DslJsonSerializer; |
| 29 | +import co.elastic.apm.agent.sdk.weakmap.WeakMapSupplier; |
| 30 | +import com.blogspot.mydailyjava.weaklockfree.WeakConcurrentSet; |
29 | 31 | import com.dslplatform.json.DslJson; |
30 | 32 | import com.dslplatform.json.JsonWriter; |
31 | 33 | import com.dslplatform.json.NumberConverter; |
|
38 | 40 | import io.micrometer.core.instrument.Meter; |
39 | 41 | import io.micrometer.core.instrument.Tag; |
40 | 42 | import io.micrometer.core.instrument.Timer; |
| 43 | +import org.slf4j.Logger; |
| 44 | +import org.slf4j.LoggerFactory; |
41 | 45 |
|
42 | 46 | import java.util.ArrayList; |
43 | 47 | import java.util.HashMap; |
|
52 | 56 | public class MicrometerMeterRegistrySerializer { |
53 | 57 |
|
54 | 58 | private static final byte NEW_LINE = (byte) '\n'; |
| 59 | + |
| 60 | + private static final Logger logger = LoggerFactory.getLogger(MicrometerMeterRegistrySerializer.class); |
| 61 | + |
55 | 62 | private final DslJson<Object> dslJson = new DslJson<>(new DslJson.Settings<>()); |
56 | 63 | private final StringBuilder replaceBuilder = new StringBuilder(); |
57 | 64 | private final MetricsConfiguration config; |
58 | | - |
| 65 | + private final WeakConcurrentSet<Meter> internallyDisabledMeters = WeakMapSupplier.createSet(); |
59 | 66 | private int previousSize = 0; |
60 | 67 |
|
61 | 68 | public MicrometerMeterRegistrySerializer(MetricsConfiguration config) { |
62 | 69 | this.config = config; |
63 | 70 | } |
64 | 71 |
|
| 72 | + Iterable<Meter> getFailedMeters() { |
| 73 | + return internallyDisabledMeters; |
| 74 | + } |
| 75 | + |
65 | 76 | public JsonWriter serialize(final Map<Meter.Id, Meter> metersById, final long epochMicros) { |
66 | 77 | int newSize = (int) (Math.max(previousSize, 512) * 1.25); |
67 | 78 | JsonWriter jw = dslJson.newWriter(newSize); |
@@ -101,31 +112,50 @@ void serializeMetricSet(List<Tag> tags, List<Meter> meters, long epochMicros, St |
101 | 112 | DslJsonSerializer.writeFieldName("samples", jw); |
102 | 113 | jw.writeByte(JsonWriter.OBJECT_START); |
103 | 114 | boolean hasValue = false; |
104 | | - for (int i = 0, size = meters.size(); i < size; i++) { |
105 | | - Meter meter = meters.get(i); |
106 | | - if (meter instanceof Timer) { |
107 | | - Timer timer = (Timer) meter; |
108 | | - hasValue = serializeTimer(jw, timer.getId(), timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasValue, replaceBuilder, dedotMetricName); |
109 | | - } else if (meter instanceof FunctionTimer) { |
110 | | - FunctionTimer timer = (FunctionTimer) meter; |
111 | | - hasValue = serializeTimer(jw, timer.getId(), (long) timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasValue, replaceBuilder, dedotMetricName); |
112 | | - } else if (meter instanceof LongTaskTimer) { |
113 | | - LongTaskTimer timer = (LongTaskTimer) meter; |
114 | | - hasValue = serializeTimer(jw, timer.getId(), timer.activeTasks(), timer.duration(TimeUnit.MICROSECONDS), hasValue, replaceBuilder, dedotMetricName); |
115 | | - } else if (meter instanceof DistributionSummary) { |
116 | | - DistributionSummary timer = (DistributionSummary) meter; |
117 | | - hasValue = serializeDistributionSummary(jw, timer.getId(), timer.count(), timer.totalAmount(), hasValue, replaceBuilder, dedotMetricName); |
118 | | - } else if (meter instanceof Gauge) { |
119 | | - Gauge gauge = (Gauge) meter; |
120 | | - hasValue = serializeValue(gauge.getId(), gauge.value(), hasValue, jw, replaceBuilder, dedotMetricName); |
121 | 115 |
|
122 | | - } else if (meter instanceof Counter) { |
123 | | - Counter counter = (Counter) meter; |
124 | | - hasValue = serializeValue(counter.getId(), counter.count(), hasValue, jw, replaceBuilder, dedotMetricName); |
125 | | - } else if (meter instanceof FunctionCounter) { |
126 | | - FunctionCounter counter = (FunctionCounter) meter; |
127 | | - hasValue = serializeValue(counter.getId(), counter.count(), hasValue, jw, replaceBuilder, dedotMetricName); |
| 116 | + ClassLoader originalContextCL = Thread.currentThread().getContextClassLoader(); |
| 117 | + try { |
| 118 | + for (int i = 0, size = meters.size(); i < size; i++) { |
| 119 | + Meter meter = meters.get(i); |
| 120 | + if (internallyDisabledMeters.contains(meter)) { |
| 121 | + continue; |
| 122 | + } |
| 123 | + try { |
| 124 | + // Setting the Meter CL as the context class loader during the Meter query operations |
| 125 | + Thread.currentThread().setContextClassLoader(meter.getClass().getClassLoader()); |
| 126 | + if (meter instanceof Timer) { |
| 127 | + Timer timer = (Timer) meter; |
| 128 | + hasValue = serializeTimer(jw, timer.getId(), timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasValue, replaceBuilder, dedotMetricName); |
| 129 | + } else if (meter instanceof FunctionTimer) { |
| 130 | + FunctionTimer timer = (FunctionTimer) meter; |
| 131 | + hasValue = serializeTimer(jw, timer.getId(), (long) timer.count(), timer.totalTime(TimeUnit.MICROSECONDS), hasValue, replaceBuilder, dedotMetricName); |
| 132 | + } else if (meter instanceof LongTaskTimer) { |
| 133 | + LongTaskTimer timer = (LongTaskTimer) meter; |
| 134 | + hasValue = serializeTimer(jw, timer.getId(), timer.activeTasks(), timer.duration(TimeUnit.MICROSECONDS), hasValue, replaceBuilder, dedotMetricName); |
| 135 | + } else if (meter instanceof DistributionSummary) { |
| 136 | + DistributionSummary timer = (DistributionSummary) meter; |
| 137 | + hasValue = serializeDistributionSummary(jw, timer.getId(), timer.count(), timer.totalAmount(), hasValue, replaceBuilder, dedotMetricName); |
| 138 | + } else if (meter instanceof Gauge) { |
| 139 | + Gauge gauge = (Gauge) meter; |
| 140 | + hasValue = serializeValue(gauge.getId(), gauge.value(), hasValue, jw, replaceBuilder, dedotMetricName); |
| 141 | + } else if (meter instanceof Counter) { |
| 142 | + Counter counter = (Counter) meter; |
| 143 | + hasValue = serializeValue(counter.getId(), counter.count(), hasValue, jw, replaceBuilder, dedotMetricName); |
| 144 | + } else if (meter instanceof FunctionCounter) { |
| 145 | + FunctionCounter counter = (FunctionCounter) meter; |
| 146 | + hasValue = serializeValue(counter.getId(), counter.count(), hasValue, jw, replaceBuilder, dedotMetricName); |
| 147 | + } |
| 148 | + } catch (Throwable throwable) { |
| 149 | + String meterName = meter.getId().getName(); |
| 150 | + logger.warn("Failed to serialize Micrometer meter \"{}\" with tags {}. This meter will be " + |
| 151 | + "excluded from serialization going forward.", meterName, tags); |
| 152 | + logger.debug("Detailed info about failure to register Micrometer meter \"" + meterName + |
| 153 | + "\": ", throwable); |
| 154 | + internallyDisabledMeters.add(meter); |
| 155 | + } |
128 | 156 | } |
| 157 | + } finally { |
| 158 | + Thread.currentThread().setContextClassLoader(originalContextCL); |
129 | 159 | } |
130 | 160 | jw.writeByte(JsonWriter.OBJECT_END); |
131 | 161 | } |
|
0 commit comments