mlbiscoc commented on code in PR #3482:
URL: https://github.com/apache/solr/pull/3482#discussion_r2283045977


##########
solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java:
##########
@@ -2592,83 +2607,145 @@ public SolrMetricsContext getSolrMetricsContext() {
   // TODO SOLR-17458: Migrate to Otel
   @Override
   public void initializeMetrics(
-      SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    parentContext.gauge(() -> name, true, "searcherName", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> cachingEnabled, true, "caching", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> openTime, true, "openedAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> warmupTime, true, "warmupTime", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        () -> registerTime, true, "registeredAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        fullSortCount::sum, true, "fullSortCount", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        skipSortCount::sum, true, "skipSortCount", 
Category.SEARCHER.toString(), scope);
-    final MetricsMap liveDocsCacheMetrics =
-        new MetricsMap(
-            (map) -> {
-              map.put("inserts", liveDocsInsertsCount.sum());
-              map.put("hits", liveDocsHitCount.sum());
-              map.put("naiveHits", liveDocsNaiveCacheHitCount.sum());
-            });
-    parentContext.gauge(
-        liveDocsCacheMetrics, true, "liveDocsCache", 
Category.SEARCHER.toString(), scope);
-    // reader stats
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.numDocs()),
-        true,
-        "numDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc()),
-        true,
-        "maxDoc",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc() - 
reader.numDocs()),
-        true,
-        "deletedDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> reader.toString()),
-        true,
-        "reader",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> 
reader.directory().toString()),
-        true,
-        "readerDir",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.getVersion()),
-        true,
-        "indexVersion",
-        Category.SEARCHER.toString(),
-        scope);
+      SolrMetricsContext solrMetricsContext, Attributes attributes, String 
scope) {
+    var baseAttributes =
+        attributes.toBuilder()
+            .remove(AttributeKey.stringKey("scope"))

Review Comment:
   You shouldn't have to do this remove anymore



##########
solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java:
##########
@@ -2592,83 +2607,145 @@ public SolrMetricsContext getSolrMetricsContext() {
   // TODO SOLR-17458: Migrate to Otel
   @Override
   public void initializeMetrics(
-      SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    parentContext.gauge(() -> name, true, "searcherName", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> cachingEnabled, true, "caching", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> openTime, true, "openedAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> warmupTime, true, "warmupTime", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        () -> registerTime, true, "registeredAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        fullSortCount::sum, true, "fullSortCount", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        skipSortCount::sum, true, "skipSortCount", 
Category.SEARCHER.toString(), scope);
-    final MetricsMap liveDocsCacheMetrics =
-        new MetricsMap(
-            (map) -> {
-              map.put("inserts", liveDocsInsertsCount.sum());
-              map.put("hits", liveDocsHitCount.sum());
-              map.put("naiveHits", liveDocsNaiveCacheHitCount.sum());
-            });
-    parentContext.gauge(
-        liveDocsCacheMetrics, true, "liveDocsCache", 
Category.SEARCHER.toString(), scope);
-    // reader stats
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.numDocs()),
-        true,
-        "numDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc()),
-        true,
-        "maxDoc",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc() - 
reader.numDocs()),
-        true,
-        "deletedDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> reader.toString()),
-        true,
-        "reader",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> 
reader.directory().toString()),
-        true,
-        "readerDir",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.getVersion()),
-        true,
-        "indexVersion",
-        Category.SEARCHER.toString(),
-        scope);
+      SolrMetricsContext solrMetricsContext, Attributes attributes, String 
scope) {
+    var baseAttributes =
+        attributes.toBuilder()
+            .remove(AttributeKey.stringKey("scope"))
+            .put(CATEGORY_ATTR, Category.SEARCHER.toString())
+            .build();
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_name", "Searcher name (as attribute)", obs -> 
obs.record(1, baseAttributes));

Review Comment:
   Don't create metrics where value is in an attribute. The gauge then has a 
value of 1 that doesn't make any sense. Metrics are only numerics that can be 
aggregated. If the metric was a string as the value, just drop it completely 
and we need to figure out where this information should be instead. Also if you 
put unique names in the attributes, you blow up cardinality.



