dsmiley commented on code in PR #3514:
URL: https://github.com/apache/solr/pull/3514#discussion_r2302214106


##########
solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java:
##########
@@ -841,83 +851,139 @@ private CommitVersionInfo getIndexVersion() {
   @Override
   public void initializeMetrics(
       SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    super.initializeMetrics(parentContext, attributes, scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? NumberUtils.readableSize(core.getIndexSize())
-                : parentContext.nullString()),
-        true,
-        "indexSize",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().toString()
-                : parentContext.nullString()),
-        true,
-        "indexVersion",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().generation
-                : parentContext.nullNumber()),
-        true,
-        GENERATION,
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () -> (core != null && !core.isClosed() ? core.getIndexDir() : 
parentContext.nullString()),
-        true,
-        "indexPath",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(() -> isLeader, true, "isLeader", 
getCategory().toString(), scope);
-    solrMetricsContext.gauge(() -> isFollower, true, "isFollower", 
getCategory().toString(), scope);
-    final MetricsMap fetcherMap =
-        new MetricsMap(
-            map -> {
+    Attributes replicationAttributes =
+        Attributes.builder()
+            .putAll(attributes)
+            .put(CATEGORY_ATTR, Category.REPLICATION.toString())
+            .build();
+    super.initializeMetrics(parentContext, replicationAttributes, scope);
+
+    indexSizeGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_size",
+            "Size of the index in bytes",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(core.getIndexSize(), replicationAttributes);
+              }
+            },
+            OtelUnit.BYTES);
+
+    indexVersionGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_version",
+            "Current index version",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(getIndexVersion().version, replicationAttributes);
+              }
+            });
+
+    generationGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_generation",
+            "Current index generation",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(getIndexVersion().generation, 
replicationAttributes);
+              }
+            });
+
+    isLeaderGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_leader",
+            "Whether this node is a leader (1) or not (0)",
+            gauge -> gauge.record(isLeader ? 1 : 0, replicationAttributes));
+
+    isFollowerGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_follower",
+            "Whether this node is a follower (1) or not (0)",
+            gauge -> gauge.record(isFollower ? 1 : 0, replicationAttributes));
+
+    replicationEnabledGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_enabled",
+            "Whether replication is enabled (1) or not (0)",
+            gauge ->
+                gauge.record(
+                    (isLeader && replicationEnabled.get()) ? 1 : 0, 
replicationAttributes));
+
+    // Create measurements for fetcher metrics in a batch to ensure consistent 
fetcher reference
+    ObservableLongMeasurement isPollingDisabled =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_is_polling_disabled", "Whether polling is 
disabled (1) or not (0)");
+
+    ObservableLongMeasurement isReplicating =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_is_replicating", "Whether replication is in 
progress (1) or not (0)");
+
+    ObservableLongMeasurement timeElapsed =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_time_elapsed",
+            "Time elapsed during replication in seconds",
+            OtelUnit.SECONDS);
+
+    ObservableLongMeasurement bytesDownloaded =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_bytes_downloaded",

Review Comment:
   @mlbiscoc I recall you said that "_bytes" will be appended if that is the 
unit.  If so, then this metric shouldn't have "bytes" in it already.  Maybe use 
"solr_replication_downloaded_size"



##########
solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java:
##########
@@ -841,83 +851,139 @@ private CommitVersionInfo getIndexVersion() {
   @Override
   public void initializeMetrics(
       SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    super.initializeMetrics(parentContext, attributes, scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? NumberUtils.readableSize(core.getIndexSize())
-                : parentContext.nullString()),
-        true,
-        "indexSize",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().toString()
-                : parentContext.nullString()),
-        true,
-        "indexVersion",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().generation
-                : parentContext.nullNumber()),
-        true,
-        GENERATION,
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () -> (core != null && !core.isClosed() ? core.getIndexDir() : 
parentContext.nullString()),
-        true,
-        "indexPath",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(() -> isLeader, true, "isLeader", 
getCategory().toString(), scope);
-    solrMetricsContext.gauge(() -> isFollower, true, "isFollower", 
getCategory().toString(), scope);
-    final MetricsMap fetcherMap =
-        new MetricsMap(
-            map -> {
+    Attributes replicationAttributes =
+        Attributes.builder()
+            .putAll(attributes)
+            .put(CATEGORY_ATTR, Category.REPLICATION.toString())
+            .build();
+    super.initializeMetrics(parentContext, replicationAttributes, scope);
+
+    indexSizeGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_size",
+            "Size of the index in bytes",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(core.getIndexSize(), replicationAttributes);
+              }
+            },
+            OtelUnit.BYTES);
+
+    indexVersionGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_version",
+            "Current index version",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(getIndexVersion().version, replicationAttributes);
+              }
+            });
+
+    generationGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_generation",

