[ 
https://issues.apache.org/jira/browse/NIFI-16297?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Pierre Villard resolved NIFI-16297.
-----------------------------------
    Fix Version/s: 2.12.0
         Assignee: Alexander Bij
       Resolution: Fixed

> Prometheus jvm/cluster/connection metrics permanently retain a stale 
> pre-cluster-join instance ID series
> --------------------------------------------------------------------------------------------------------
>
>                 Key: NIFI-16297
>                 URL: https://issues.apache.org/jira/browse/NIFI-16297
>             Project: Apache NiFi
>          Issue Type: Bug
>          Components: Core Framework
>    Affects Versions: 2.1.0, 2.11.0
>            Reporter: Alexander Bij
>            Assignee: Alexander Bij
>            Priority: Minor
>              Labels: metric-collector, metrics, prometheus
>             Fix For: 2.12.0
>
>          Time Spent: 0.5h
>  Remaining Estimate: 0h
>
> h2. Summary
> NIFI-14014 described this exact problem: a node's Prometheus {{instance}} 
> label starts as a temporary, per-process value and later switches to the 
> node's persisted cluster UUID once it joins the cluster; any scrape that 
> lands before that switch leaves a permanent, frozen series behind under the 
> old value. NIFI-14014's fix (prefer {{node.getId()}} over 
> {{controllerFacade.getInstanceId()}} once available) only changed which 
> identifier is used after the transition – it did not stop metrics from being 
> recorded under the temporary identifier before the transition, and it did not 
> address the actual root cause: the registries these metrics live in are 
> long-lived singletons that are never cleared. As a result, the symptom 
> NIFI-14014 was meant to fix can still occur today.
> This affects {{{}jvmMetricsRegistry{}}}, 
> {{{}connectionAnalyticsMetricsRegistry{}}}, and {{clusterMetricsRegistry.}} 
> Every metric in all three registries shares the exact same {{instance}} label 
> value, computed once per scrape.
> h2. Root cause
> {code:java}
> // StandardNiFiServiceFacade.java, inside populateFlowMetrics()
> final NodeIdentifier node = controllerFacade.getNodeId();
> final String instId = StringUtils.isEmpty(controllerFacade.getInstanceId()) ? 
> "" : controllerFacade.getInstanceId();
> final String instanceId = node == null ? instId : node.getId();
> {code}
>  * Before a clustered node completes its first connection handshake, 
> {{controllerFacade.getNodeId()}} is {{{}null{}}}, so {{instanceId}} falls 
> back to {{controllerFacade.getInstanceId()}} (i.e. 
> {{FlowController.instanceId}} – effectively a standalone-mode value, itself 
> sourced from whichever node is currently cluster coordinator).
>  * Once the handshake completes, {{getNodeId()}} becomes non-null and 
> {{instanceId}} permanently switches to the node's persisted cluster UUID 
> ({{{}node.getId(){}}}), which is stable for the rest of that process's life 
> (stored via local {{StateManager}} state, unaffected by later 
> disconnects/reconnects/coordinator elections).
>  * This one-time transition happens on every node start in a clustered 
> deployment. Any scrape landing in the (typically brief, but non-zero) window 
> before the transition permanently registers {{instance=<temporary-id>}} in 
> {{{}jvmMetricsRegistry{}}}, {{{}connectionAnalyticsMetricsRegistry{}}}, and 
> {{clusterMetricsRegistry}} – and because none of these three registries are 
> ever cleared or recreated, that series is never removed. It sits frozen at 
> whatever value it had during that startup window, returned on every 
> subsequent scrape for the life of the process, alongside the correct, 
> continuously-updated series under the real node UUID.
> h2. Why NIFI-14014 didn't fully fix this
> NIFI-14014's own description matches this symptom precisely: "If metrics 
> endpoints are queried before the instance ID transitions, various Gauges 
> (JVM, cluster, and storage metrics) register with the initial instance 
> identifier. When the metrics endpoints are subsequently called after the 
> clustered instance ID is set, the system returns data for both the outdated 
> instance ID and the new one, creating duplicate metric streams." The fix (PR 
> #9528) only reordered which identifier source is preferred; it never 
> addressed why a stale identifier's data persists forever once recorded – i.e. 
> it didn't touch the singleton/never-cleared registry lifecycle, which is the 
> actual root cause (the same root cause behind NIFI-8272, NIFI-11899, and 
> NIFI-16296).
> h2. Steps to reproduce
>  # Start (or restart) a NiFi node configured to join a cluster.
>  # As early as possible during that node's startup – before it has completed 
> its initial connect handshake – scrape {{GET 
> /nifi-api/flow/metrics/prometheus}} on that node (a tight polling loop from 
> just after process start works; a Kubernetes readiness/liveness probe pointed 
> at this endpoint reproduces this reliably in practice). Observe 
> {{nifi_jvm_heap_used}} (or any {{{}nifi_jvm_{}}}/{{{}cluster_{}}} metric) 
> reported under some {{{}instance=<uuid-A>{}}}.
>  # Wait for the node to finish joining the cluster, then scrape again. 
> Observe the same metrics now reported under a different {{instance=<uuid-B>}} 
> (the persisted cluster node UUID).
>  # Continue scraping indefinitely – observe that {{{}instance=<uuid-A>{}}}'s 
> series for every metric in {{{}jvmMetricsRegistry{}}}, 
> {{{}connectionAnalyticsMetricsRegistry{}}}, and {{clusterMetricsRegistry}} 
> remains present, frozen at its last-recorded values, for the remaining 
> lifetime of the process.



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

Reply via email to