Skip to content

Commit e78a235

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

File tree

6 files changed

+139
-3
lines changed

6 files changed

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

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,25 @@ 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(
31+
KubernetesClient k8sClient, ConfigurationService configurationService, Metrics metrics) {
3032
this.k8sClient = k8sClient;
3133
this.configurationService = configurationService;
3234
this.closeables = new ArrayList<>();
3335
this.lock = new Object();
3436
this.controllers = new ArrayList<>();
3537
this.started = false;
38+
this.metrics = metrics;
3639

3740
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
3841
}
3942

43+
public Operator(KubernetesClient k8sClient, ConfigurationService configurationService) {
44+
this(k8sClient, configurationService, Metrics.NOOP);
45+
}
46+
4047
public KubernetesClient getKubernetesClient() {
4148
return k8sClient;
4249
}

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: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,11 @@ private PostExecutionControl handleCreateOrUpdate(
122122
getName(resource),
123123
getVersion(resource),
124124
executionScope);
125-
UpdateControl<R> updateControl = controller.createOrUpdateResource(resource, context);
125+
UpdateControl<R> updateControl =
126+
configuration
127+
.getConfigurationService()
128+
.getMetrics()
129+
.timeControllerCreateOrUpdate(controller, configuration, resource, context);
126130
R updatedCustomResource = null;
127131
if (updateControl.isUpdateCustomResourceAndStatusSubResource()) {
128132
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)