##########
solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java:
##########
@@ -2592,83 +2607,145 @@ public SolrMetricsContext getSolrMetricsContext() {
   // TODO SOLR-17458: Migrate to Otel

Review Comment:
   Remove this TODO



##########
solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java:
##########
@@ -2592,83 +2607,145 @@ public SolrMetricsContext getSolrMetricsContext() {
   // TODO SOLR-17458: Migrate to Otel
   @Override
   public void initializeMetrics(
-      SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    parentContext.gauge(() -> name, true, "searcherName", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> cachingEnabled, true, "caching", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> openTime, true, "openedAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> warmupTime, true, "warmupTime", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        () -> registerTime, true, "registeredAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        fullSortCount::sum, true, "fullSortCount", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        skipSortCount::sum, true, "skipSortCount", 
Category.SEARCHER.toString(), scope);
-    final MetricsMap liveDocsCacheMetrics =
-        new MetricsMap(
-            (map) -> {
-              map.put("inserts", liveDocsInsertsCount.sum());
-              map.put("hits", liveDocsHitCount.sum());
-              map.put("naiveHits", liveDocsNaiveCacheHitCount.sum());
-            });
-    parentContext.gauge(
-        liveDocsCacheMetrics, true, "liveDocsCache", 
Category.SEARCHER.toString(), scope);
-    // reader stats
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.numDocs()),
-        true,
-        "numDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc()),
-        true,
-        "maxDoc",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc() - 
reader.numDocs()),
-        true,
-        "deletedDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> reader.toString()),
-        true,
-        "reader",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> 
reader.directory().toString()),
-        true,
-        "readerDir",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.getVersion()),
-        true,
-        "indexVersion",
-        Category.SEARCHER.toString(),
-        scope);
+      SolrMetricsContext solrMetricsContext, Attributes attributes, String 
scope) {
+    var baseAttributes =
+        attributes.toBuilder()
+            .remove(AttributeKey.stringKey("scope"))
+            .put(CATEGORY_ATTR, Category.SEARCHER.toString())
+            .build();
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_name", "Searcher name (as attribute)", obs -> 
obs.record(1, baseAttributes));
+    // caching (boolean -> 0/1)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_caching_enabled",
+        "1 if caching enabled",
+        obs -> obs.record(cachingEnabled ? 1 : 0, baseAttributes));
+
+    // warmupTime (ms)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_warmup_time_ms",
+        "Searcher warmup time (ms)",
+        obs -> obs.record(warmupTime, baseAttributes));
+    // registeredAt (ms)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_registered_at_ms",
+        "Searcher registered time (ms)",
+        obs -> obs.record(registerTime.getTime(), baseAttributes));
+
+    // fullSortCount
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_full_sort_count",
+        "Total full sorts",
+        obs -> obs.record(fullSortCount.sum(), baseAttributes));
+    // fullSortCount
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_full_sort_count",
+        "Total full sorts",
+        obs -> obs.record(fullSortCount.sum(), baseAttributes));
+
+    // skipSortCount
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_skip_sort_count",
+        "Total skip sorts",
+        obs -> obs.record(skipSortCount.sum(), baseAttributes));
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_live_docs_cache",
+        "LiveDocs cache metrics",
+        obs -> {
+          obs.record(
+              liveDocsInsertsCount.sum(),
+              baseAttributes.toBuilder().put("type", "inserts").build());
+          obs.record(
+              liveDocsHitCount.sum(), baseAttributes.toBuilder().put("type", 
"hits").build());
+          obs.record(
+              liveDocsNaiveCacheHitCount.sum(),
+              baseAttributes.toBuilder().put("type", "naive_hits").build());
+        });
+    // reader stats (numeric)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_num_docs",
+        "Number of live docs",
+        obs -> {
+          try {
+            obs.record(reader.numDocs(), baseAttributes);
+          } catch (Exception ignore) {
+            // replacement for nullNumber
+          }
+        });
+
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_max_doc",
+        "Max doc (including deletions)",
+        obs -> {
+          try {
+            obs.record(reader.maxDoc(), baseAttributes);
+          } catch (Exception ignore) {
+          }
+        });
+
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_deleted_docs",
+        "Number of deleted docs",
+        obs -> {
+          try {
+            obs.record(reader.maxDoc() - reader.numDocs(), baseAttributes);
+          } catch (Exception ignore) {
+          }
+        });
+    // reader identity (strings → attributes on a dummy value 1)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_reader",
+        "Reader identity (as attribute)",
+        obs -> {
+          try {
+            obs.record(
+                1,
+                baseAttributes.toBuilder()
+                    .put(AttributeKey.stringKey("reader"), 
String.valueOf(reader))

Review Comment:
   Remove this reader attribute. Its not useful as an attribute and you can't 
really aggregate on something so large and unique of a string value of an 
object.



##########
solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java:
##########
@@ -2592,83 +2607,145 @@ public SolrMetricsContext getSolrMetricsContext() {
   // TODO SOLR-17458: Migrate to Otel
   @Override
   public void initializeMetrics(
-      SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    parentContext.gauge(() -> name, true, "searcherName", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> cachingEnabled, true, "caching", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> openTime, true, "openedAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> warmupTime, true, "warmupTime", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        () -> registerTime, true, "registeredAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        fullSortCount::sum, true, "fullSortCount", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        skipSortCount::sum, true, "skipSortCount", 
Category.SEARCHER.toString(), scope);
-    final MetricsMap liveDocsCacheMetrics =
-        new MetricsMap(
-            (map) -> {
-              map.put("inserts", liveDocsInsertsCount.sum());
-              map.put("hits", liveDocsHitCount.sum());
-              map.put("naiveHits", liveDocsNaiveCacheHitCount.sum());
-            });
-    parentContext.gauge(
-        liveDocsCacheMetrics, true, "liveDocsCache", 
Category.SEARCHER.toString(), scope);
-    // reader stats
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.numDocs()),
-        true,
-        "numDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc()),
-        true,
-        "maxDoc",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc() - 
reader.numDocs()),
-        true,
-        "deletedDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> reader.toString()),
-        true,
-        "reader",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> 
reader.directory().toString()),
-        true,
-        "readerDir",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.getVersion()),
-        true,
-        "indexVersion",
-        Category.SEARCHER.toString(),
-        scope);
+      SolrMetricsContext solrMetricsContext, Attributes attributes, String 
scope) {
+    var baseAttributes =
+        attributes.toBuilder()
+            .remove(AttributeKey.stringKey("scope"))
+            .put(CATEGORY_ATTR, Category.SEARCHER.toString())
+            .build();
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_name", "Searcher name (as attribute)", obs -> 
obs.record(1, baseAttributes));
+    // caching (boolean -> 0/1)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_caching_enabled",
+        "1 if caching enabled",
+        obs -> obs.record(cachingEnabled ? 1 : 0, baseAttributes));
+
+    // warmupTime (ms)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_warmup_time_ms",
+        "Searcher warmup time (ms)",
+        obs -> obs.record(warmupTime, baseAttributes));
+    // registeredAt (ms)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_registered_at_ms",
+        "Searcher registered time (ms)",
+        obs -> obs.record(registerTime.getTime(), baseAttributes));
+
+    // fullSortCount
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_full_sort_count",
+        "Total full sorts",
+        obs -> obs.record(fullSortCount.sum(), baseAttributes));
+    // fullSortCount
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_full_sort_count",
+        "Total full sorts",
+        obs -> obs.record(fullSortCount.sum(), baseAttributes));
+
+    // skipSortCount
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_skip_sort_count",
+        "Total skip sorts",
+        obs -> obs.record(skipSortCount.sum(), baseAttributes));
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_live_docs_cache",
+        "LiveDocs cache metrics",
+        obs -> {
+          obs.record(
+              liveDocsInsertsCount.sum(),
+              baseAttributes.toBuilder().put("type", "inserts").build());
+          obs.record(
+              liveDocsHitCount.sum(), baseAttributes.toBuilder().put("type", 
"hits").build());
+          obs.record(
+              liveDocsNaiveCacheHitCount.sum(),
+              baseAttributes.toBuilder().put("type", "naive_hits").build());
+        });
+    // reader stats (numeric)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_num_docs",
+        "Number of live docs",
+        obs -> {
+          try {
+            obs.record(reader.numDocs(), baseAttributes);
+          } catch (Exception ignore) {
+            // replacement for nullNumber
+          }
+        });
+
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_max_doc",
+        "Max doc (including deletions)",
+        obs -> {
+          try {
+            obs.record(reader.maxDoc(), baseAttributes);
+          } catch (Exception ignore) {
+          }
+        });
+
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_deleted_docs",
+        "Number of deleted docs",
+        obs -> {
+          try {
+            obs.record(reader.maxDoc() - reader.numDocs(), baseAttributes);
+          } catch (Exception ignore) {
+          }
+        });
+    // reader identity (strings → attributes on a dummy value 1)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_reader",
+        "Reader identity (as attribute)",
+        obs -> {
+          try {
+            obs.record(
+                1,
+                baseAttributes.toBuilder()
+                    .put(AttributeKey.stringKey("reader"), 
String.valueOf(reader))
+                    .build());
+          } catch (Exception ignore) {
+          }
+        });
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_reader_dir",
+        "Reader directory (as attribute)",
+        obs -> {
+          try {
+            obs.record(
+                1,
+                baseAttributes.toBuilder()
+                    .put(AttributeKey.stringKey("reader_dir"), 
String.valueOf(reader.directory()))
+                    .build());
+          } catch (Exception ignore) {
+          }
+        });
+    // indexVersion (numeric)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_index_version",
+        "Lucene index version",
+        obs -> {
+          try {
+            obs.record(reader.getVersion(), baseAttributes);
+          } catch (Exception ignore) {
+          }
+        });
     // size of the currently opened commit
