FELIX-6250 Ensure speaking thread name for HealthCheckMonitor
diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitor.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitor.java
index be2dc59..f2f991a 100644
--- a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitor.java
+++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitor.java
@@ -148,6 +148,8 @@
     private boolean sendEvents;
 
     private BundleContext bundleContext;
+    
+    private String monitorId;
 
     @Activate
     protected final void activate(BundleContext bundleContext, Config config, ComponentContext componentContext)
@@ -170,10 +172,10 @@
 
         this.intervalInSec = config.intervalInSec();
         this.cronExpression = config.cronExpression();
+        
+        this.monitorId = getMonitorId(componentContext.getProperties().get(ComponentConstants.COMPONENT_ID));
         if (StringUtils.isNotBlank(cronExpression)) {
-            monitorJob = cronJobFactory.createAsyncCronJob(this,
-                    "job-hc-monitor-" + componentContext.getProperties().get(ComponentConstants.COMPONENT_ID),
-                    "healthcheck-monitor", cronExpression);
+            monitorJob = cronJobFactory.createAsyncCronJob(this, monitorId, "healthcheck-monitor", cronExpression);
         } else if (intervalInSec > 0) {
             monitorJob = new AsyncIntervalJob(this, healthCheckExecutorThreadPool, intervalInSec);
         } else {
@@ -183,6 +185,10 @@
         LOG.info("HealthCheckMonitor active for tags {} and names {}", this.tags, this.names);
     }
 
+    private String getMonitorId(Object compId) {
+        return "hc-monitor-" + compId + '-' + String.join(",", tags)+(!names.isEmpty()?"-"+names.size()+"_names":"");
+    }
+
     @Override
     public String toString() {
         return "[HealthCheckMonitor tags=" + tags + "/names=" + names + ", intervalInSec=" + intervalInSec + "/cron="
@@ -198,29 +204,40 @@
     }
 
     public void run() {
+        String threadNameToRestore = Thread.currentThread().getName();
         try {
+            Thread.currentThread().setName(monitorId);
+            
             // run in tags/names in parallel
-            healthStates.parallelStream().forEach(healthState -> {
-                HealthCheckSelector selector = healthState.isTag ? HealthCheckSelector.tags(healthState.tagOrName)
-                        : HealthCheckSelector.names(healthState.tagOrName);
-
-                List<HealthCheckExecutionResult> executionResults = executor.execute(selector);
-
-                HealthCheckExecutionResult result = executionResults.size() == 1 ? executionResults.get(0)
-                        : new CombinedExecutionResult(executionResults, Result.Status.TEMPORARILY_UNAVAILABLE);
-
-                LOG.trace("Result of '{}' => {}", healthState.tagOrName, result.getHealthCheckResult().getStatus());
-
-                healthState.update(result);
-            });
+            healthStates.parallelStream().forEach(this::runFor);
 
             LOG.trace("HealthCheckMonitor: updated results for tags {} and names {}", this.tags, this.names);
         } catch (Exception e) {
             LOG.error("Exception HealthCheckMonitor run(): " + e, e);
+        } finally {
+            Thread.currentThread().setName(threadNameToRestore);
         }
-
     }
 
+    public void runFor(HealthState healthState) {
+        String threadNameToRestore = Thread.currentThread().getName();
+        try {
+            Thread.currentThread().setName(monitorId);
+            HealthCheckSelector selector = healthState.isTag ? HealthCheckSelector.tags(healthState.tagOrName)
+                    : HealthCheckSelector.names(healthState.tagOrName);
+            List<HealthCheckExecutionResult> executionResults = executor.execute(selector);
+
+            HealthCheckExecutionResult result = executionResults.size() == 1 ? executionResults.get(0)
+                    : new CombinedExecutionResult(executionResults, Result.Status.TEMPORARILY_UNAVAILABLE);
+            LOG.trace("Result of '{}' => {}", healthState.tagOrName, result.getHealthCheckResult().getStatus());
+
+            healthState.update(result);
+        } finally {
+            Thread.currentThread().setName(threadNameToRestore);
+        }
+    }
+
+    
     class HealthState {
 
         private String tagOrName;
diff --git a/healthcheck/core/src/test/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitorTest.java b/healthcheck/core/src/test/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitorTest.java
index dfc770f..7610015 100644
--- a/healthcheck/core/src/test/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitorTest.java
+++ b/healthcheck/core/src/test/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitorTest.java
@@ -30,6 +30,8 @@
 
 import java.lang.reflect.Method;
 import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Hashtable;
 import java.util.List;
 
 import org.apache.felix.hc.api.HealthCheck;
@@ -113,6 +115,10 @@
         when(config.tags()).thenReturn(new String[] { TEST_TAG });
         
         when(healthCheckMetadata.getServiceReference()).thenReturn(healthCheckServiceRef);
+        
+        Dictionary<String,Object> componentProps = new Hashtable<>();
+        componentProps.put(ComponentConstants.COMPONENT_ID, 7L);
+        when(componentContext.getProperties()).thenReturn(componentProps);
     }
 
     @Test