From a9ab430fd3b773f996253aeddcfb3fde42e04a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Tue, 17 Mar 2026 20:27:06 +0100 Subject: [PATCH 1/6] SOLR-18165 Use dot separated metric names for OTLP --- .../SOLR-18165-dot-separated-metric-names.yml | 8 ++++ .../org/apache/solr/core/CoreContainer.java | 4 +- .../java/org/apache/solr/core/SolrCore.java | 20 +++++----- .../solr/handler/ReplicationHandler.java | 22 +++++------ .../solr/handler/RequestHandlerBase.java | 10 ++--- .../solr/handler/admin/CoreAdminHandler.java | 4 +- .../component/HttpShardHandlerFactory.java | 2 +- .../handler/component/SuggestComponent.java | 2 +- .../FilterablePrometheusMetricReader.java | 18 +++++++-- .../AttributedInstrumentFactory.java | 2 +- .../solr/search/SolrFieldCacheBean.java | 4 +- .../apache/solr/search/SolrIndexSearcher.java | 14 +++---- .../apache/solr/search/stats/StatsCache.java | 2 +- .../solr/update/DirectUpdateHandler2.java | 38 +++++++++---------- .../java/org/apache/solr/update/PeerSync.java | 6 +-- .../solr/update/PeerSyncWithLeader.java | 6 +-- .../apache/solr/update/SolrIndexWriter.java | 10 ++--- .../org/apache/solr/update/UpdateLog.java | 14 +++---- .../solr/update/UpdateShardHandler.java | 4 +- .../update/processor/ProducerMetrics.java | 16 ++++---- 20 files changed, 113 insertions(+), 93 deletions(-) create mode 100644 changelog/unreleased/SOLR-18165-dot-separated-metric-names.yml diff --git a/changelog/unreleased/SOLR-18165-dot-separated-metric-names.yml b/changelog/unreleased/SOLR-18165-dot-separated-metric-names.yml new file mode 100644 index 000000000000..cb4a84fbfbfd --- /dev/null +++ b/changelog/unreleased/SOLR-18165-dot-separated-metric-names.yml @@ -0,0 +1,8 @@ +title: Use dot-separated OTel metric names for OTLP export. This is a back-compat break from version 10.0 +type: changed +authors: + - name: Jan Høydahl + url: https://home.apache.org/phonebook.html?uid=janhoy +links: + - name: SOLR-18165 + url: https://issues.apache.org/jira/browse/SOLR-18165 diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java index 9ca9b377cb2e..0899d20086f1 100644 --- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java +++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java @@ -809,7 +809,7 @@ private void loadInternal() { caffeineCache.initializeMetrics( solrMetricsContext, Attributes.builder().put(NAME_ATTR, cacheName).build(), - "solr_node_cache"); + "solr.node.cache"); } m.put(cacheName, c); } @@ -952,7 +952,7 @@ private void loadInternal() { ExecutorUtil.newMDCAwareFixedThreadPool( cfg.getCoreLoadThreadCount(isZooKeeperAware()), new SolrNamedThreadFactory("coreLoadExecutor")), - "solr_node_executor", + "solr.node.executor", "coreLoadExecutor", SolrInfoBean.Category.CONTAINER); diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java index 93699357426b..9bcea6a89f8f 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java @@ -1340,26 +1340,26 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri newSearcherCounter = new AttributedLongCounter( parentContext.longCounter( - "solr_core_searcher_new", "Total number of new searchers opened"), + "solr.core.searcher.new", "Total number of new searchers opened"), baseSearcherAttributes); newSearcherMaxReachedCounter = new AttributedLongCounter( parentContext.longCounter( - "solr_core_searcher_warming_max", + "solr.core.searcher.warming.max", "Total number of maximum concurrent warming searchers reached"), baseSearcherAttributes); newSearcherOtherErrorsCounter = new AttributedLongCounter( parentContext.longCounter( - "solr_core_searcher_errors", "Total number of searcher errors"), + "solr.core.searcher.errors", "Total number of searcher errors"), baseSearcherAttributes); newSearcherTimer = new AttributedLongTimer( parentContext.longHistogram( - "solr_core_indexsearcher_open_time", + "solr.core.indexsearcher.open.time", "Time to open new searchers", OtelUnit.MILLISECONDS), baseSearcherAttributes); @@ -1367,14 +1367,14 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri newSearcherWarmupTimer = new AttributedLongTimer( parentContext.longHistogram( - "solr_core_indexsearcher_open_warmup_time", + "solr.core.indexsearcher.open.warmup.time", "Time to warmup new searchers", OtelUnit.MILLISECONDS), baseSearcherAttributes); observables.add( parentContext.observableLongGauge( - "solr_core_ref_count", + "solr.core.ref_count", "The current number of active references to a Solr core", (observableLongMeasurement -> { observableLongMeasurement.record(getOpenCount(), baseGaugeCoreAttributes); @@ -1382,7 +1382,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri observables.add( parentContext.observableDoubleGauge( - "solr_core_disk_space", + "solr.core.disk.space", "Solr core disk space metrics", (observableDoubleMeasurement -> { @@ -1417,7 +1417,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri observables.add( parentContext.observableDoubleGauge( - "solr_core_index_size", + "solr.core.index.size", "Index size for a Solr core", (observableDoubleMeasurement -> { if (!isClosed()) @@ -1427,7 +1427,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri OtelUnit.MEGABYTES)); parentContext.observableLongGauge( - "solr_core_segments", + "solr.core.segments", "Number of segments in a Solr core", (observableLongMeasurement -> { if (isReady()) @@ -1437,7 +1437,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri if (coreContainer.isZooKeeperAware()) observables.add( parentContext.observableLongGauge( - "solr_core_is_leader", + "solr.core.is_leader", "Indicates whether this Solr core is currently the leader", (observableLongMeasurement -> { observableLongMeasurement.record( diff --git a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java index 8b367cf8c300..1e4e73ae2be0 100644 --- a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java @@ -882,55 +882,55 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri ObservableDoubleMeasurement indexSizeMetric = solrMetricsContext.doubleGaugeMeasurement( - "solr_core_replication_index_size", + "solr.core.replication.index.size", "Size of the index in megabytes", OtelUnit.MEGABYTES); ObservableLongMeasurement indexVersionMetric = solrMetricsContext.longGaugeMeasurement( - "solr_core_replication_index_version", "Current index version"); + "solr.core.replication.index.version", "Current index version"); ObservableLongMeasurement indexGenerationMetric = solrMetricsContext.longGaugeMeasurement( - "solr_core_replication_index_generation", "Current index generation"); + "solr.core.replication.index.generation", "Current index generation"); ObservableLongMeasurement isLeaderMetric = solrMetricsContext.longGaugeMeasurement( - "solr_core_replication_is_leader", "Whether this node is a leader (1) or not (0)"); + "solr.core.replication.is_leader", "Whether this node is a leader (1) or not (0)"); ObservableLongMeasurement isFollowerMetric = solrMetricsContext.longGaugeMeasurement( - "solr_core_replication_is_follower", "Whether this node is a follower (1) or not (0)"); + "solr.core.replication.is_follower", "Whether this node is a follower (1) or not (0)"); ObservableLongMeasurement replicationEnabledMetric = solrMetricsContext.longGaugeMeasurement( - "solr_core_replication_is_enabled", "Whether replication is enabled (1) or not (0)"); + "solr.core.replication.is_enabled", "Whether replication is enabled (1) or not (0)"); ObservableLongMeasurement isPollingDisabledMetric = solrMetricsContext.longGaugeMeasurement( - "solr_core_replication_is_polling_disabled", + "solr.core.replication.is_polling.disabled", "Whether polling is disabled (1) or not (0)"); ObservableLongMeasurement isReplicatingMetric = solrMetricsContext.longGaugeMeasurement( - "solr_core_replication_is_replicating", + "solr.core.replication.is_replicating", "Whether replication is in progress (1) or not (0)"); ObservableLongMeasurement timeElapsedMetric = solrMetricsContext.longGaugeMeasurement( - "solr_core_replication_time_elapsed", + "solr.core.replication.time.elapsed", "Time elapsed during replication in seconds", OtelUnit.SECONDS); ObservableLongMeasurement bytesDownloadedMetric = solrMetricsContext.longGaugeMeasurement( - "solr_core_replication_downloaded_size", + "solr.core.replication.downloaded.size", "Total bytes downloaded during replication", OtelUnit.BYTES); ObservableLongMeasurement downloadSpeedMetric = solrMetricsContext.longGaugeMeasurement( - "solr_core_replication_download_speed", "Download speed in bytes per second"); + "solr.core.replication.download.speed", "Download speed in bytes per second"); metricsCallback = solrMetricsContext.batchCallback( diff --git a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java index b76a9778d115..e70e81ad654e 100644 --- a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java +++ b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java @@ -198,27 +198,27 @@ public HandlerMetrics( requests = factory.attributedLongCounter( - "solr_core_requests", "HTTP Solr requests", Attributes.empty()); + "solr.core.requests", "HTTP Solr requests", Attributes.empty()); numServerErrors = factory.attributedLongCounter( - "solr_core_requests_errors", + "solr.core.requests.errors", "HTTP Solr request errors", Attributes.of(SOURCE_ATTR, "server")); numClientErrors = factory.attributedLongCounter( - "solr_core_requests_errors", + "solr.core.requests.errors", "HTTP Solr request errors", Attributes.of(SOURCE_ATTR, "client")); numTimeouts = factory.attributedLongCounter( - "solr_core_requests_timeout", "HTTP Solr request timeouts", Attributes.empty()); + "solr.core.requests.timeout", "HTTP Solr request timeouts", Attributes.empty()); requestTimes = factory.attributedLongTimer( - "solr_core_requests_times", + "solr.core.requests.times", "HTTP Solr request times", OtelUnit.MILLISECONDS, Attributes.empty()); diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java index c6d9474e0de8..9fe8d9403c4e 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java @@ -132,14 +132,14 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri coreAdminAsyncTracker.standardExecutor = solrMetricsContext.instrumentedExecutorService( coreAdminAsyncTracker.standardExecutor, - "solr_node_executor", + "solr.node.executor", "asyncCoreAdminExecutor", getCategory()); coreAdminAsyncTracker.expensiveExecutor = solrMetricsContext.instrumentedExecutorService( coreAdminAsyncTracker.expensiveExecutor, - "solr_node_executor", + "solr.node.executor", "asyncCoreExpensiveAdminExecutor", getCategory()); } diff --git a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java index a8e9513e5875..6dc30f47b9bb 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java +++ b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java @@ -439,6 +439,6 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri httpListenerFactory.initializeMetrics(solrMetricsContext, Attributes.empty()); commExecutor = solrMetricsContext.instrumentedExecutorService( - commExecutor, "solr_core_executor", "httpShardExecutor", SolrInfoBean.Category.QUERY); + commExecutor, "solr.core.executor", "httpShardExecutor", SolrInfoBean.Category.QUERY); } } diff --git a/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java b/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java index 5a82e1088b05..27e2f838a8c5 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java +++ b/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java @@ -392,7 +392,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri attributes.toBuilder().put(CATEGORY_ATTR, getCategory().toString()).build(); this.toClose = this.solrMetricsContext.observableLongGauge( - "solr_core_suggester_total_size", + "solr.core.suggester.total.size", "Total memory size in bytes of all suggester", (observableLongMeasurement) -> { observableLongMeasurement.record(ramBytesUsed(), suggesterAttributes); diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/FilterablePrometheusMetricReader.java b/solr/core/src/java/org/apache/solr/metrics/otel/FilterablePrometheusMetricReader.java index 5664ff047b15..6461b3bb52a8 100644 --- a/solr/core/src/java/org/apache/solr/metrics/otel/FilterablePrometheusMetricReader.java +++ b/solr/core/src/java/org/apache/solr/metrics/otel/FilterablePrometheusMetricReader.java @@ -65,8 +65,9 @@ public MetricSnapshots collect( return super.collect(); } - // Prometheus appends a suffix to the metrics depending on the metric type. We need to sanitize - // the suffix off if they filter by Prometheus name instead of OTEL name. + // Users may filter by Prometheus-format names (e.g. "solr_core_requests") or with a + // Prometheus type suffix (e.g. "solr_core_requests_total"). Strip any such suffix so we can + // compare against the Prometheus base name returned by getMetadata().getPrometheusName(). Set sanitizedNames = includedNames.stream() .map( @@ -84,7 +85,18 @@ public MetricSnapshots collect( if (sanitizedNames.isEmpty()) { snapshotsToFilter = super.collect(); } else { - snapshotsToFilter = super.collect(sanitizedNames::contains); + // We collect all metrics and filter by Prometheus name rather than using + // super.collect(Predicate) which matches on OTel internal names. This avoids a mismatch + // when OTel names use dot-separators (e.g. "solr.core.requests") but users filter by the + // Prometheus underscore-format name they see in the output (e.g. "solr_core_requests"). + MetricSnapshots all = super.collect(); + MetricSnapshots.Builder nameFiltered = MetricSnapshots.builder(); + for (MetricSnapshot snapshot : all) { + if (sanitizedNames.contains(snapshot.getMetadata().getPrometheusName())) { + nameFiltered.metricSnapshot(snapshot); + } + } + snapshotsToFilter = nameFiltered.build(); } // Return named filtered snapshots if not label filters provided diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedInstrumentFactory.java b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedInstrumentFactory.java index b4cd5cd514fe..ceb982bf80a6 100644 --- a/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedInstrumentFactory.java +++ b/solr/core/src/java/org/apache/solr/metrics/otel/instruments/AttributedInstrumentFactory.java @@ -132,7 +132,7 @@ public AttributedLongTimer attributedLongTimer( /** Replace core metric name prefix to node prefix */ private String toNodeMetricName(String coreMetricName) { - return coreMetricName.replace("solr_core", "solr_node"); + return coreMetricName.replace("solr.core", "solr.node"); } /** Filter out core attributes and keep all others for node-level metrics */ diff --git a/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java b/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java index fb8d92120a2c..10abe1918b0a 100644 --- a/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java +++ b/solr/core/src/java/org/apache/solr/search/SolrFieldCacheBean.java @@ -60,10 +60,10 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri this.solrMetricsContext = parentContext; var solrCacheStats = solrMetricsContext.longGaugeMeasurement( - "solr_core_field_cache_entries", "Number of field cache entries"); + "solr.core.field_cache.entries", "Number of field cache entries"); var solrCacheSize = solrMetricsContext.longGaugeMeasurement( - "solr_core_field_cache_size", "Size of field cache in bytes", OtelUnit.BYTES); + "solr.core.field_cache.size", "Size of field cache in bytes", OtelUnit.BYTES); this.toClose = solrMetricsContext.batchCallback( () -> { diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java index 862b6a22ac41..39f79872ba7f 100644 --- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java +++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java @@ -612,7 +612,7 @@ public void register() { caffeineCache.initializeMetrics( solrMetricsContext, core.getCoreAttributes().toBuilder().put(NAME_ATTR, cache.name()).build(), - "solr_core_indexsearcher_cache"); + "solr.core.indexsearcher.cache"); } } initializeMetrics(solrMetricsContext, core.getCoreAttributes()); @@ -2637,14 +2637,14 @@ public void initializeMetrics(SolrMetricsContext solrMetricsContext, Attributes warmupTimer = new AttributedLongTimer( solrMetricsContext.longHistogram( - "solr_core_indexsearcher_warmup_time", + "solr.core.indexsearcher.warmup.time", "Searcher warmup time (ms)", OtelUnit.MILLISECONDS), baseAttributes); toClose.add( solrMetricsContext.observableLongCounter( - "solr_core_indexsearcher_live_docs_cache", + "solr.core.indexsearcher.live_docs.cache", "LiveDocs cache metrics", obs -> { obs.record( @@ -2660,7 +2660,7 @@ public void initializeMetrics(SolrMetricsContext solrMetricsContext, Attributes // reader stats (numeric) toClose.add( solrMetricsContext.observableLongGauge( - "solr_core_indexsearcher_index_num_docs", + "solr.core.indexsearcher.index.num.docs", "Number of live docs in the index", obs -> { try { @@ -2672,7 +2672,7 @@ public void initializeMetrics(SolrMetricsContext solrMetricsContext, Attributes toClose.add( solrMetricsContext.observableLongGauge( - "solr_core_indexsearcher_index_docs", + "solr.core.indexsearcher.index.docs", "Total number of docs in the index (including deletions)", obs -> { try { @@ -2683,7 +2683,7 @@ public void initializeMetrics(SolrMetricsContext solrMetricsContext, Attributes // indexVersion (numeric) toClose.add( solrMetricsContext.observableLongGauge( - "solr_core_indexsearcher_index_version", + "solr.core.indexsearcher.index.version", "Lucene index version", obs -> { try { @@ -2694,7 +2694,7 @@ public void initializeMetrics(SolrMetricsContext solrMetricsContext, Attributes // size of the currently opened commit toClose.add( solrMetricsContext.observableDoubleGauge( - "solr_core_indexsearcher_index_commit_size", + "solr.core.indexsearcher.index.commit.size", "Size of the current index commit (megabytes)", obs -> { try { diff --git a/solr/core/src/java/org/apache/solr/search/stats/StatsCache.java b/solr/core/src/java/org/apache/solr/search/stats/StatsCache.java index e79051449de0..5c4570faa9c6 100644 --- a/solr/core/src/java/org/apache/solr/search/stats/StatsCache.java +++ b/solr/core/src/java/org/apache/solr/search/stats/StatsCache.java @@ -336,7 +336,7 @@ public void initializeMetrics(SolrMetricsContext solrMetricsContext, Attributes .build(); this.toClose = solrMetricsContext.observableLongGauge( - "solr_core_indexsearcher_termstats_cache", + "solr.core.indexsearcher.termstats.cache", "Operation counts for the searcher term statistics cache, reported per operation type", obs -> { var cacheMetrics = getCacheMetrics(); diff --git a/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java b/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java index 373a9289bc90..fc7476a4c759 100644 --- a/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java +++ b/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java @@ -246,102 +246,102 @@ private void createMetrics(Attributes baseAttributes, boolean aggregateToNodeReg addCommandsCumulative = factory.attributedLongUpDownCounter( - "solr_core_update_cumulative_ops", + "solr.core.update.cumulative.ops", "Cumulative number of update commands processed. Cumulative can decrease from rollback command", Attributes.of(OPERATION_ATTR, "adds")); deleteByIdCommandsCumulative = factory.attributedLongUpDownCounter( - "solr_core_update_cumulative_ops", + "solr.core.update.cumulative.ops", "Cumulative number of update commands processed. Cumulative can decrease from rollback command", Attributes.of(OPERATION_ATTR, "deletes_by_id")); deleteByQueryCommandsCumulative = factory.attributedLongUpDownCounter( - "solr_core_update_cumulative_ops", + "solr.core.update.cumulative.ops", "Cumulative number of update commands processed. Cumulative can decrease from rollback command", Attributes.of(OPERATION_ATTR, "deletes_by_query")); commitCommands = factory.attributedLongCounter( - "solr_core_update_commit_ops", + "solr.core.update.commit.ops", "Total number of commit operations", Attributes.of(OPERATION_ATTR, "commits")); optimizeCommands = factory.attributedLongCounter( - "solr_core_update_commit_ops", + "solr.core.update.commit.ops", "Total number of commit operations", Attributes.of(OPERATION_ATTR, "optimize")); mergeIndexesCommands = factory.attributedLongCounter( - "solr_core_update_commit_ops", + "solr.core.update.commit.ops", "Total number of commit operations", Attributes.of(OPERATION_ATTR, "merge_indexes")); expungeDeleteCommands = factory.attributedLongCounter( - "solr_core_update_commit_ops", + "solr.core.update.commit.ops", "Total number of commit operations", Attributes.of(OPERATION_ATTR, "expunge_deletes")); rollbackCommands = factory.attributedLongCounter( - "solr_core_update_maintenance_ops", + "solr.core.update.maintenance.ops", "Total number of maintenance operations", Attributes.of(OPERATION_ATTR, "rollback")); splitCommands = factory.attributedLongCounter( - "solr_core_update_maintenance_ops", + "solr.core.update.maintenance.ops", "Total number of maintenance operations", Attributes.of(OPERATION_ATTR, "split")); numErrorsCumulative = factory.attributedLongCounter( - "solr_core_update_errors", "Total number of update errors", Attributes.empty()); + "solr.core.update.errors", "Total number of update errors", Attributes.empty()); submittedAdds = factory.attributedLongCounter( - "solr_core_update_submitted_ops", + "solr.core.update.submitted.ops", "Total number of submitted update operations", Attributes.of(OPERATION_ATTR, "adds")); submittedDeleteById = factory.attributedLongCounter( - "solr_core_update_submitted_ops", + "solr.core.update.submitted.ops", "Total number of submitted update operations", Attributes.of(OPERATION_ATTR, "deletes_by_id")); submittedDeleteByQuery = factory.attributedLongCounter( - "solr_core_update_submitted_ops", + "solr.core.update.submitted.ops", "Total number of submitted update operations", Attributes.of(OPERATION_ATTR, "deletes_by_query")); committedAdds = factory.attributedLongCounter( - "solr_core_update_committed_ops", + "solr.core.update.committed.ops", "Total number of committed update operations", Attributes.of(OPERATION_ATTR, "adds")); committedDeleteById = factory.attributedLongCounter( - "solr_core_update_committed_ops", + "solr.core.update.committed.ops", "Total number of committed update operations", Attributes.of(OPERATION_ATTR, "deletes_by_id")); committedDeleteByQuery = factory.attributedLongCounter( - "solr_core_update_committed_ops", + "solr.core.update.committed.ops", "Total number of committed update operations", Attributes.of(OPERATION_ATTR, "deletes_by_query")); // Create observable metrics only for core registry observables.add( solrMetricsContext.observableLongCounter( - "solr_core_update_auto_commits", + "solr.core.update.auto_commits", "Current number of auto commits", (observableLongMeasurement -> { observableLongMeasurement.record( @@ -354,7 +354,7 @@ private void createMetrics(Attributes baseAttributes, boolean aggregateToNodeReg observables.add( solrMetricsContext.observableLongGauge( - "solr_core_update_commit_stats", + "solr.core.update.commit.stats", "Metrics around commits", (observableLongMeasurement -> { if (commitTracker.getDocsUpperBound() > 0) { @@ -386,7 +386,7 @@ private void createMetrics(Attributes baseAttributes, boolean aggregateToNodeReg observables.add( solrMetricsContext.observableLongGauge( - "solr_core_update_docs_pending_commit", + "solr.core.update.docs.pending_commit", "Current number of documents pending commit. Value is reset to 0 on commit.", (observableLongMeasurement) -> { observableLongMeasurement.record( diff --git a/solr/core/src/java/org/apache/solr/update/PeerSync.java b/solr/core/src/java/org/apache/solr/update/PeerSync.java index 5034797956d7..7d69b4de9c61 100644 --- a/solr/core/src/java/org/apache/solr/update/PeerSync.java +++ b/solr/core/src/java/org/apache/solr/update/PeerSync.java @@ -154,17 +154,17 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri syncErrors = new AttributedLongCounter( solrMetricsContext.longCounter( - "solr_core_peer_sync_errors", "Total number of sync errors with peer"), + "solr.core.peer_sync.errors", "Total number of sync errors with peer"), baseAttributes); syncSkipped = new AttributedLongCounter( solrMetricsContext.longCounter( - "solr_core_peer_sync_skipped", "Total number of skipped syncs with peer"), + "solr.core.peer_sync.skipped", "Total number of skipped syncs with peer"), baseAttributes); syncTime = new AttributedLongTimer( solrMetricsContext.longHistogram( - "solr_core_peer_sync_time", "Peer sync times", OtelUnit.MILLISECONDS), + "solr.core.peer_sync.time", "Peer sync times", OtelUnit.MILLISECONDS), baseAttributes); } diff --git a/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java b/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java index 00097cb981d5..272e610718b9 100644 --- a/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java +++ b/solr/core/src/java/org/apache/solr/update/PeerSyncWithLeader.java @@ -109,17 +109,17 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri syncErrors = new AttributedLongCounter( solrMetricsContext.longCounter( - "solr_core_sync_with_leader_errors", "Total number of sync errors with leader"), + "solr.core.sync_with_leader.errors", "Total number of sync errors with leader"), baseAttributes); syncSkipped = new AttributedLongCounter( solrMetricsContext.longCounter( - "solr_core_sync_with_leader_skipped", "Total number of skipped syncs with leader"), + "solr.core.sync_with_leader.skipped", "Total number of skipped syncs with leader"), baseAttributes); syncTime = new AttributedLongTimer( solrMetricsContext.longHistogram( - "solr_core_sync_with_leader_time", "leader sync times", OtelUnit.MILLISECONDS), + "solr.core.sync_with_leader.time", "leader sync times", OtelUnit.MILLISECONDS), baseAttributes); } diff --git a/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java b/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java index 2f028f08587f..18439f76a56f 100644 --- a/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java +++ b/solr/core/src/java/org/apache/solr/update/SolrIndexWriter.java @@ -258,22 +258,22 @@ private void initMetrics(final SolrCore core) { mergesCounter = solrMetricsContext.longCounter( - "solr_core_indexwriter_merges", "Number of total merge operations, " + descSuffix); + "solr.core.indexwriter.merges", "Number of total merge operations, " + descSuffix); mergeDocsCounter = solrMetricsContext.longCounter( - "solr_core_indexwriter_merge_docs", + "solr.core.indexwriter.merge.docs", "Number of documents involved in merge, " + descSuffix); mergeSegmentsCounter = solrMetricsContext.longCounter( - "solr_core_indexwriter_merge_segments", + "solr.core.indexwriter.merge.segments", "Number of segments involved in merge, " + descSuffix); flushesCounter = solrMetricsContext.longCounter( - "solr_core_indexwriter_flushes", "Number of flush to disk operations triggered"); + "solr.core.indexwriter.flushes", "Number of flush to disk operations triggered"); var mergesTimerBase = solrMetricsContext.longHistogram( - "solr_core_indexwriter_merge_time", + "solr.core.indexwriter.merge.time", "Time spent merging segments, " + descSuffix, OtelUnit.MILLISECONDS); majorMergeTimer = diff --git a/solr/core/src/java/org/apache/solr/update/UpdateLog.java b/solr/core/src/java/org/apache/solr/update/UpdateLog.java index cf026c95c2ef..0d7466e8532c 100644 --- a/solr/core/src/java/org/apache/solr/update/UpdateLog.java +++ b/solr/core/src/java/org/apache/solr/update/UpdateLog.java @@ -637,14 +637,14 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri observables.add( solrMetricsContext.observableLongGauge( - "solr_core_update_log_buffered_ops", + "solr.core.update_log.buffered.ops", "The current number of buffered operations", (observableLongMeasurement -> observableLongMeasurement.record(computeBufferedOps(), baseAttributes)))); observables.add( solrMetricsContext.observableLongGauge( - "solr_core_update_log_replay_logs_remaining", + "solr.core.update_log.replay.logs_remaining", "The current number of tlogs remaining to be replayed", (observableLongMeasurement -> { observableLongMeasurement.record(logs.size(), baseAttributes); @@ -652,7 +652,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri observables.add( solrMetricsContext.observableLongGauge( - "solr_core_update_log_size_remaining", + "solr.core.update_log.size_remaining", "The total size in bytes of all tlogs remaining to be replayed", (observableLongMeasurement -> { observableLongMeasurement.record(getTotalLogsSize(), baseAttributes); @@ -663,7 +663,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri observables.add( solrMetricsContext.observableLongGauge( - "solr_core_update_log_state", + "solr.core.update_log.state", "The current state of the update log. Replaying (0), buffering (1), applying buffered (2), active (3)", (observableLongMeasurement -> { observableLongMeasurement.record(state.getValue(), baseAttributes); @@ -672,20 +672,20 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri applyingBufferedOpsCounter = new AttributedLongCounter( solrMetricsContext.longCounter( - "solr_core_update_log_applied_buffered_ops", + "solr.core.update_log.applied_buffered_ops", "Total number of buffered operations applied"), baseAttributes); replayOpsCounter = new AttributedLongCounter( solrMetricsContext.longCounter( - "solr_core_update_log_replay_ops", "Total number of log replay operations"), + "solr.core.update_log.replay_ops", "Total number of log replay operations"), baseAttributes); copyOverOldUpdatesCounter = new AttributedLongCounter( solrMetricsContext.longCounter( - "solr_core_update_log_old_updates_copied", + "solr.core.update_log.old_updates_copied", "Total number of updates copied from previous tlog or last tlog to a new tlog"), baseAttributes); } diff --git a/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java b/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java index 8abb54c066d0..ed0f4f4e850a 100644 --- a/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java +++ b/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java @@ -167,10 +167,10 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri trackHttpSolrMetrics.initializeMetrics(solrMetricsContext, Attributes.empty()); updateExecutor = solrMetricsContext.instrumentedExecutorService( - updateExecutor, "solr_core_executor", "updateOnlyExecutor", getCategory()); + updateExecutor, "solr.core.executor", "updateOnlyExecutor", getCategory()); recoveryExecutor = solrMetricsContext.instrumentedExecutorService( - recoveryExecutor, "solr_core_executor", "recoveryExecutor", getCategory()); + recoveryExecutor, "solr.core.executor", "recoveryExecutor", getCategory()); } @Override diff --git a/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/update/processor/ProducerMetrics.java b/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/update/processor/ProducerMetrics.java index 73e52a62ff99..b456fd0d48ca 100644 --- a/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/update/processor/ProducerMetrics.java +++ b/solr/modules/cross-dc/src/java/org/apache/solr/crossdc/update/processor/ProducerMetrics.java @@ -47,36 +47,36 @@ public ProducerMetrics(SolrMetricsContext solrMetricsContext, SolrCore solrCore) var localProcessed = solrMetricsContext.longCounter( - "solr_core_crossdc_producer_local_processed", + "solr.core.crossdc.producer.local.processed", "The number of local documents processed (success or error)"); var localSubmitted = solrMetricsContext.longCounter( - "solr_core_crossdc_producer_submitted", + "solr.core.crossdc.producer.submitted", "The number of documents submitted to the Kafka topic (success or error)"); var localSubmittedAdd = solrMetricsContext.longCounter( - "solr_core_crossdc_producer_submitted_add", + "solr.core.crossdc.producer.submitted.add", "The number of add requests submitted to the Kafka topic (success or error)"); var localSubmittedDbi = solrMetricsContext.longCounter( - "solr_core_crossdc_producer_submitted_delete_by_id", + "solr.core.crossdc.producer.submitted.delete_by_id", "The number of Delete-By-Id requests submitted to the Kafka topic (success or error)"); var localSubmittedDbq = solrMetricsContext.longCounter( - "solr_core_crossdc_producer_submitted_delete_by_query", + "solr.core.crossdc.producer.submitted.delete_by_query", "The number of Delete-By-Query requests submitted to the Kafka topic (success or error)"); var localSubmittedCommit = solrMetricsContext.longCounter( - "solr_core_crossdc_producer_submitted_commit", + "solr.core.crossdc.producer.submitted.commit", "The number of standalone Commit requests submitted to the Kafka topic (success or error)"); var histogramDocSizes = solrMetricsContext.longHistogram( - "solr_core_crossdc_producer_document_size", + "solr.core.crossdc.producer.document_size", "Histogram of the processed document sizes processed", OtelUnit.BYTES); var tooLargeErrors = solrMetricsContext.longCounter( - "solr_core_crossdc_producer_doc_too_large_errors", + "solr.core.crossdc.producer.doc_too_large_errors", "The number of documents that were too large to send to the Kafka topic"); this.local = From c4a84b9a155190228451a74d397ef10efc014613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Tue, 17 Mar 2026 20:59:44 +0100 Subject: [PATCH 2/6] Additional underscore naming --- solr/core/src/java/org/apache/solr/core/SolrCore.java | 6 +++--- .../java/org/apache/solr/handler/ReplicationHandler.java | 8 ++++---- .../java/org/apache/solr/search/SolrIndexSearcher.java | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java index 9bcea6a89f8f..96544f6d1b7c 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java @@ -1346,7 +1346,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri newSearcherMaxReachedCounter = new AttributedLongCounter( parentContext.longCounter( - "solr.core.searcher.warming.max", + "solr.core.searcher.warming_max", "Total number of maximum concurrent warming searchers reached"), baseSearcherAttributes); @@ -1367,7 +1367,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri newSearcherWarmupTimer = new AttributedLongTimer( parentContext.longHistogram( - "solr.core.indexsearcher.open.warmup.time", + "solr.core.indexsearcher.open.warmup_time", "Time to warmup new searchers", OtelUnit.MILLISECONDS), baseSearcherAttributes); @@ -1382,7 +1382,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri observables.add( parentContext.observableDoubleGauge( - "solr.core.disk.space", + "solr.core.disk_space", "Solr core disk space metrics", (observableDoubleMeasurement -> { diff --git a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java index 1e4e73ae2be0..3ec327aa3499 100644 --- a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java @@ -908,7 +908,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri ObservableLongMeasurement isPollingDisabledMetric = solrMetricsContext.longGaugeMeasurement( - "solr.core.replication.is_polling.disabled", + "solr.core.replication.is_polling_disabled", "Whether polling is disabled (1) or not (0)"); ObservableLongMeasurement isReplicatingMetric = @@ -918,19 +918,19 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri ObservableLongMeasurement timeElapsedMetric = solrMetricsContext.longGaugeMeasurement( - "solr.core.replication.time.elapsed", + "solr.core.replication.time_elapsed", "Time elapsed during replication in seconds", OtelUnit.SECONDS); ObservableLongMeasurement bytesDownloadedMetric = solrMetricsContext.longGaugeMeasurement( - "solr.core.replication.downloaded.size", + "solr.core.replication.downloaded_size", "Total bytes downloaded during replication", OtelUnit.BYTES); ObservableLongMeasurement downloadSpeedMetric = solrMetricsContext.longGaugeMeasurement( - "solr.core.replication.download.speed", "Download speed in bytes per second"); + "solr.core.replication.download_speed", "Download speed in bytes per second"); metricsCallback = solrMetricsContext.batchCallback( diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java index 39f79872ba7f..98fd4518f7e8 100644 --- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java +++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java @@ -2660,7 +2660,7 @@ public void initializeMetrics(SolrMetricsContext solrMetricsContext, Attributes // reader stats (numeric) toClose.add( solrMetricsContext.observableLongGauge( - "solr.core.indexsearcher.index.num.docs", + "solr.core.indexsearcher.index.num_docs", "Number of live docs in the index", obs -> { try { @@ -2694,7 +2694,7 @@ public void initializeMetrics(SolrMetricsContext solrMetricsContext, Attributes // size of the currently opened commit toClose.add( solrMetricsContext.observableDoubleGauge( - "solr.core.indexsearcher.index.commit.size", + "solr.core.indexsearcher.index.commit_size", "Size of the current index commit (megabytes)", obs -> { try { From da9052355174d5d59dd34664883443c1e9602d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Tue, 17 Mar 2026 21:13:36 +0100 Subject: [PATCH 3/6] Major changes adoc --- .../pages/major-changes-in-solr-10.adoc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc index 86420c2815ae..37cc1dd8cdea 100644 --- a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc +++ b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc @@ -284,3 +284,18 @@ Attention: * The `llm` module has been renamed to `language-models`. * The HNSW parameters `hnswMaxConnections` and `hnswBeamWidth` have been renamed to `hnswM` and `hnswEfConstruction`, respectively, so they must be updated accordingly in the schema.xml file. + +== Solr 10.1 + +=== OTLP Metric Names Changed to Dot-Separated Format + +*Breaking change for OTLP consumers.* + +Solr's metric names exported via OTLP now follow the https://opentelemetry.io/docs/specs/semconv/general/naming/[OpenTelemetry semantic convention] of using dot-separated names instead of the underscore-separated names used in Solr 10.0. + +For example, `solr_core_requests` is now `solr.core.requests`, and `solr_node_executor` is now `solr.node.executor`. + +*Prometheus output is unaffected.* The OTel Prometheus exporter automatically converts dots to underscores, so the `/admin/metrics?wt=prometheus` endpoint continues to produce the same metric names as before (e.g., `solr_core_requests_total`). + +*Workaround for OTLP consumers depending on the old names:* +Users who consume Solr metrics via OTLP and rely on the 10.0 underscore-format names can use metric renaming or transformation features in their OpenTelemetry Collector pipeline to convert the new dot-separated names back to the old format during the transition. From bf37dd15a67411a134c4300ba5aad28e152dcbba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Thu, 19 Mar 2026 22:36:48 +0100 Subject: [PATCH 4/6] solr.core.update_log.replay.ops Co-authored-by: Matthew Biscocho --- solr/core/src/java/org/apache/solr/update/UpdateLog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/core/src/java/org/apache/solr/update/UpdateLog.java b/solr/core/src/java/org/apache/solr/update/UpdateLog.java index 0d7466e8532c..6d3099b65094 100644 --- a/solr/core/src/java/org/apache/solr/update/UpdateLog.java +++ b/solr/core/src/java/org/apache/solr/update/UpdateLog.java @@ -679,7 +679,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri replayOpsCounter = new AttributedLongCounter( solrMetricsContext.longCounter( - "solr.core.update_log.replay_ops", "Total number of log replay operations"), + "solr.core.update_log.replay.ops", "Total number of log replay operations"), baseAttributes); copyOverOldUpdatesCounter = From 39e4166fcec8fd291161644be7d9cc7920223dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Fri, 20 Mar 2026 21:36:02 +0100 Subject: [PATCH 5/6] solr.core.indexsearcher.warmup_time Co-authored-by: Chan Chan --- .../core/src/java/org/apache/solr/search/SolrIndexSearcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java index 98fd4518f7e8..ba61bc85d834 100644 --- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java +++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java @@ -2637,7 +2637,7 @@ public void initializeMetrics(SolrMetricsContext solrMetricsContext, Attributes warmupTimer = new AttributedLongTimer( solrMetricsContext.longHistogram( - "solr.core.indexsearcher.warmup.time", + "solr.core.indexsearcher.warmup_time", "Searcher warmup time (ms)", OtelUnit.MILLISECONDS), baseAttributes); From 6f6df08ed1ce681b1260fb40fcb92fb2c5abd01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Fri, 20 Mar 2026 21:52:28 +0100 Subject: [PATCH 6/6] Declare OTEL metrics as BETA Deprecate solr.core.indexsearcher.open.warmup_time --- solr/core/src/java/org/apache/solr/core/SolrCore.java | 7 ++++++- .../upgrade-notes/pages/major-changes-in-solr-10.adoc | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java index 96544f6d1b7c..4d2627811a56 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java @@ -254,7 +254,12 @@ public class SolrCore implements SolrInfoBean, Closeable { private AttributedLongCounter newSearcherMaxReachedCounter; private AttributedLongCounter newSearcherOtherErrorsCounter; private AttributedLongTimer newSearcherTimer; + + @Deprecated( + since = "10.1", + forRemoval = true) // Duplicate of solr.core.indexsearcher.warmup_time - remove private AttributedLongTimer newSearcherWarmupTimer; + private List toClose; private final String metricTag = SolrMetricProducer.getUniqueMetricTag(this, null); @@ -1368,7 +1373,7 @@ public void initializeMetrics(SolrMetricsContext parentContext, Attributes attri new AttributedLongTimer( parentContext.longHistogram( "solr.core.indexsearcher.open.warmup_time", - "Time to warmup new searchers", + "DEPRECATED - Use solr.core.indexsearcher.warmup_time instead", OtelUnit.MILLISECONDS), baseSearcherAttributes); diff --git a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc index 37cc1dd8cdea..2cd29994b370 100644 --- a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc +++ b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc @@ -287,6 +287,10 @@ Attention: == Solr 10.1 +=== OTEL metrics classified as BETA + +The new OTEL metrics system, naming and dashboard should be treated as a BETA. We reserve the right to make breaking changes in this space in minor versions. + === OTLP Metric Names Changed to Dot-Separated Format *Breaking change for OTLP consumers.* @@ -299,3 +303,7 @@ For example, `solr_core_requests` is now `solr.core.requests`, and `solr_node_ex *Workaround for OTLP consumers depending on the old names:* Users who consume Solr metrics via OTLP and rely on the 10.0 underscore-format names can use metric renaming or transformation features in their OpenTelemetry Collector pipeline to convert the new dot-separated names back to the old format during the transition. + +=== Metric solr_core_indexsearcher_open_warmup_time is deprecated + +If you use `solr_core_indexsearcher_open_warmup_time` in a dashboard, it duplicates `solr_core_indexsearcher_warmup_time` and is deprecated for removal in a later 10.x release.