Skip to content

Commit 6695906

Browse files
committed
Fix #26344: NPE in Micrometer because the valueFunction can return null
1 parent b6be914 commit 6695906

1 file changed

Lines changed: 26 additions & 4 deletions

File tree

src/main/java/eu/openanalytics/containerproxy/stat/impl/Micrometer.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.util.Timer;
4646
import java.util.TimerTask;
4747
import java.util.concurrent.ConcurrentHashMap;
48+
import java.util.function.ToDoubleFunction;
4849

4950
public class Micrometer implements IStatCollector {
5051

@@ -82,15 +83,15 @@ public void init() {
8283
userLogouts = registry.counter("userLogouts");
8384
appStartFailedCounter = registry.counter("startFailed");
8485
authFailedCounter = registry.counter("authFailed");
85-
registry.gauge("absolute_users_logged_in", Tags.empty(), sessionService, ISessionService::getLoggedInUsersCount);
86-
registry.gauge("absolute_users_active", Tags.empty(), sessionService, ISessionService::getActiveUsersCount);
86+
registry.gauge("absolute_users_logged_in", Tags.empty(), sessionService, wrapHandleNull(ISessionService::getLoggedInUsersCount));
87+
registry.gauge("absolute_users_active", Tags.empty(), sessionService, wrapHandleNull(ISessionService::getActiveUsersCount));
8788

8889
for (ProxySpec spec : proxyService.getProxySpecs(null, true)) {
8990
registry.counter("appStarts", "spec.id", spec.getId());
9091
registry.counter("appStops", "spec.id", spec.getId());
9192
ProxyCounter proxyCounter = new ProxyCounter(spec.getId());
9293
proxyCounters.add(proxyCounter);
93-
registry.gauge("absolute_apps_running", Tags.of("spec.id", spec.getId()), proxyCounter, ProxyCounter::getProxyCount);
94+
registry.gauge("absolute_apps_running", Tags.of("spec.id", spec.getId()), proxyCounter, wrapHandleNull(ProxyCounter::getProxyCount));
9495
registry.timer("startupTime", "spec.id", spec.getId());
9596
registry.timer("usageTime", "spec.id", spec.getId());
9697
}
@@ -165,10 +166,31 @@ public ProxyCounter(String specId) {
165166
this.specId = specId;
166167
}
167168

168-
public int getProxyCount() {
169+
public Integer getProxyCount() {
169170
return proxyCountCache.getOrDefault(specId, null);
170171
}
171172

172173
}
173174

175+
/**
176+
* Wraps a function that returns an Integer into a function that returns a double.
177+
* When the provided Integer is null, the resulting function returns Double.NaN.
178+
*
179+
* We need this function because Micrometer cannot handle null values for Gauges.
180+
*/
181+
private static <T> ToDoubleFunction<T> wrapHandleNull(ToIntegerFunction<T> producer) {
182+
return (state) -> {
183+
Integer res = producer.applyAsDouble(state);
184+
if (res == null) {
185+
return Double.NaN;
186+
}
187+
return res;
188+
};
189+
}
190+
191+
@FunctionalInterface
192+
private interface ToIntegerFunction<T> {
193+
Integer applyAsDouble(T var1);
194+
}
195+
174196
}

0 commit comments

Comments
 (0)