-    parentContext.gauge(
-        () -> {
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_index_commit_size_bytes",
+        "Size of the current index commit (bytes)",
+        obs -> {
           try {
-            Collection<String> files = reader.getIndexCommit().getFileNames();
-            long total = 0;
-            for (String file : files) {
+            long total = 0L;
+            for (String file : reader.getIndexCommit().getFileNames()) {
               total += DirectoryFactory.sizeOf(reader.directory(), file);
             }
-            return total;
+            obs.record(total, baseAttributes);
           } catch (Exception e) {
-            return parentContext.nullNumber();
+            // skip recording if unavailable (no nullNumber in OTel)
           }
-        },
-        true,
-        "indexCommitSize",
-        Category.SEARCHER.toString(),
-        scope);
+        });
     // statsCache metrics
-    parentContext.gauge(
+    solrMetricsContext.gauge(

Review Comment:
   We should migrate these metrics as well.



##########
solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java:
##########
@@ -2592,83 +2607,145 @@ public SolrMetricsContext getSolrMetricsContext() {
   // TODO SOLR-17458: Migrate to Otel
   @Override
   public void initializeMetrics(
-      SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    parentContext.gauge(() -> name, true, "searcherName", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> cachingEnabled, true, "caching", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> openTime, true, "openedAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> warmupTime, true, "warmupTime", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        () -> registerTime, true, "registeredAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        fullSortCount::sum, true, "fullSortCount", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        skipSortCount::sum, true, "skipSortCount", 
Category.SEARCHER.toString(), scope);
-    final MetricsMap liveDocsCacheMetrics =
-        new MetricsMap(
-            (map) -> {
-              map.put("inserts", liveDocsInsertsCount.sum());
-              map.put("hits", liveDocsHitCount.sum());
-              map.put("naiveHits", liveDocsNaiveCacheHitCount.sum());
-            });
-    parentContext.gauge(
-        liveDocsCacheMetrics, true, "liveDocsCache", 
Category.SEARCHER.toString(), scope);
-    // reader stats
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.numDocs()),
-        true,
-        "numDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc()),
-        true,
-        "maxDoc",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc() - 
reader.numDocs()),
-        true,
-        "deletedDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> reader.toString()),
-        true,
-        "reader",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> 
reader.directory().toString()),
-        true,
-        "readerDir",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.getVersion()),
-        true,
-        "indexVersion",
-        Category.SEARCHER.toString(),
-        scope);
+      SolrMetricsContext solrMetricsContext, Attributes attributes, String 
scope) {
+    var baseAttributes =
+        attributes.toBuilder()
+            .remove(AttributeKey.stringKey("scope"))
+            .put(CATEGORY_ATTR, Category.SEARCHER.toString())
+            .build();
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_name", "Searcher name (as attribute)", obs -> 
obs.record(1, baseAttributes));
+    // caching (boolean -> 0/1)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_caching_enabled",
+        "1 if caching enabled",
+        obs -> obs.record(cachingEnabled ? 1 : 0, baseAttributes));
+
+    // warmupTime (ms)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_warmup_time_ms",
+        "Searcher warmup time (ms)",
+        obs -> obs.record(warmupTime, baseAttributes));
+    // registeredAt (ms)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_registered_at_ms",
+        "Searcher registered time (ms)",
+        obs -> obs.record(registerTime.getTime(), baseAttributes));
+
+    // fullSortCount
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_full_sort_count",
+        "Total full sorts",
+        obs -> obs.record(fullSortCount.sum(), baseAttributes));
+    // fullSortCount
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_full_sort_count",
+        "Total full sorts",

