Skip to content

Commit 9d84668

Browse files
committed
feat: initial PoC for micrometer integration
1 parent fe7d823 commit 9d84668

File tree

6 files changed

+120
-3
lines changed

6 files changed

+120
-3
lines changed

operator-framework-core/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<java.version>11</java.version>
2020
<maven.compiler.source>11</maven.compiler.source>
2121
<maven.compiler.target>11</maven.compiler.target>
22+
<micrometer-core.version>1.7.3</micrometer-core.version>
2223
</properties>
2324

2425
<build>
@@ -94,5 +95,10 @@
9495
<version>3.20.2</version>
9596
<scope>test</scope>
9697
</dependency>
98+
<dependency>
99+
<groupId>io.micrometer</groupId>
100+
<artifactId>micrometer-core</artifactId>
101+
<version>${micrometer-core.version}</version>
102+
</dependency>
97103
</dependencies>
98104
</project>
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package io.javaoperatorsdk.operator;
2+
3+
import io.fabric8.kubernetes.client.CustomResource;
4+
import io.javaoperatorsdk.operator.api.Context;
5+
import io.javaoperatorsdk.operator.api.ResourceController;
6+
import io.javaoperatorsdk.operator.api.UpdateControl;
7+
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
8+
import io.micrometer.core.instrument.*;
9+
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
10+
import io.micrometer.core.instrument.distribution.pause.PauseDetector;
11+
import io.micrometer.core.instrument.noop.*;
12+
13+
import java.util.concurrent.TimeUnit;
14+
import java.util.function.ToDoubleFunction;
15+
import java.util.function.ToLongFunction;
16+
17+
public class Metrics {
18+
public static final Metrics NOOP = new Metrics(new NoopMeterRegistry(Clock.SYSTEM));
19+
private final MeterRegistry registry;
20+
21+
public Metrics(MeterRegistry registry) {
22+
this.registry = registry;
23+
}
24+
25+
public <R extends CustomResource> UpdateControl<R> timeControllerCreateOrUpdate(ResourceController<R> controller, ControllerConfiguration<R> configuration, R resource, Context<R> context) {
26+
// todo: https://github.com/java-operator-sdk/java-operator-sdk/issues/496 would simplify things
27+
final var name = configuration.getName();
28+
final var timer = registry.timer("operator.sdk.controllers.execution.createOrUpdate", name);
29+
try {
30+
final var result = timer.record(() -> controller.createOrUpdateResource(resource, context));
31+
String successType = "cr";
32+
if(result.isUpdateStatusSubResource()) {
33+
successType = "status";
34+
}
35+
if(result.isUpdateCustomResourceAndStatusSubResource()) {
36+
successType = "both";
37+
}
38+
registry.counter("operator.sdk.controllers.execution.success", name, successType);
39+
return result;
40+
} catch (Exception e) {
41+
registry.counter("operator.sdk.controllers.execution.failure", name, e.getClass().getSimpleName());
42+
throw e;
43+
}
44+
}
45+
46+
private static class NoopMeterRegistry extends MeterRegistry {
47+
protected NoopMeterRegistry(Clock clock) {
48+
super(clock);
49+
}
50+
51+
@Override
52+
protected <T> Gauge newGauge(Meter.Id id, T t, ToDoubleFunction<T> toDoubleFunction) {
53+
return new NoopGauge(id);
54+
}
55+
56+
@Override
57+
protected Counter newCounter(Meter.Id id) {
58+
return new NoopCounter(id);
59+
}
60+
61+
@Override
62+
protected Timer newTimer(Meter.Id id, DistributionStatisticConfig distributionStatisticConfig, PauseDetector pauseDetector) {
63+
return new NoopTimer(id);
64+
}
65+
66+
@Override
67+
protected DistributionSummary newDistributionSummary(Meter.Id id, DistributionStatisticConfig distributionStatisticConfig, double v) {
68+
return new NoopDistributionSummary(id);
69+
}
70+
71+
@Override
72+
protected Meter newMeter(Meter.Id id, Meter.Type type, Iterable<Measurement> iterable) {
73+
return new NoopMeter(id);
74+
}
75+
76+
@Override
77+
protected <T> FunctionTimer newFunctionTimer(Meter.Id id, T t, ToLongFunction<T> toLongFunction, ToDoubleFunction<T> toDoubleFunction, TimeUnit timeUnit) {
78+
return new NoopFunctionTimer(id);
79+
}
80+
81+
@Override
82+
protected <T> FunctionCounter newFunctionCounter(Meter.Id id, T t, ToDoubleFunction<T> toDoubleFunction) {
83+
return new NoopFunctionCounter(id);
84+
}
85+
86+
@Override
87+
protected TimeUnit getBaseTimeUnit() {
88+
return TimeUnit.SECONDS;
89+
}
90+
91+
@Override
92+
protected DistributionStatisticConfig defaultHistogramConfig() {
93+
return DistributionStatisticConfig.NONE;
94+
}
95+
}
96+
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,24 @@ public class Operator implements AutoCloseable {
2525
private final Object lock;
2626
private final List<ControllerRef> controllers;
2727
private volatile boolean started;
28+
private final Metrics metrics;
2829

29-
public Operator(KubernetesClient k8sClient, ConfigurationService configurationService) {
30+
public Operator(KubernetesClient k8sClient, ConfigurationService configurationService, Metrics metrics) {
3031
this.k8sClient = k8sClient;
3132
this.configurationService = configurationService;
3233
this.closeables = new ArrayList<>();
3334
this.lock = new Object();
3435
this.controllers = new ArrayList<>();
3536
this.started = false;
37+
this.metrics = metrics;
3638

3739
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
3840
}
3941

42+
public Operator(KubernetesClient k8sClient, ConfigurationService configurationService) {
43+
this(k8sClient, configurationService, Metrics.NOOP);
44+
}
45+
4046
public KubernetesClient getKubernetesClient() {
4147
return k8sClient;
4248
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.fasterxml.jackson.databind.ObjectMapper;
44
import io.fabric8.kubernetes.client.Config;
55
import io.fabric8.kubernetes.client.CustomResource;
6+
import io.javaoperatorsdk.operator.Metrics;
67
import io.javaoperatorsdk.operator.api.ResourceController;
78
import java.util.Set;
89

@@ -91,4 +92,8 @@ default ObjectMapper getObjectMapper() {
9192
default int getTerminationTimeoutSeconds() {
9293
return DEFAULT_TERMINATION_TIMEOUT_SECONDS;
9394
}
95+
96+
default Metrics getMetrics() {
97+
return Metrics.NOOP;
98+
}
9499
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/EventDispatcher.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ private PostExecutionControl handleCreateOrUpdate(
122122
getName(resource),
123123
getVersion(resource),
124124
executionScope);
125-
UpdateControl<R> updateControl = controller.createOrUpdateResource(resource, context);
125+
UpdateControl<R> updateControl = configuration.getConfigurationService().getMetrics()
126+
.timeControllerCreateOrUpdate(controller, configuration, resource, context);
126127
R updatedCustomResource = null;
127128
if (updateControl.isUpdateCustomResourceAndStatusSubResource()) {
128129
updatedCustomResource = updateCustomResource(updateControl.getCustomResource());

operator-framework/src/test/java/io/javaoperatorsdk/operator/IntegrationTestSupport.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
import java.io.IOException;
2323
import java.io.InputStream;
2424
import java.util.concurrent.TimeUnit;
25+
26+
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
27+
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
2528
import org.slf4j.Logger;
2629
import org.slf4j.LoggerFactory;
2730

@@ -61,7 +64,7 @@ public void initialize(KubernetesClient k8sClient, ResourceController controller
6164
namespaces.create(
6265
new NamespaceBuilder().withNewMetadata().withName(TEST_NAMESPACE).endMetadata().build());
6366
}
64-
operator = new Operator(k8sClient, configurationService);
67+
operator = new Operator(k8sClient, configurationService, Metrics.NOOP);
6568
final var overriddenConfig =
6669
ControllerConfigurationOverrider.override(config).settingNamespace(TEST_NAMESPACE);
6770
if (retry != null) {

0 commit comments

Comments
 (0)