diff options
author | Lukasz Jarocki <lukasz.jarocki@sonarsource.com> | 2021-12-08 09:35:06 +0100 |
---|---|---|
committer | Lukasz Jarocki <lukasz.jarocki@sonarsource.com> | 2021-12-13 15:22:35 +0100 |
commit | d58a45b4b4fd196cccb8cbd1c9a479a3c783afe3 (patch) | |
tree | cfeb1df309b2eaaa2adeae63780472d0c0108172 /server/sonar-webserver-monitoring | |
parent | 601e7fbb0ca7cd323b69742e15cd016dac46cf62 (diff) | |
download | sonarqube-d58a45b4b4fd196cccb8cbd1c9a479a3c783afe3.tar.gz sonarqube-d58a45b4b4fd196cccb8cbd1c9a479a3c783afe3.zip |
SONAR-15769 added metrics for integration with devops platforms
Diffstat (limited to 'server/sonar-webserver-monitoring')
5 files changed, 532 insertions, 0 deletions
diff --git a/server/sonar-webserver-monitoring/build.gradle b/server/sonar-webserver-monitoring/build.gradle new file mode 100644 index 00000000000..854ae9a59e6 --- /dev/null +++ b/server/sonar-webserver-monitoring/build.gradle @@ -0,0 +1,13 @@ +description = 'SonarQube :: Monitoring' + +dependencies { + compile project(path: ':sonar-plugin-api', configuration: 'shadow') + compile project(':server:sonar-webserver-api') + compile project(':server:sonar-alm-client') + compile 'io.prometheus:simpleclient' + + testCompile 'junit:junit' + testCompile 'org.assertj:assertj-core' + testCompile 'org.mockito:mockito-core' + +} diff --git a/server/sonar-webserver-monitoring/src/main/java/org/sonar/server/monitoring/ServerMonitoringMetrics.java b/server/sonar-webserver-monitoring/src/main/java/org/sonar/server/monitoring/ServerMonitoringMetrics.java new file mode 100644 index 00000000000..1fb4c46adaa --- /dev/null +++ b/server/sonar-webserver-monitoring/src/main/java/org/sonar/server/monitoring/ServerMonitoringMetrics.java @@ -0,0 +1,86 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.monitoring; + +import io.prometheus.client.Gauge; +import org.sonar.api.server.ServerSide; + +@ServerSide +public class ServerMonitoringMetrics { + + private final Gauge githubConfigOk; + private final Gauge gitlabConfigOk; + private final Gauge bitbucketConfigOk; + private final Gauge azureConfigOk; + + public ServerMonitoringMetrics() { + githubConfigOk = Gauge.build() + .name("github_config_ok") + .help("Tells whether SonarQube instance has configured GitHub integration and its status is green. 0 for green, 1 otherwise .") + .register(); + + gitlabConfigOk = Gauge.build() + .name("gitlab_config_ok") + .help("Tells whether SonarQube instance has configured GitLab integration and its status is green. 0 for green, 1 otherwise .") + .register(); + + bitbucketConfigOk = Gauge.build() + .name("bitbucket_config_ok") + .help("Tells whether SonarQube instance has configured BitBucket integration and its status is green. 0 for green, 1 otherwise .") + .register(); + + azureConfigOk = Gauge.build() + .name("azure_config_ok") + .help("Tells whether SonarQube instance has configured Azure integration and its status is green. 0 for green, 1 otherwise .") + .register(); + } + + public void setGithubStatusToGreen() { + githubConfigOk.set(0); + } + + public void setGithubStatusToRed() { + githubConfigOk.set(1); + } + + public void setGitlabStatusToGreen() { + gitlabConfigOk.set(0); + } + + public void setGitlabStatusToRed() { + gitlabConfigOk.set(1); + } + + public void setAzureStatusToGreen() { + azureConfigOk.set(0); + } + + public void setAzureStatusToRed() { + azureConfigOk.set(1); + } + + public void setBitbucketStatusToGreen() { + bitbucketConfigOk.set(0); + } + + public void setBitbucketStatusToRed() { + bitbucketConfigOk.set(1); + } +} diff --git a/server/sonar-webserver-monitoring/src/main/java/org/sonar/server/monitoring/devops/DevOpsPlatformsMetricsCollector.java b/server/sonar-webserver-monitoring/src/main/java/org/sonar/server/monitoring/devops/DevOpsPlatformsMetricsCollector.java new file mode 100644 index 00000000000..fcee736a451 --- /dev/null +++ b/server/sonar-webserver-monitoring/src/main/java/org/sonar/server/monitoring/devops/DevOpsPlatformsMetricsCollector.java @@ -0,0 +1,166 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.monitoring.devops; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.stream.Collectors; +import org.picocontainer.Startable; +import org.sonar.alm.client.azure.AzureDevOpsValidator; +import org.sonar.alm.client.bitbucket.bitbucketcloud.BitbucketCloudValidator; +import org.sonar.alm.client.bitbucketserver.BitbucketServerSettingsValidator; +import org.sonar.alm.client.github.GithubGlobalSettingsValidator; +import org.sonar.alm.client.gitlab.GitlabGlobalSettingsValidator; +import org.sonar.api.config.Configuration; +import org.sonar.api.server.ServerSide; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.alm.setting.ALM; +import org.sonar.db.alm.setting.AlmSettingDto; +import org.sonar.server.monitoring.ServerMonitoringMetrics; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +@ServerSide +public class DevOpsPlatformsMetricsCollector implements Startable { + + private static final String DELAY_IN_MILISECONDS_PROPERTY = "sonar.server.monitoring.devops.initial.delay"; + private static final String PERIOD_IN_MILISECONDS_PROPERTY = "sonar.server.monitoring.devops.period"; + + private final Configuration config; + + private final BitbucketServerSettingsValidator bitbucketServerValidator; + private final GithubGlobalSettingsValidator githubValidator; + private final GitlabGlobalSettingsValidator gitlabValidator; + private final BitbucketCloudValidator bitbucketCloudValidator; + private final AzureDevOpsValidator azureDevOpsValidator; + + private final DbClient dbClient; + private final ServerMonitoringMetrics metrics; + + private ScheduledExecutorService scheduledExecutorService; + + public DevOpsPlatformsMetricsCollector(ServerMonitoringMetrics metrics, DbClient dbClient, + BitbucketServerSettingsValidator bitbucketServerValidator, GithubGlobalSettingsValidator githubValidator, + GitlabGlobalSettingsValidator gitlabValidator, BitbucketCloudValidator bitbucketCloudValidator, + AzureDevOpsValidator azureDevOpsValidator, Configuration config) { + this.bitbucketCloudValidator = bitbucketCloudValidator; + this.bitbucketServerValidator = bitbucketServerValidator; + this.githubValidator = githubValidator; + this.azureDevOpsValidator = azureDevOpsValidator; + this.gitlabValidator = gitlabValidator; + this.metrics = metrics; + this.dbClient = dbClient; + this.config = config; + } + + @Override + public void start() { + this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor( + new ThreadFactoryBuilder() + .setDaemon(true) + .setNameFormat(getClass().getCanonicalName() + "-thread-%d") + .build()); + long delayInMilliseconds = config.getLong(DELAY_IN_MILISECONDS_PROPERTY).orElse(10_000L); + long periodInMilliseconds = config.getLong(PERIOD_IN_MILISECONDS_PROPERTY).orElse(300_000L); + scheduledExecutorService.scheduleWithFixedDelay(createTask(), delayInMilliseconds, periodInMilliseconds, MILLISECONDS); + } + + @Override + public void stop() { + scheduledExecutorService.shutdown(); + } + + @VisibleForTesting + Runnable createTask() { + return () -> { + try (DbSession dbSession = dbClient.openSession(false)) { + List<AlmSettingDto> almSettingDtos = dbClient.almSettingDao().selectAll(dbSession); + validateBitbucket(getALMsDTOs(almSettingDtos, ALM.BITBUCKET)); + validateBitbucketCloud(getALMsDTOs(almSettingDtos, ALM.BITBUCKET_CLOUD)); + validateGithub(getALMsDTOs(almSettingDtos, ALM.GITHUB)); + validateGitlab(getALMsDTOs(almSettingDtos, ALM.GITLAB)); + validateAzure(getALMsDTOs(almSettingDtos, ALM.AZURE_DEVOPS)); + } + }; + } + + private static List<AlmSettingDto> getALMsDTOs(List<AlmSettingDto> almSettingDtos, ALM alm) { + return almSettingDtos.stream().filter(dto -> dto.getAlm() == alm).collect(Collectors.toList()); + } + + private void validateGithub(List<AlmSettingDto> almSettingDtos) { + try { + for (AlmSettingDto dto : almSettingDtos) { + githubValidator.validate(dto); + } + metrics.setGithubStatusToGreen(); + } catch (RuntimeException e) { + metrics.setGithubStatusToRed(); + } + } + + private void validateBitbucket(List<AlmSettingDto> almSettingDtos) { + try { + for (AlmSettingDto dto : almSettingDtos) { + bitbucketServerValidator.validate(dto); + } + metrics.setBitbucketStatusToGreen(); + } catch (Exception e) { + metrics.setBitbucketStatusToRed(); + } + } + + private void validateBitbucketCloud(List<AlmSettingDto> almSettingDtos) { + try { + for (AlmSettingDto dto : almSettingDtos) { + bitbucketCloudValidator.validate(dto); + } + metrics.setBitbucketStatusToGreen(); + } catch (Exception e) { + metrics.setBitbucketStatusToRed(); + } + } + + private void validateGitlab(List<AlmSettingDto> almSettingDtos) { + try { + for (AlmSettingDto dto : almSettingDtos) { + gitlabValidator.validate(dto); + } + metrics.setGitlabStatusToGreen(); + } catch (Exception e) { + metrics.setGitlabStatusToRed(); + } + } + + private void validateAzure(List<AlmSettingDto> almSettingDtos) { + try { + for (AlmSettingDto dto : almSettingDtos) { + azureDevOpsValidator.validate(dto); + } + metrics.setAzureStatusToGreen(); + } catch (Exception e) { + metrics.setAzureStatusToRed(); + } + } +} diff --git a/server/sonar-webserver-monitoring/src/test/java/org/sonar/server/monitoring/ServerMonitoringMetricsTest.java b/server/sonar-webserver-monitoring/src/test/java/org/sonar/server/monitoring/ServerMonitoringMetricsTest.java new file mode 100644 index 00000000000..0849f04a3e3 --- /dev/null +++ b/server/sonar-webserver-monitoring/src/test/java/org/sonar/server/monitoring/ServerMonitoringMetricsTest.java @@ -0,0 +1,82 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.monitoring; + +import io.prometheus.client.Collector; +import io.prometheus.client.CollectorRegistry; +import java.util.Collections; +import java.util.Enumeration; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +//@Execution(SAME_THREAD) for JUnit5 +public class ServerMonitoringMetricsTest { + + @Before + public void before() { + CollectorRegistry.defaultRegistry.clear(); + } + + @Test + public void creatingClassShouldAddMetricsToRegistry() { + assertThat(sizeOfDefaultRegistry()).isNotPositive(); + + new ServerMonitoringMetrics(); + + assertThat(sizeOfDefaultRegistry()).isPositive(); + } + + @Test + public void setters_setGreenStatusForMetricsInTheMetricsRegistry() { + ServerMonitoringMetrics metrics = new ServerMonitoringMetrics(); + + metrics.setGithubStatusToGreen(); + metrics.setGitlabStatusToGreen(); + metrics.setAzureStatusToGreen(); + metrics.setBitbucketStatusToGreen(); + + assertThat(CollectorRegistry.defaultRegistry.getSampleValue("github_config_ok")).isZero(); + assertThat(CollectorRegistry.defaultRegistry.getSampleValue("gitlab_config_ok")).isZero(); + assertThat(CollectorRegistry.defaultRegistry.getSampleValue("bitbucket_config_ok")).isZero(); + assertThat(CollectorRegistry.defaultRegistry.getSampleValue("azure_config_ok")).isZero(); + } + + @Test + public void setters_setRedStatusForMetricsInTheMetricsRegistry() { + ServerMonitoringMetrics metrics = new ServerMonitoringMetrics(); + + metrics.setGithubStatusToRed(); + metrics.setGitlabStatusToRed(); + metrics.setAzureStatusToRed(); + metrics.setBitbucketStatusToRed(); + + assertThat(CollectorRegistry.defaultRegistry.getSampleValue("github_config_ok")).isEqualTo(1); + assertThat(CollectorRegistry.defaultRegistry.getSampleValue("gitlab_config_ok")).isEqualTo(1); + assertThat(CollectorRegistry.defaultRegistry.getSampleValue("bitbucket_config_ok")).isEqualTo(1); + assertThat(CollectorRegistry.defaultRegistry.getSampleValue("azure_config_ok")).isEqualTo(1); + } + + private int sizeOfDefaultRegistry() { + Enumeration<Collector.MetricFamilySamples> metrics = CollectorRegistry.defaultRegistry.metricFamilySamples(); + return Collections.list(metrics).size(); + } +} diff --git a/server/sonar-webserver-monitoring/src/test/java/org/sonar/server/monitoring/devops/DevOpsPlatformsMetricsCollectorTest.java b/server/sonar-webserver-monitoring/src/test/java/org/sonar/server/monitoring/devops/DevOpsPlatformsMetricsCollectorTest.java new file mode 100644 index 00000000000..d464825e9ee --- /dev/null +++ b/server/sonar-webserver-monitoring/src/test/java/org/sonar/server/monitoring/devops/DevOpsPlatformsMetricsCollectorTest.java @@ -0,0 +1,185 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.monitoring.devops; + +import org.sonar.api.config.Configuration; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import org.junit.Before; +import org.junit.Test; +import org.sonar.alm.client.azure.AzureDevOpsValidator; +import org.sonar.alm.client.bitbucket.bitbucketcloud.BitbucketCloudValidator; +import org.sonar.alm.client.bitbucketserver.BitbucketServerSettingsValidator; +import org.sonar.alm.client.github.GithubGlobalSettingsValidator; +import org.sonar.alm.client.gitlab.GitlabGlobalSettingsValidator; +import org.sonar.db.DbClient; +import org.sonar.db.alm.setting.ALM; +import org.sonar.db.alm.setting.AlmSettingDao; +import org.sonar.db.alm.setting.AlmSettingDto; +import org.sonar.server.monitoring.ServerMonitoringMetrics; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +public class DevOpsPlatformsMetricsCollectorTest { + + private final ServerMonitoringMetrics serverMonitoringMetrics = mock(ServerMonitoringMetrics.class); + private final DbClient dbClient = mock(DbClient.class); + private final BitbucketServerSettingsValidator bitbucketServerValidator = mock(BitbucketServerSettingsValidator.class); + private final GithubGlobalSettingsValidator githubValidator = mock(GithubGlobalSettingsValidator.class); + private final GitlabGlobalSettingsValidator gitlabValidator = mock(GitlabGlobalSettingsValidator.class); + private final BitbucketCloudValidator bitbucketCloudValidator = mock(BitbucketCloudValidator.class); + private final AzureDevOpsValidator azureDevOpsValidator = mock(AzureDevOpsValidator.class); + private final Configuration config = mock(Configuration.class); + + private DevOpsPlatformsMetricsCollector collector; + + @Before + public void before() { + collector = new DevOpsPlatformsMetricsCollector(serverMonitoringMetrics, + dbClient, bitbucketServerValidator, githubValidator, gitlabValidator, bitbucketCloudValidator, + azureDevOpsValidator, config); + } + + @Test + public void start_startsNewDeamonThread() { + collector.start(); + + Optional<Thread> newDeamonThread = findNewDeamonThread(); + + assertThat(newDeamonThread).isPresent(); + assertThat(newDeamonThread.get().isDaemon()).isTrue(); + } + + @Test + public void createTask_givenOneConfigForEachALM_allValidatorsAreCalled() { + AlmSettingDao dao = mock(AlmSettingDao.class); + List<AlmSettingDto> almSettingDtos = createAlmSettingDtos(); + when(dao.selectAll(any())).thenReturn(almSettingDtos); + when(dbClient.almSettingDao()).thenReturn(dao); + + collector.createTask().run(); + + verify(bitbucketCloudValidator, times(1)).validate(findDto(ALM.BITBUCKET_CLOUD, almSettingDtos)); + verify(bitbucketServerValidator, times(1)).validate(findDto(ALM.BITBUCKET, almSettingDtos)); + verify(azureDevOpsValidator, times(1)).validate(findDto(ALM.AZURE_DEVOPS, almSettingDtos)); + verify(gitlabValidator, times(1)).validate(findDto(ALM.GITLAB, almSettingDtos)); + verify(githubValidator, times(1)).validate(findDto(ALM.GITHUB, almSettingDtos)); + } + + @Test + public void createTask_givenOnlyGitHubConfigured_validateOnlyGithub() { + AlmSettingDao dao = mock(AlmSettingDao.class); + AlmSettingDto githubDto = new AlmSettingDto(); + githubDto.setAlm(ALM.GITHUB); + when(dao.selectAll(any())).thenReturn(List.of(githubDto)); + when(dbClient.almSettingDao()).thenReturn(dao); + + collector.createTask().run(); + + verifyNoInteractions(bitbucketCloudValidator); + verifyNoInteractions(bitbucketServerValidator); + verifyNoInteractions(azureDevOpsValidator); + verifyNoInteractions(gitlabValidator); + + verify(githubValidator, times(1)).validate(githubDto); + } + + @Test + public void createTask_givenAllValidationsFailing_setAllMetricsStatusesToFalse() { + AlmSettingDao dao = mock(AlmSettingDao.class); + List<AlmSettingDto> almSettingDtos = createAlmSettingDtos(); + when(dao.selectAll(any())).thenReturn(almSettingDtos); + when(dbClient.almSettingDao()).thenReturn(dao); + + doThrow(new RuntimeException()).when(bitbucketCloudValidator).validate(any()); + doThrow(new RuntimeException()).when(bitbucketServerValidator).validate(any()); + doThrow(new RuntimeException()).when(azureDevOpsValidator).validate(any()); + doThrow(new RuntimeException()).when(gitlabValidator).validate(any()); + doThrow(new RuntimeException()).when(githubValidator).validate(any()); + + collector.createTask().run(); + + verify(serverMonitoringMetrics, times(2)).setBitbucketStatusToRed(); //2 validators for Bitbucket + verify(serverMonitoringMetrics, times(1)).setAzureStatusToRed(); + verify(serverMonitoringMetrics, times(1)).setGitlabStatusToRed(); + verify(serverMonitoringMetrics, times(1)).setGithubStatusToRed(); + } + + @Test + public void createTask_givenAllValidationsArePassing_setAllMetricsStatusesToTrue() { + AlmSettingDao dao = mock(AlmSettingDao.class); + List<AlmSettingDto> almSettingDtos = createAlmSettingDtos(); + when(dao.selectAll(any())).thenReturn(almSettingDtos); + when(dbClient.almSettingDao()).thenReturn(dao); + + collector.createTask().run(); + + verify(serverMonitoringMetrics, times(2)).setBitbucketStatusToGreen(); //2 validators for Bitbucket + verify(serverMonitoringMetrics, times(1)).setAzureStatusToGreen(); + verify(serverMonitoringMetrics, times(1)).setGitlabStatusToGreen(); + verify(serverMonitoringMetrics, times(1)).setGithubStatusToGreen(); + } + + @Test + public void createTask_givenFirstGithubValidationNotPassingAndSecondPassing_setGitHubValidationToTrue() { + AlmSettingDao dao = mock(AlmSettingDao.class); + List<AlmSettingDto> almSettingDtos = createAlmSettingDtos(); + when(dao.selectAll(any())).thenReturn(almSettingDtos); + when(dbClient.almSettingDao()).thenReturn(dao); + + when(githubValidator.validate(any())) + .thenThrow(new RuntimeException()) + .thenReturn(null); + + collector.createTask().run(); + + verify(serverMonitoringMetrics, times(1)).setGithubStatusToRed(); + verify(serverMonitoringMetrics, times(0)).setGithubStatusToGreen(); + } + + private AlmSettingDto findDto(ALM alm, List<AlmSettingDto> almSettingDtos) { + return almSettingDtos.stream().filter(d -> d.getAlm() == alm).findFirst().get(); + } + + private List<AlmSettingDto> createAlmSettingDtos() { + List<AlmSettingDto> dtos = new ArrayList<>(); + for(ALM alm : ALM.values()) { + AlmSettingDto almSettingDto = new AlmSettingDto(); + almSettingDto.setAlm(alm); + dtos.add(almSettingDto); + } + return dtos; + } + + private Optional<Thread> findNewDeamonThread() { + Set<Thread> threadSet = Thread.getAllStackTraces().keySet(); + String threadPartialName = DevOpsPlatformsMetricsCollector.class.getName(); + return threadSet.stream().filter(t -> t.getName().contains(threadPartialName)).findFirst(); + } +} |