Review Comment:
   Can we have better descriptions of this and possibly others? "Total full 
sorts" alone doesn't tell use much. I am assuming this metric is counting the 
total number of full sorts it applied on a result set from a searchers doc list?



##########
solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java:
##########
@@ -2592,83 +2607,145 @@ public SolrMetricsContext getSolrMetricsContext() {
   // TODO SOLR-17458: Migrate to Otel
   @Override
   public void initializeMetrics(
-      SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    parentContext.gauge(() -> name, true, "searcherName", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> cachingEnabled, true, "caching", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> openTime, true, "openedAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> warmupTime, true, "warmupTime", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        () -> registerTime, true, "registeredAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        fullSortCount::sum, true, "fullSortCount", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        skipSortCount::sum, true, "skipSortCount", 
Category.SEARCHER.toString(), scope);
-    final MetricsMap liveDocsCacheMetrics =
-        new MetricsMap(
-            (map) -> {
-              map.put("inserts", liveDocsInsertsCount.sum());
-              map.put("hits", liveDocsHitCount.sum());
-              map.put("naiveHits", liveDocsNaiveCacheHitCount.sum());
-            });
-    parentContext.gauge(
-        liveDocsCacheMetrics, true, "liveDocsCache", 
Category.SEARCHER.toString(), scope);
-    // reader stats
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.numDocs()),
-        true,
-        "numDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc()),
-        true,
-        "maxDoc",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc() - 
reader.numDocs()),
-        true,
-        "deletedDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> reader.toString()),
-        true,
-        "reader",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> 
reader.directory().toString()),
-        true,
-        "readerDir",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.getVersion()),
-        true,
-        "indexVersion",
-        Category.SEARCHER.toString(),
-        scope);
+      SolrMetricsContext solrMetricsContext, Attributes attributes, String 
scope) {
+    var baseAttributes =
+        attributes.toBuilder()
+            .remove(AttributeKey.stringKey("scope"))
+            .put(CATEGORY_ATTR, Category.SEARCHER.toString())
+            .build();
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_name", "Searcher name (as attribute)", obs -> 
obs.record(1, baseAttributes));
+    // caching (boolean -> 0/1)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_caching_enabled",
+        "1 if caching enabled",
+        obs -> obs.record(cachingEnabled ? 1 : 0, baseAttributes));
+
+    // warmupTime (ms)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_warmup_time_ms",
+        "Searcher warmup time (ms)",
+        obs -> obs.record(warmupTime, baseAttributes));
+    // registeredAt (ms)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_registered_at_ms",
+        "Searcher registered time (ms)",
+        obs -> obs.record(registerTime.getTime(), baseAttributes));
+
+    // fullSortCount
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_full_sort_count",
+        "Total full sorts",
+        obs -> obs.record(fullSortCount.sum(), baseAttributes));

