[ 
https://issues.apache.org/jira/browse/CAMEL-25804?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18128837#comment-18128837
 ] 

Claus Ibsen commented on CAMEL-25804:
-------------------------------------

Merged to main via https://github.com/apache/camel/pull/28102 (c78add1c7e53).

_Claude Code on behalf of Claus Ibsen_

> camel-pqc - the Micrometer stateful key gauge is held weakly and stops 
> reporting
> --------------------------------------------------------------------------------
>
>                 Key: CAMEL-25804
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25804
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-pqc
>            Reporter: Andrea Cosentino
>            Assignee: Andrea Cosentino
>            Priority: Major
>             Fix For: 4.24.0
>
>
> The {{camel.pqc.stateful.key.remaining}} gauge is registered against a lambda 
> that nothing keeps alive, so it reports {{NaN}} once that lambda is garbage 
> collected.
> {{PQCMicrometerMetrics.java:71-78}}:
> {code:java}
>     @Override
>     public void registerStatefulKeyGauge(String algorithm, LongSupplier 
> remainingSupplier) {
>         statefulKeyGauge = Gauge.builder(METRIC_STATEFUL_REMAINING, 
> remainingSupplier, LongSupplier::getAsLong)
>                 .tag("algorithm", algorithm)
>                 .description("Remaining signatures for the stateful PQC 
> signature key")
>                 .register(registry);
>     }
> {code}
> Micrometer's {{Gauge.builder(String, T obj, ToDoubleFunction<T>)}} holds the 
> state object *weakly*. Verified against the {{micrometer-core}} jar on disk:
> {noformat}
> public class io.micrometer.core.instrument.internal.DefaultGauge<T> ... {
>   private final java.lang.ref.WeakReference<T> ref;
> {noformat}
> The only reference to the supplier is the inline lambda passed by the 
> producer — {{PQCProducer.java:504-509}}:
> {code:java}
>             metrics.registerStatefulKeyGauge(signatureAlgorithm, () -> {
>                 KeyPair kp = getRuntimeKeyPair();
>                 return kp != null && kp.getPrivate() != null ? 
> getStatefulKeyRemaining(kp.getPrivate()) : -1;
>             });
> {code}
> Neither the producer nor {{PQCMicrometerMetrics}} stores it — the class keeps 
> only the {{Gauge}}. So after the next GC the metric that tells an operator a 
> one-time-use key is approaching exhaustion goes dark, silently.
> h3. Two related issues in the same class
> {{statefulKeyGauge}} is a single field ({{:40}}), so a second 
> {{registerStatefulKeyGauge}} call leaks the first gauge rather than replacing 
> it cleanly.
> {{close()}} ({{:80-87}}) removes meters by id from a shared 
> {{MeterRegistry}}, so stopping one producer unregisters counters still in use 
> by another producer carrying the same {{operation|algorithm|outcome}} tags.
> h3. Suggested fix
> Keep a strong reference to the supplier in a field of 
> {{PQCMicrometerMetrics}} (a map keyed by algorithm, so multiple registrations 
> work), and make {{close()}} only remove meters this instance actually created.
> h3. Test gap
> No test asserts the gauge still reports a value after a GC, nor that two 
> producers sharing a registry do not unregister each other's counters.
> ----
> _Reported by Claude Code (AI agent) on behalf of [~oscerd]. Every code 
> reference was verified against commit {{7aae27315946}} on {{main}}._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to