This is an automated email from the ASF dual-hosted git repository.

hossman pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/main by this push:
     new 2e5f89a  SOLR-15783: Prevent Logging MDC values from leaking between 
request threads, and set 'trace_id' in MDC as soon as it's available
2e5f89a is described below

commit 2e5f89a87296269cdf05ac30d178089832cfa5a7
Author: Chris Hostetter <[email protected]>
AuthorDate: Thu Nov 11 14:57:07 2021 -0700

    SOLR-15783: Prevent Logging MDC values from leaking between request 
threads, and set 'trace_id' in MDC as soon as it's available
---
 solr/CHANGES.txt                                   |  2 +
 .../java/org/apache/solr/logging/MDCSnapshot.java  | 58 ++++++++++++++++++++++
 .../java/org/apache/solr/servlet/HttpSolrCall.java |  4 --
 .../apache/solr/servlet/SolrDispatchFilter.java    | 11 +++-
 .../src/java/org/apache/solr/util/TestHarness.java | 12 +++--
 5 files changed, 79 insertions(+), 8 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index fd82e10..710bd8a 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -408,6 +408,8 @@ Bug Fixes
 
 * SOLR-10529: Solr UI Health Check enable/disable ping Button doesn't work 
(Oscar Wang via janhoy)
 
+* SOLR-15783: Prevent Logging MDC values from leaking between request threads, 
and set 'trace_id' in MDC as soon as it's available (hossman)
+
 ==================  8.11.0 ==================
 
 Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this 
release.
diff --git a/solr/core/src/java/org/apache/solr/logging/MDCSnapshot.java 
b/solr/core/src/java/org/apache/solr/logging/MDCSnapshot.java
new file mode 100644
index 0000000..040316d
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/logging/MDCSnapshot.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.logging;
+
+import java.io.Closeable;
+import java.util.Map;
+
+import org.slf4j.MDC;
+
+
+/**
+ * Takes a 'snapshot' of the current MDC context map which is restored on 
(auto) close.  
+ * This can be used to ensure that no MDC values set (or overridden) inside of 
call stack
+ * will "leak" beyond that call stack.
+ *
+ * <pre>
+ * try (var mdcSnapshot = MDCSnapshot.create()) {
+ *   assert null != mdcSnapshot; // prevent compiler warning
+ * 
+ *   // ... arbitrary calls to MDC methods
+ * }
+ * </pre>
+ * 
+ * @see org.slf4j.MDC#putCloseable
+ */
+public final class MDCSnapshot implements Closeable {
+
+  public static MDCSnapshot create() {
+    return new MDCSnapshot();
+  }
+  
+  private final Map<String,String> snapshot;
+  private MDCSnapshot() {
+    this.snapshot = MDC.getCopyOfContextMap();
+    assert null != snapshot;
+  }
+  
+  public void close() {
+    MDC.clear();
+    if (! snapshot.isEmpty()) { // common case optimization
+      MDC.setContextMap(snapshot);
+    }
+  }
+}
diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java 
b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
index 460e8d6..a414102 100644
--- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
+++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
@@ -90,7 +90,6 @@ import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.SolrConfig;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.handler.ContentStreamHandlerBase;
-import org.apache.solr.logging.MDCLoggingContext;
 import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequestBase;
@@ -504,9 +503,6 @@ public class HttpSolrCall {
    * This method processes the request.
    */
   public Action call() throws IOException {
-    MDCLoggingContext.reset();
-    MDCLoggingContext.setTracerId(getSpan().context().toTraceId()); // handles 
empty string
-    MDCLoggingContext.setNode(cores);
 
     if (cores == null) {
       sendError(503, "Server is shutting down or failed to initialize");
diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java 
b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
index 2816727..93a5897 100644
--- a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
+++ b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
@@ -80,6 +80,8 @@ import org.apache.solr.core.NodeConfig;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.core.SolrInfoBean;
 import org.apache.solr.core.SolrXmlConfig;
+import org.apache.solr.logging.MDCLoggingContext;
+import org.apache.solr.logging.MDCSnapshot;
 import org.apache.solr.metrics.AltBufferPoolMetricSet;
 import org.apache.solr.metrics.MetricsMap;
 import org.apache.solr.metrics.OperatingSystemMetricSet;
@@ -430,7 +432,13 @@ public class SolrDispatchFilter extends BaseSolrFilter {
   
   @Override
   public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException, ServletException {
-    doFilter(request, response, chain, false);
+    try (var mdcSnapshot = MDCSnapshot.create()) {
+      assert null != mdcSnapshot; // prevent compiler warning
+      MDCLoggingContext.reset();
+      MDCLoggingContext.setNode(cores);
+      
+      doFilter(request, response, chain, false);
+    }
   }
   
   public void doFilter(ServletRequest _request, ServletResponse _response, 
FilterChain chain, boolean retry) throws IOException, ServletException {
@@ -457,6 +465,7 @@ public class SolrDispatchFilter extends BaseSolrFilter {
     boolean accepted = false;
     try (var scope = tracer.scopeManager().activate(span)) {
       assert scope != null; // prevent javac warning about scope being unused
+      MDCLoggingContext.setTracerId(span.context().toTraceId()); // handles 
empty string
 
       if (cores == null || cores.isShutDown()) {
         try {
diff --git a/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java 
b/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java
index b4c4a31..67f7aeb 100644
--- a/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java
+++ b/solr/test-framework/src/java/org/apache/solr/util/TestHarness.java
@@ -45,6 +45,7 @@ import org.apache.solr.core.SolrConfig;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.core.SolrXmlConfig;
 import org.apache.solr.handler.UpdateRequestHandler;
+import org.apache.solr.logging.MDCSnapshot;
 import org.apache.solr.metrics.reporters.SolrJmxReporter;
 import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
@@ -278,7 +279,9 @@ public class TestHarness extends BaseTestHarness {
    * @return The XML response to the update
    */
   public String update(String xml) {
-    try (SolrCore core = getCoreInc()) {
+    try (var mdcSnap = MDCSnapshot.create();
+         SolrCore core = getCoreInc()) {
+      assert null != mdcSnap; // prevent compiler warning of unused var
       DirectSolrConnection connection = new DirectSolrConnection(core);
       SolrRequestHandler handler = core.getRequestHandler("/update");
       // prefer the handler mapped to /update, but use our generic backup 
handler
@@ -335,7 +338,8 @@ public class TestHarness extends BaseTestHarness {
    * @see LocalSolrQueryRequest
    */
   public String query(String handler, SolrQueryRequest req) throws Exception {
-    try {
+    try (var mdcSnap = MDCSnapshot.create()) {
+      assert null != mdcSnap; // prevent compiler warning of unused var
       SolrCore core = req.getCore();
       SolrQueryResponse rsp = new SolrQueryResponse();
       SolrRequestInfo.setRequestInfo(new SolrRequestInfo(req, rsp));
@@ -364,7 +368,9 @@ public class TestHarness extends BaseTestHarness {
   /** It is the users responsibility to close the request object when done 
with it.
    * This method does not set/clear SolrRequestInfo */
   public SolrQueryResponse queryAndResponse(String handler, SolrQueryRequest 
req) throws Exception {
-    try (SolrCore core = getCoreInc()) {
+    try (var mdcSnap = MDCSnapshot.create();
+         SolrCore core = getCoreInc()) {
+      assert null != mdcSnap; // prevent compiler warning of unused var
       SolrQueryResponse rsp = new SolrQueryResponse();
       core.execute(core.getRequestHandler(handler), req, rsp);
       if (rsp.getException() != null) {

Reply via email to