Review Comment:
   For these metrics, don't use a gauge. We can see that fullSortCount is 
basically a counter backed by LongAdder. We should either switch LongAdder and 
create an `AttributedLongCounter` or use an `observableLongCounter` and 
callback on `fullSortCount.sum()`. Remove `_count` from the name as counter 
type implies that already and prometheus format will append `_total` as a 
suffix.



##########
solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java:
##########
@@ -2592,83 +2607,145 @@ public SolrMetricsContext getSolrMetricsContext() {
   // TODO SOLR-17458: Migrate to Otel
   @Override
   public void initializeMetrics(
-      SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    parentContext.gauge(() -> name, true, "searcherName", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> cachingEnabled, true, "caching", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> openTime, true, "openedAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> warmupTime, true, "warmupTime", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        () -> registerTime, true, "registeredAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        fullSortCount::sum, true, "fullSortCount", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        skipSortCount::sum, true, "skipSortCount", 
Category.SEARCHER.toString(), scope);
-    final MetricsMap liveDocsCacheMetrics =
-        new MetricsMap(
-            (map) -> {
-              map.put("inserts", liveDocsInsertsCount.sum());
-              map.put("hits", liveDocsHitCount.sum());
-              map.put("naiveHits", liveDocsNaiveCacheHitCount.sum());
-            });
-    parentContext.gauge(
-        liveDocsCacheMetrics, true, "liveDocsCache", 
Category.SEARCHER.toString(), scope);
-    // reader stats
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.numDocs()),
-        true,
-        "numDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc()),
-        true,
-        "maxDoc",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc() - 
reader.numDocs()),
-        true,
-        "deletedDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> reader.toString()),
-        true,
-        "reader",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> 
reader.directory().toString()),
-        true,
-        "readerDir",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.getVersion()),
-        true,
-        "indexVersion",
-        Category.SEARCHER.toString(),
-        scope);
+      SolrMetricsContext solrMetricsContext, Attributes attributes, String 
scope) {
+    var baseAttributes =
+        attributes.toBuilder()
+            .remove(AttributeKey.stringKey("scope"))
+            .put(CATEGORY_ATTR, Category.SEARCHER.toString())
+            .build();
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_name", "Searcher name (as attribute)", obs -> 
obs.record(1, baseAttributes));
+    // caching (boolean -> 0/1)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_caching_enabled",
+        "1 if caching enabled",
+        obs -> obs.record(cachingEnabled ? 1 : 0, baseAttributes));
+
+    // warmupTime (ms)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_warmup_time_ms",
+        "Searcher warmup time (ms)",
+        obs -> obs.record(warmupTime, baseAttributes));
+    // registeredAt (ms)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_registered_at_ms",
+        "Searcher registered time (ms)",
+        obs -> obs.record(registerTime.getTime(), baseAttributes));
+
+    // fullSortCount
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_full_sort_count",
+        "Total full sorts",
+        obs -> obs.record(fullSortCount.sum(), baseAttributes));
+    // fullSortCount
+    solrMetricsContext.observableLongGauge(

Review Comment:
   Did you accidentally dupe this?



##########
solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java:
##########
@@ -2592,83 +2607,145 @@ public SolrMetricsContext getSolrMetricsContext() {
   // TODO SOLR-17458: Migrate to Otel
   @Override
   public void initializeMetrics(
-      SolrMetricsContext parentContext, Attributes attributes, String scope) {
-    parentContext.gauge(() -> name, true, "searcherName", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> cachingEnabled, true, "caching", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> openTime, true, "openedAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(() -> warmupTime, true, "warmupTime", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        () -> registerTime, true, "registeredAt", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        fullSortCount::sum, true, "fullSortCount", 
Category.SEARCHER.toString(), scope);
-    parentContext.gauge(
-        skipSortCount::sum, true, "skipSortCount", 
Category.SEARCHER.toString(), scope);
-    final MetricsMap liveDocsCacheMetrics =
-        new MetricsMap(
-            (map) -> {
-              map.put("inserts", liveDocsInsertsCount.sum());
-              map.put("hits", liveDocsHitCount.sum());
-              map.put("naiveHits", liveDocsNaiveCacheHitCount.sum());
-            });
-    parentContext.gauge(
-        liveDocsCacheMetrics, true, "liveDocsCache", 
Category.SEARCHER.toString(), scope);
-    // reader stats
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.numDocs()),
-        true,
-        "numDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc()),
-        true,
-        "maxDoc",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.maxDoc() - 
reader.numDocs()),
-        true,
-        "deletedDocs",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> reader.toString()),
-        true,
-        "reader",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullString(), () -> 
reader.directory().toString()),
-        true,
-        "readerDir",
-        Category.SEARCHER.toString(),
-        scope);
-    parentContext.gauge(
-        rgauge(parentContext.nullNumber(), () -> reader.getVersion()),
-        true,
-        "indexVersion",
-        Category.SEARCHER.toString(),
-        scope);
+      SolrMetricsContext solrMetricsContext, Attributes attributes, String 
scope) {
+    var baseAttributes =
+        attributes.toBuilder()
+            .remove(AttributeKey.stringKey("scope"))
+            .put(CATEGORY_ATTR, Category.SEARCHER.toString())
+            .build();
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_name", "Searcher name (as attribute)", obs -> 
obs.record(1, baseAttributes));
+    // caching (boolean -> 0/1)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_caching_enabled",
+        "1 if caching enabled",
+        obs -> obs.record(cachingEnabled ? 1 : 0, baseAttributes));
+
+    // warmupTime (ms)
+    solrMetricsContext.observableLongGauge(
+        "solr_searcher_warmup_time_ms",
+        "Searcher warmup time (ms)",
+        obs -> obs.record(warmupTime, baseAttributes));

Review Comment:
   For OTEL, you put the unit as metadata. Pass `OtelUnit.MILLISECONDS` and 
remove `_ms` from the name. Prometheus metric reader will append milliseconds 
in the name itself as a way to follow prometheus format.



-- 
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