Skip to content

Commit

Permalink
Updates to global instances through Helidon context for MP and to fix…
Browse files Browse the repository at this point in the history
… all tests
  • Loading branch information
tomas-langer committed Sep 2, 2024
1 parent 4b69c25 commit 213eb55
Show file tree
Hide file tree
Showing 25 changed files with 438 additions and 412 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ public <T> Optional<T> get(Object classifier, Class<T> type) {
}
}

@Override
public String toString() {
return contextId;
}

long nextChildId() {
return contextCounter.getAndUpdate(operand -> (operand == Long.MAX_VALUE) ? 1 : (operand + 1));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.function.Supplier;

import io.helidon.common.config.Config;
import io.helidon.common.context.ContextValue;
import io.helidon.common.context.Contexts;
import io.helidon.config.metadata.Configured;
import io.helidon.webserver.http.HttpRouting;
Expand Down Expand Up @@ -46,9 +47,10 @@
*/
@Deprecated(forRemoval = true, since = "4.1")
public class MicrometerFeature extends HelidonFeatureSupport {

static final String DEFAULT_CONTEXT = "/micrometer";
private static final String SERVICE_NAME = "Micrometer";

private static final ContextValue<MeterRegistry> METER_REGISTRY = ContextValue.create(MeterRegistry.class);
private static final String SERVICE_NAME = "Micrometer";
private static final System.Logger LOGGER = System.getLogger(MicrometerFeature.class.getName());

private final MeterRegistryFactory meterRegistryFactory;
Expand Down Expand Up @@ -105,7 +107,7 @@ protected void postSetup(HttpRouting.Builder defaultRouting, HttpRouting.Builder

@Override
public void beforeStart() {
Contexts.globalContext().register(registry());
METER_REGISTRY.set(registry());
LOGGER.log(System.Logger.Level.WARNING,
"Micrometer integration is deprecated and will be removed in a future major release.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import io.helidon.metrics.api.Meter;
import io.helidon.metrics.api.MeterRegistry;
import io.helidon.metrics.api.Metrics;
import io.helidon.metrics.api.MetricsFactory;
import io.helidon.microprofile.config.ConfigCdiExtension;
import io.helidon.microprofile.server.JaxRsCdiExtension;
import io.helidon.microprofile.server.ServerCdiExtension;
Expand All @@ -53,6 +54,7 @@
import jakarta.enterprise.inject.spi.configurator.BeanConfigurator;
import org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -85,7 +87,6 @@ class OciMetricsCdiExtensionTest {
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static PostMetricDataDetails postMetricDataDetails;
private static boolean activateOciMetricsSupportIsInvoked;
private static MeterRegistry registry = Metrics.globalRegistry();

@AfterEach
void resetState() {
Expand All @@ -112,6 +113,7 @@ void testDisableOciMetrics() throws InterruptedException {
}

private void validateOciMetricsSupport(boolean enabled) throws InterruptedException {
MeterRegistry registry = Metrics.globalRegistry();
Counter c1 = registry.getOrCreate(Counter.builder(Meter.Scope.BASE + METRIC_NAME_SUFFIX)
.scope(Meter.Scope.BASE));
c1.increment();
Expand Down Expand Up @@ -150,6 +152,7 @@ private void validateOciMetricsSupport(boolean enabled) throws InterruptedExcept
registry.remove(c1);
registry.remove(c2);
registry.remove(c3);
clear();
}

interface MetricDataDetailsOCIParams {
Expand Down Expand Up @@ -233,4 +236,25 @@ protected void activateOciMetricsSupport(Config rootConfig, Config ociMetricsCon
super.activateOciMetricsSupport(rootConfig, ociMetricsConfig, builder);
}
}

static void clear() {
MetricsFactory.closeAll();

// And clear out Micrometer's global registry explicitly to be extra sure.
io.micrometer.core.instrument.MeterRegistry mmGlobal = io.micrometer.core.instrument.Metrics.globalRegistry;
mmGlobal.clear();

int delayMS = 250;
int maxSecondsToWait = 5;
int iterationsRemaining = (maxSecondsToWait * 1000) / delayMS;

while (iterationsRemaining > 0 && !mmGlobal.getMeters().isEmpty()) {
iterationsRemaining--;
try {
TimeUnit.MILLISECONDS.sleep(delayMS);
} catch (InterruptedException e) {
throw new RuntimeException("Error awaiting clear-out of meter registries to finish", e);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import io.helidon.common.context.Context;
import io.helidon.common.context.Contexts;
import io.helidon.config.Config;
import io.helidon.config.metadata.Configured;
import io.helidon.config.metadata.ConfiguredOption;
Expand Down Expand Up @@ -175,8 +177,11 @@ static String baseMetricUnits(String metricUnits) {
}

private void startExecutor() {
Context ctx = Contexts.context().orElseGet(Contexts::globalContext);
scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleAtFixedRate(this::pushMetrics, initialDelay, delay, schedulingTimeUnit);
scheduledExecutorService.scheduleAtFixedRate(() -> {
Contexts.runInContext(ctx, this::pushMetrics);
}, initialDelay, delay, schedulingTimeUnit);
}

private void pushMetrics() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ class MetricsFactoryManager {
private static final ContextValue<MetersProviders> METER_PROVIDERS =
ContextValue.create(MetersProviders.class, () ->
new MetersProviders(HelidonServiceLoader.create(ServiceLoader.load(MetersProvider.class)).asList()));
private static final ContextValue<Config> METRICS_CONFIG = ContextValue.create(Config.class);
// we cannot use Config directly, as that would conflict with GlobalConfig itself
private static final ContextValue<MetricsConfigHolder> METRICS_CONFIG = ContextValue.create(MetricsConfigHolder.class);
private static final ContextValue<MetricsFactory> METRICS_FACTORY = ContextValue.create(MetricsFactory.class);

private MetricsFactoryManager() {
Expand All @@ -94,7 +95,7 @@ private MetricsFactoryManager() {
* @return new metrics factory
*/
static MetricsFactory getMetricsFactory(Config metricsConfigNode) {
METRICS_CONFIG.set(metricsConfigNode);
METRICS_CONFIG.set(new MetricsConfigHolder(metricsConfigNode));

MetricsFactory metricsFactory = buildMetricsFactory(metricsConfigNode);
METRICS_FACTORY.set(metricsFactory);
Expand All @@ -111,7 +112,9 @@ static MetricsFactory getMetricsFactory(Config metricsConfigNode) {
*/
static MetricsFactory getMetricsFactory() {
return METRICS_FACTORY.get(() -> {
Config metricsConfig = METRICS_CONFIG.get(MetricsFactoryManager::externalMetricsConfig);
Config metricsConfig = METRICS_CONFIG.get(() -> new MetricsConfigHolder(MetricsFactoryManager
.externalMetricsConfig()))
.config();
return buildMetricsFactory(metricsConfig);
});
}
Expand Down Expand Up @@ -161,4 +164,7 @@ private static MetricsConfig applyOverrides(MetricsConfig metricsConfig) {

private record MetersProviders(Collection<MetersProvider> providers) {
}

private record MetricsConfigHolder(Config config) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,88 +127,6 @@ static Builder builder(
return new Builder(delegate, metricsFactory);
}

/**
* Creates a new meter registry which wraps an newly-created Micrometer
* {@link io.micrometer.core.instrument.composite.CompositeMeterRegistry} with a Prometheus meter registry
* automatically added, using the specified clock.
*
* @param metricsFactory metrics factory the new meter registry should use in creating and registering meters
* @param clock default clock to associate with the new meter registry
* @param metersProviders providers of built-in meters to be registered upon creation of the meter registry
* @return new wrapper around a new Micrometer composite meter registry
*/
static MMeterRegistry create(MicrometerMetricsFactory metricsFactory,
Clock clock,
Collection<MetersProvider> metersProviders) {
CompositeMeterRegistry delegate = new CompositeMeterRegistry(ClockWrapper.create(clock));
// The specified clock is already a Helidon one so pass it directly; no need to wrap it.
return create(delegate,
metricsFactory,
metricsFactory.metricsConfig(),
clock,
metersProviders);
}

static MMeterRegistry create(io.micrometer.core.instrument.MeterRegistry delegate,
MicrometerMetricsFactory metricsFactory,
MetricsConfig metricsConfig,
Collection<MetersProvider> metersProviders) {

return create(delegate, metricsFactory, metricsConfig, MClock.create(delegate.config().clock()), metersProviders);
}

static MMeterRegistry create(io.micrometer.core.instrument.MeterRegistry delegate,
MicrometerMetricsFactory metricsFactory,
MetricsConfig metricsConfig,
Collection<MetersProvider> metersProviders,
Consumer<io.helidon.metrics.api.Meter> onAddListener,
Consumer<io.helidon.metrics.api.Meter> onRemoveListener) {
MMeterRegistry result = create(delegate, metricsFactory, metricsConfig, MClock.create(delegate.config().clock()));
result.onMeterAdded(onAddListener)
.onMeterRemoved(onRemoveListener);
return applyMetersProvidersToRegistry(metricsFactory, result, metersProviders);
}

static MMeterRegistry create(io.micrometer.core.instrument.MeterRegistry delegate,
MicrometerMetricsFactory metricsFactory,
MetricsConfig metricsConfig,
Clock clock,
Collection<MetersProvider> metersProviders) {

return applyMetersProvidersToRegistry(metricsFactory,
create(delegate,
metricsFactory,
metricsConfig,
clock),
metersProviders);
}

static MMeterRegistry create(io.micrometer.core.instrument.MeterRegistry delegate,
MicrometerMetricsFactory metricsFactory,
MetricsConfig metricsConfig,
Clock clock) {

io.micrometer.core.instrument.MeterRegistry preppedDelegate =
ensurePrometheusRegistryIsPresent(delegate,
metricsFactory.metricsConfig());

return new MMeterRegistry(preppedDelegate,
metricsFactory,
metricsConfig,
clock);
}

static MMeterRegistry create(io.micrometer.core.instrument.MeterRegistry delegate,
MicrometerMetricsFactory metricsFactory,
Collection<MetersProvider> metersProviders) {

return create(delegate,
metricsFactory,
metricsFactory.metricsConfig(),
MClock.create(delegate.config().clock()),
metersProviders);
}

static MMeterRegistry applyMetersProvidersToRegistry(MetricsFactory factory,
MMeterRegistry registry,
Collection<MetersProvider> metersProviders) {
Expand All @@ -230,6 +148,7 @@ public void close() {
buildersByPromMeterId.clear();
scopeMembership.clear();
metersById.clear();
delegate.clear();
} finally {
lock.writeLock().unlock();
}
Expand Down Expand Up @@ -558,7 +477,7 @@ void onMeterRemoved(Meter removedMeter) {

private io.helidon.metrics.api.Meter noopMeterIfDisabled(io.helidon.metrics.api.Meter.Builder<?, ?> builder) {
if (!isMeterEnabled(builder.name(), builder.tags(), builder.scope())) {

System.out.println("Meter is disabled: " + builder.name());
io.helidon.metrics.api.Meter result = metricsFactory.noOpMeter(builder);
onAddListeners.forEach(listener -> listener.accept(result));
return result;
Expand Down Expand Up @@ -594,6 +513,7 @@ private static io.micrometer.core.instrument.MeterRegistry ensurePrometheusRegis
MetricsConfig metricsConfig) {

if (meterRegistry instanceof CompositeMeterRegistry compositeMeterRegistry) {

if (compositeMeterRegistry.getRegistries()
.stream()
.noneMatch(r -> r instanceof PrometheusMeterRegistry)) {
Expand Down Expand Up @@ -894,30 +814,4 @@ public R build() {
return (R) applyMetersProvidersToRegistry(metricsFactory, result, metersProviders);
}
}

/**
* Micrometer-friendly wrapper around a Helidon clock.
*/
private static class ClockWrapper implements io.micrometer.core.instrument.Clock {

private final Clock neutralClock;

private ClockWrapper(Clock neutralClock) {
this.neutralClock = neutralClock;
}

static ClockWrapper create(Clock clock) {
return new ClockWrapper(clock);
}

@Override
public long wallTime() {
return neutralClock.wallTime();
}

@Override
public long monotonicTime() {
return neutralClock.monotonicTime();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ public void close() {
registries.forEach(MMeterRegistry::close);
meterRegistries.clear();
globalMeterRegistry = null;
for (var registry : Metrics.globalRegistry.getRegistries()) {
Metrics.globalRegistry.remove(registry);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ final class HelidonContainerImpl extends Weld implements HelidonContainer {
private static final AtomicBoolean IN_RUNTIME = new AtomicBoolean();
private static final String EXIT_ON_STARTED_KEY = "exit.on.started";
private static final boolean EXIT_ON_STARTED = "!".equals(System.getProperty(EXIT_ON_STARTED_KEY));
private static final Context ROOT_CONTEXT;
// whether the current shutdown was invoked by the shutdown hook
private static final AtomicBoolean FROM_SHUTDOWN_HOOK = new AtomicBoolean();
// Default Weld container id. TCKs assumes this value.
Expand All @@ -102,26 +101,25 @@ final class HelidonContainerImpl extends Weld implements HelidonContainer {
static {
HelidonFeatures.flavor(HelidonFlavor.MP);

Context.Builder contextBuilder = Context.builder()
.id("helidon-cdi");

Contexts.context()
.ifPresent(contextBuilder::parent);

ROOT_CONTEXT = contextBuilder.build();

CDI.setCDIProvider(new HelidonCdiProvider());
}

private static volatile HelidonShutdownHandler shutdownHandler;
private final WeldBootstrap bootstrap;
private final String id;
private final Context rootContext;

private HelidonCdi cdi;

HelidonContainerImpl() {
this.bootstrap = new WeldBootstrap();
this.id = STATIC_INSTANCE;
this.rootContext = Context.builder()
.id("helidon-cdi")
.update(it ->
Contexts.context()
.ifPresent(it::parent))
.build();
}

/**
Expand All @@ -140,7 +138,7 @@ static HelidonContainerImpl create() {
void initInContext() {
long time = System.nanoTime();

Contexts.runInContext(ROOT_CONTEXT, this::init);
Contexts.runInContext(rootContext, this::init);

time = System.nanoTime() - time;
long t = TimeUnit.MILLISECONDS.convert(time, TimeUnit.NANOSECONDS);
Expand Down Expand Up @@ -255,7 +253,7 @@ public SeContainer start() {
SerializationConfig.configureRuntime();
LogConfig.configureRuntime();
try {
Contexts.runInContext(ROOT_CONTEXT, this::doStart);
Contexts.runInContext(rootContext, this::doStart);
} catch (Exception e) {
try {
// we must clean up
Expand All @@ -274,7 +272,7 @@ public SeContainer start() {

@Override
public Context context() {
return ROOT_CONTEXT;
return rootContext;
}

@Override
Expand Down
Loading

0 comments on commit 213eb55

Please sign in to comment.