Review Comment:
   shouldn't this have "index" in its name, like the others?  Even the 
description refers to the "index".



##########
solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java:
##########
@@ -841,83 +851,139 @@ private CommitVersionInfo getIndexVersion() {
   @Override
   public void initializeMetrics(
       SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    super.initializeMetrics(parentContext, attributes, scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? NumberUtils.readableSize(core.getIndexSize())
-                : parentContext.nullString()),
-        true,
-        "indexSize",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().toString()
-                : parentContext.nullString()),
-        true,
-        "indexVersion",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().generation
-                : parentContext.nullNumber()),
-        true,
-        GENERATION,
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () -> (core != null && !core.isClosed() ? core.getIndexDir() : 
parentContext.nullString()),
-        true,
-        "indexPath",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(() -> isLeader, true, "isLeader", 
getCategory().toString(), scope);
-    solrMetricsContext.gauge(() -> isFollower, true, "isFollower", 
getCategory().toString(), scope);
-    final MetricsMap fetcherMap =
-        new MetricsMap(
-            map -> {
+    Attributes replicationAttributes =
+        Attributes.builder()
+            .putAll(attributes)
+            .put(CATEGORY_ATTR, Category.REPLICATION.toString())
+            .build();
+    super.initializeMetrics(parentContext, replicationAttributes, scope);
+
+    indexSizeGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_size",
+            "Size of the index in bytes",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(core.getIndexSize(), replicationAttributes);
+              }
+            },
+            OtelUnit.BYTES);
+
+    indexVersionGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_version",
+            "Current index version",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(getIndexVersion().version, replicationAttributes);
+              }
+            });
+
+    generationGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_generation",
+            "Current index generation",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(getIndexVersion().generation, 
replicationAttributes);
+              }
+            });
+
+    isLeaderGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_leader",
+            "Whether this node is a leader (1) or not (0)",
+            gauge -> gauge.record(isLeader ? 1 : 0, replicationAttributes));
+
+    isFollowerGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_follower",
+            "Whether this node is a follower (1) or not (0)",
+            gauge -> gauge.record(isFollower ? 1 : 0, replicationAttributes));
+
+    replicationEnabledGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_enabled",
+            "Whether replication is enabled (1) or not (0)",
+            gauge ->
+                gauge.record(
+                    (isLeader && replicationEnabled.get()) ? 1 : 0, 
replicationAttributes));
+
+    // Create measurements for fetcher metrics in a batch to ensure consistent 
fetcher reference
+    ObservableLongMeasurement isPollingDisabled =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_is_polling_disabled", "Whether polling is 
disabled (1) or not (0)");
+
+    ObservableLongMeasurement isReplicating =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_is_replicating", "Whether replication is in 
progress (1) or not (0)");
+
+    ObservableLongMeasurement timeElapsed =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_time_elapsed",
+            "Time elapsed during replication in seconds",
+            OtelUnit.SECONDS);
+
+    ObservableLongMeasurement bytesDownloaded =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_bytes_downloaded",
+            "Total bytes downloaded during replication",
+            OtelUnit.BYTES);
+
+    ObservableLongMeasurement downloadSpeed =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_download_speed", "Download speed in bytes per 
second");
+
+    // Use batch callback to ensure consistent fetcher reference
+    fetcherMetricsBatch =
+        solrMetricsContext.batchCallback(
+            () -> {
               IndexFetcher fetcher = currentIndexFetcher;
               if (fetcher != null) {
-                map.put(LEADER_URL, fetcher.getLeaderCoreUrl());
-                if (getPollInterval() != null) {
-                  map.put(ReplicationAPIBase.POLL_INTERVAL, getPollInterval());
-                }
-                map.put("isPollingDisabled", isPollingDisabled());
-                map.put("isReplicating", isReplicating());
+                isPollingDisabled.record(isPollingDisabled() ? 1 : 0, 
replicationAttributes);
+                isReplicating.record(isReplicating() ? 1 : 0, 
replicationAttributes);
+
                 long elapsed = fetcher.getReplicationTimeElapsed();
                 long val = fetcher.getTotalBytesDownloaded();
                 if (elapsed > 0) {
-                  map.put("timeElapsed", elapsed);
-                  map.put("bytesDownloaded", val);
-                  map.put("downloadSpeed", val / elapsed);
+                  timeElapsed.record(elapsed, replicationAttributes);
+                  bytesDownloaded.record(val, replicationAttributes);
+                  downloadSpeed.record(val / elapsed, replicationAttributes);
                 }
-                Properties props = loadReplicationProperties();
-                addReplicationProperties(map::putNoEx, props);
               }
-            });
-    solrMetricsContext.gauge(fetcherMap, true, "fetcher", 
getCategory().toString(), scope);
-    solrMetricsContext.gauge(
-        () -> isLeader && includeConfFiles != null ? includeConfFiles : "",
-        true,
-        "confFilesToReplicate",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () -> isLeader ? getReplicateAfterStrings() : 
Collections.<String>emptyList(),
-        true,
-        REPLICATE_AFTER,
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () -> isLeader && replicationEnabled.get(),
-        true,
-        "replicationEnabled",
-        getCategory().toString(),
-        scope);
+            },
+            isPollingDisabled,
+            isReplicating,
+            timeElapsed,
+            bytesDownloaded,
+            downloadSpeed);
+  }
+
+  @Override
+  public void close() throws IOException {

Review Comment:
   Interesting OTEL difference... gauges need to be closed.  Good to know, and 
makes sense to me.



##########
solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java:
##########
@@ -841,83 +851,139 @@ private CommitVersionInfo getIndexVersion() {
   @Override
   public void initializeMetrics(
       SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    super.initializeMetrics(parentContext, attributes, scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? NumberUtils.readableSize(core.getIndexSize())
-                : parentContext.nullString()),
-        true,
-        "indexSize",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().toString()
-                : parentContext.nullString()),
-        true,
-        "indexVersion",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().generation
-                : parentContext.nullNumber()),
-        true,
-        GENERATION,
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () -> (core != null && !core.isClosed() ? core.getIndexDir() : 
parentContext.nullString()),
-        true,
-        "indexPath",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(() -> isLeader, true, "isLeader", 
getCategory().toString(), scope);
-    solrMetricsContext.gauge(() -> isFollower, true, "isFollower", 
getCategory().toString(), scope);
-    final MetricsMap fetcherMap =
-        new MetricsMap(
-            map -> {
+    Attributes replicationAttributes =
+        Attributes.builder()
+            .putAll(attributes)
+            .put(CATEGORY_ATTR, Category.REPLICATION.toString())
+            .build();
+    super.initializeMetrics(parentContext, replicationAttributes, scope);
+
+    indexSizeGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_size",
+            "Size of the index in bytes",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(core.getIndexSize(), replicationAttributes);
+              }
+            },
+            OtelUnit.BYTES);
+
+    indexVersionGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_version",
+            "Current index version",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(getIndexVersion().version, replicationAttributes);
+              }
+            });
+
+    generationGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_generation",
+            "Current index generation",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(getIndexVersion().generation, 
replicationAttributes);
+              }
+            });
+
+    isLeaderGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_leader",
+            "Whether this node is a leader (1) or not (0)",
+            gauge -> gauge.record(isLeader ? 1 : 0, replicationAttributes));
+
+    isFollowerGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_follower",
+            "Whether this node is a follower (1) or not (0)",
+            gauge -> gauge.record(isFollower ? 1 : 0, replicationAttributes));
+
+    replicationEnabledGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_enabled",
+            "Whether replication is enabled (1) or not (0)",
+            gauge ->
+                gauge.record(
+                    (isLeader && replicationEnabled.get()) ? 1 : 0, 
replicationAttributes));
+
+    // Create measurements for fetcher metrics in a batch to ensure consistent 
fetcher reference
+    ObservableLongMeasurement isPollingDisabled =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_is_polling_disabled", "Whether polling is 
disabled (1) or not (0)");
+
+    ObservableLongMeasurement isReplicating =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_is_replicating", "Whether replication is in 
progress (1) or not (0)");
+
+    ObservableLongMeasurement timeElapsed =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_time_elapsed",
+            "Time elapsed during replication in seconds",
+            OtelUnit.SECONDS);
+
+    ObservableLongMeasurement bytesDownloaded =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_bytes_downloaded",
+            "Total bytes downloaded during replication",
+            OtelUnit.BYTES);
+
+    ObservableLongMeasurement downloadSpeed =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_download_speed", "Download speed in bytes per 
second");
+
+    // Use batch callback to ensure consistent fetcher reference
+    fetcherMetricsBatch =
+        solrMetricsContext.batchCallback(
+            () -> {
               IndexFetcher fetcher = currentIndexFetcher;
               if (fetcher != null) {
-                map.put(LEADER_URL, fetcher.getLeaderCoreUrl());
-                if (getPollInterval() != null) {
-                  map.put(ReplicationAPIBase.POLL_INTERVAL, getPollInterval());
-                }
-                map.put("isPollingDisabled", isPollingDisabled());
-                map.put("isReplicating", isReplicating());
+                isPollingDisabled.record(isPollingDisabled() ? 1 : 0, 
replicationAttributes);
+                isReplicating.record(isReplicating() ? 1 : 0, 
replicationAttributes);
+
                 long elapsed = fetcher.getReplicationTimeElapsed();
                 long val = fetcher.getTotalBytesDownloaded();
                 if (elapsed > 0) {
-                  map.put("timeElapsed", elapsed);
-                  map.put("bytesDownloaded", val);
-                  map.put("downloadSpeed", val / elapsed);
+                  timeElapsed.record(elapsed, replicationAttributes);
+                  bytesDownloaded.record(val, replicationAttributes);
+                  downloadSpeed.record(val / elapsed, replicationAttributes);
                 }
-                Properties props = loadReplicationProperties();
-                addReplicationProperties(map::putNoEx, props);
               }
-            });
-    solrMetricsContext.gauge(fetcherMap, true, "fetcher", 
getCategory().toString(), scope);
-    solrMetricsContext.gauge(
-        () -> isLeader && includeConfFiles != null ? includeConfFiles : "",
-        true,
-        "confFilesToReplicate",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () -> isLeader ? getReplicateAfterStrings() : 
Collections.<String>emptyList(),
-        true,
-        REPLICATE_AFTER,
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () -> isLeader && replicationEnabled.get(),
-        true,
-        "replicationEnabled",
-        getCategory().toString(),
-        scope);
+            },
+            isPollingDisabled,
+            isReplicating,
+            timeElapsed,
+            bytesDownloaded,
+            downloadSpeed);
+  }
+
+  @Override
+  public void close() throws IOException {
+    if (indexSizeGauge != null) {

Review Comment:
   try `IOUtils.closeQuietly` to make these one-liners



##########
solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java:
##########
@@ -841,83 +851,139 @@ private CommitVersionInfo getIndexVersion() {
   @Override
   public void initializeMetrics(
       SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    super.initializeMetrics(parentContext, attributes, scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? NumberUtils.readableSize(core.getIndexSize())
-                : parentContext.nullString()),
-        true,
-        "indexSize",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().toString()
-                : parentContext.nullString()),
-        true,
-        "indexVersion",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().generation
-                : parentContext.nullNumber()),
-        true,
-        GENERATION,
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () -> (core != null && !core.isClosed() ? core.getIndexDir() : 
parentContext.nullString()),
-        true,
-        "indexPath",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(() -> isLeader, true, "isLeader", 
getCategory().toString(), scope);
-    solrMetricsContext.gauge(() -> isFollower, true, "isFollower", 
getCategory().toString(), scope);
-    final MetricsMap fetcherMap =
-        new MetricsMap(
-            map -> {
+    Attributes replicationAttributes =
+        Attributes.builder()
+            .putAll(attributes)
+            .put(CATEGORY_ATTR, Category.REPLICATION.toString())
+            .build();
+    super.initializeMetrics(parentContext, replicationAttributes, scope);
+
+    indexSizeGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_size",
+            "Size of the index in bytes",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(core.getIndexSize(), replicationAttributes);
+              }
+            },
+            OtelUnit.BYTES);
+
+    indexVersionGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_version",
+            "Current index version",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(getIndexVersion().version, replicationAttributes);
+              }
+            });
+
+    generationGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_generation",
+            "Current index generation",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(getIndexVersion().generation, 
replicationAttributes);
+              }
+            });
+
+    isLeaderGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_leader",
+            "Whether this node is a leader (1) or not (0)",
+            gauge -> gauge.record(isLeader ? 1 : 0, replicationAttributes));
+
+    isFollowerGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_follower",
+            "Whether this node is a follower (1) or not (0)",
+            gauge -> gauge.record(isFollower ? 1 : 0, replicationAttributes));
+
+    replicationEnabledGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_enabled",
+            "Whether replication is enabled (1) or not (0)",
+            gauge ->
+                gauge.record(
+                    (isLeader && replicationEnabled.get()) ? 1 : 0, 
replicationAttributes));
+
+    // Create measurements for fetcher metrics in a batch to ensure consistent 
fetcher reference
+    ObservableLongMeasurement isPollingDisabled =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_is_polling_disabled", "Whether polling is 
disabled (1) or not (0)");
+
+    ObservableLongMeasurement isReplicating =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_is_replicating", "Whether replication is in 
progress (1) or not (0)");
+
+    ObservableLongMeasurement timeElapsed =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_time_elapsed",
+            "Time elapsed during replication in seconds",
+            OtelUnit.SECONDS);
+
+    ObservableLongMeasurement bytesDownloaded =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_bytes_downloaded",
+            "Total bytes downloaded during replication",
+            OtelUnit.BYTES);
+
+    ObservableLongMeasurement downloadSpeed =
+        solrMetricsContext.longMeasurement(
+            "solr_replication_download_speed", "Download speed in bytes per 
second");
+
+    // Use batch callback to ensure consistent fetcher reference

Review Comment:
   cool feature of OTEL here!  Glad you thought of it.
   
   But I fail to see how you are leveraging it here in this snippet.  You see 
if currentIndexFetcher isn't null then call methods that don't seem (at a 
glance) to have to do with it.



##########
solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java:
##########
@@ -841,83 +851,139 @@ private CommitVersionInfo getIndexVersion() {
   @Override
   public void initializeMetrics(
       SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    super.initializeMetrics(parentContext, attributes, scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? NumberUtils.readableSize(core.getIndexSize())
-                : parentContext.nullString()),
-        true,
-        "indexSize",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().toString()
-                : parentContext.nullString()),
-        true,
-        "indexVersion",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () ->
-            (core != null && !core.isClosed()
-                ? getIndexVersion().generation
-                : parentContext.nullNumber()),
-        true,
-        GENERATION,
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(
-        () -> (core != null && !core.isClosed() ? core.getIndexDir() : 
parentContext.nullString()),
-        true,
-        "indexPath",
-        getCategory().toString(),
-        scope);
-    solrMetricsContext.gauge(() -> isLeader, true, "isLeader", 
getCategory().toString(), scope);
-    solrMetricsContext.gauge(() -> isFollower, true, "isFollower", 
getCategory().toString(), scope);
-    final MetricsMap fetcherMap =
-        new MetricsMap(
-            map -> {
+    Attributes replicationAttributes =
+        Attributes.builder()
+            .putAll(attributes)
+            .put(CATEGORY_ATTR, Category.REPLICATION.toString())
+            .build();
+    super.initializeMetrics(parentContext, replicationAttributes, scope);
+
+    indexSizeGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_size",
+            "Size of the index in bytes",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(core.getIndexSize(), replicationAttributes);
+              }
+            },
+            OtelUnit.BYTES);
+
+    indexVersionGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_index_version",
+            "Current index version",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(getIndexVersion().version, replicationAttributes);
+              }
+            });
+
+    generationGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_generation",
+            "Current index generation",
+            gauge -> {
+              if (core != null && !core.isClosed()) {
+                gauge.record(getIndexVersion().generation, 
replicationAttributes);
+              }
+            });
+
+    isLeaderGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_leader",
+            "Whether this node is a leader (1) or not (0)",
+            gauge -> gauge.record(isLeader ? 1 : 0, replicationAttributes));
+
+    isFollowerGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_follower",
+            "Whether this node is a follower (1) or not (0)",
+            gauge -> gauge.record(isFollower ? 1 : 0, replicationAttributes));
+
+    replicationEnabledGauge =
+        solrMetricsContext.observableLongGauge(
+            "solr_replication_is_enabled",
+            "Whether replication is enabled (1) or not (0)",
+            gauge ->
+                gauge.record(
+                    (isLeader && replicationEnabled.get()) ? 1 : 0, 
replicationAttributes));
+
+    // Create measurements for fetcher metrics in a batch to ensure consistent 
fetcher reference
+    ObservableLongMeasurement isPollingDisabled =

Review Comment:
   @epugh you seem all about an "enabled" only world.  Does that apply to not 
only configuration but metrics?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to