diff --git a/service/application/src/main/java/com/solace/maas/ep/common/messages/ScanCommandMessage.java b/service/application/src/main/java/com/solace/maas/ep/common/messages/ScanCommandMessage.java index cfb17c9f0..538bdc563 100644 --- a/service/application/src/main/java/com/solace/maas/ep/common/messages/ScanCommandMessage.java +++ b/service/application/src/main/java/com/solace/maas/ep/common/messages/ScanCommandMessage.java @@ -49,8 +49,6 @@ public ScanCommandMessage(String messagingServiceId, this(messagingServiceId, scanId, scanTypes, destinations, null); } - - @Override public String toLog() { return null; diff --git a/service/application/src/main/java/com/solace/maas/ep/common/metrics/ObservabilityConstants.java b/service/application/src/main/java/com/solace/maas/ep/common/metrics/ObservabilityConstants.java new file mode 100644 index 000000000..8030c1077 --- /dev/null +++ b/service/application/src/main/java/com/solace/maas/ep/common/metrics/ObservabilityConstants.java @@ -0,0 +1,18 @@ +package com.solace.maas.ep.common.metrics; + +public class ObservabilityConstants { + public static final String MAAS_EMA_SCAN_EVENT_SENT = "maas.ema.scan_event.sent"; + public static final String MAAS_EMA_CONFIG_PUSH_EVENT_SENT = "maas.ema.config_push_event.sent"; + public static final String MAAS_EMA_HEARTBEAT_EVENT_SENT = "maas.ema.heartbeat_event.sent"; + + public static final String MAAS_EMA_SCAN_EVENT_RECEIVED = "maas.ema.scan_event.received"; + public static final String MAAS_EMA_CONFIG_PUSH_EVENT_RECEIVED = "maas.ema.config_push_event.received"; + + public static final String MAAS_EMA_CONFIG_PUSH_EVENT_CYCLE_TIME = "maas.ema.config_push_event.cycle_time"; + + public static final String STATUS_TAG = "status"; + public static final String ORG_ID_TAG = "org_id"; + public static final String SCAN_ID_TAG = "scan_id"; + + private ObservabilityConstants() {} +} diff --git a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/command/CommandManager.java b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/command/CommandManager.java index 6aef42e3a..e277a11da 100644 --- a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/command/CommandManager.java +++ b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/command/CommandManager.java @@ -15,6 +15,8 @@ import com.solace.maas.ep.event.management.agent.processor.CommandLogStreamingProcessor; import com.solace.maas.ep.event.management.agent.publisher.CommandPublisher; import com.solace.maas.ep.event.management.agent.util.MdcTaskDecorator; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Timer; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -24,14 +26,21 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.time.Instant; import java.time.OffsetDateTime; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.MAAS_EMA_CONFIG_PUSH_EVENT_CYCLE_TIME; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.MAAS_EMA_CONFIG_PUSH_EVENT_SENT; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.ORG_ID_TAG; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.STATUS_TAG; import static com.solace.maas.ep.event.management.agent.constants.Command.COMMAND_CORRELATION_ID; import static com.solace.maas.ep.event.management.agent.plugin.constants.RouteConstants.ACTOR_ID; import static com.solace.maas.ep.event.management.agent.plugin.constants.RouteConstants.TRACE_ID; @@ -49,18 +58,21 @@ public class CommandManager { private final EventPortalProperties eventPortalProperties; private final ThreadPoolTaskExecutor configPushPool; private final Optional commandLogStreamingProcessorOpt; + private final MeterRegistry meterRegistry; public CommandManager(TerraformManager terraformManager, CommandMapper commandMapper, CommandPublisher commandPublisher, MessagingServiceDelegateService messagingServiceDelegateService, EventPortalProperties eventPortalProperties, - Optional commandLogStreamingProcessorOpt) { + Optional commandLogStreamingProcessorOpt, + MeterRegistry meterRegistry) { this.terraformManager = terraformManager; this.commandMapper = commandMapper; this.commandPublisher = commandPublisher; this.messagingServiceDelegateService = messagingServiceDelegateService; this.eventPortalProperties = eventPortalProperties; + this.meterRegistry = meterRegistry; configPushPool = new ThreadPoolTaskExecutor(); configPushPool.setCorePoolSize(eventPortalProperties.getCommandThreadPoolMinSize()); configPushPool.setMaxPoolSize(eventPortalProperties.getCommandThreadPoolMaxSize()); @@ -73,6 +85,7 @@ public CommandManager(TerraformManager terraformManager, public void execute(CommandMessage request) { CommandRequest requestBO = commandMapper.map(request); + requestBO.setCreatedTime(Instant.now()); CompletableFuture.runAsync(() -> configPush(requestBO), configPushPool) .exceptionally(e -> { log.error("Error running command", e); @@ -221,6 +234,14 @@ private void finalizeAndSendResponse(CommandRequest request) { response.setTraceId(MDC.get(TRACE_ID)); response.setActorId(MDC.get(ACTOR_ID)); commandPublisher.sendCommandResponse(response, topicVars); + meterRegistry.counter(MAAS_EMA_CONFIG_PUSH_EVENT_SENT, ORG_ID_TAG, response.getOrgId(), + STATUS_TAG, response.getStatus().name()).increment(); + Timer jobCycleTime = Timer + .builder(MAAS_EMA_CONFIG_PUSH_EVENT_CYCLE_TIME) + .tag(ORG_ID_TAG, response.getOrgId()) + .tag(STATUS_TAG, request.getStatus().name()) + .register(meterRegistry); + jobCycleTime.record(request.getLifetime(ChronoUnit.MILLIS), TimeUnit.MILLISECONDS); } diff --git a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/HeartbeatGenerator.java b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/HeartbeatGenerator.java index 8fb835f08..06901b617 100644 --- a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/HeartbeatGenerator.java +++ b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/HeartbeatGenerator.java @@ -5,6 +5,8 @@ import com.solace.maas.ep.event.management.agent.config.eventPortal.EventPortalProperties; import com.solace.maas.ep.event.management.agent.plugin.jacoco.ExcludeFromJacocoGeneratedReport; import com.solace.maas.ep.event.management.agent.plugin.publisher.SolacePublisher; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.info.BuildProperties; @@ -12,6 +14,12 @@ import org.springframework.stereotype.Component; import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.MAAS_EMA_HEARTBEAT_EVENT_SENT; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.ORG_ID_TAG; @ExcludeFromJacocoGeneratedReport @Component @@ -23,21 +31,33 @@ public class HeartbeatGenerator { private final String runtimeAgentId; private final String topic; private final String runtimeAgentVersion; + private final MeterRegistry meterRegistry; public HeartbeatGenerator(SolaceConfiguration solaceConfiguration, EventPortalProperties eventPortalProperties, SolacePublisher solacePublisher, - BuildProperties buildProperties) { + BuildProperties buildProperties, + MeterRegistry meterRegistry) { this.solacePublisher = solacePublisher; this.runtimeAgentId = eventPortalProperties.getRuntimeAgentId(); topic = solaceConfiguration.getTopicPrefix() + "heartbeat/v1"; this.runtimeAgentVersion = getFormattedVersion(buildProperties.getVersion()); + this.meterRegistry = meterRegistry; } @Scheduled(fixedRate = 5000) public void sendHeartbeat() { HeartbeatMessage message = new HeartbeatMessage(runtimeAgentId, Instant.now().toString(), runtimeAgentVersion); - solacePublisher.publish(message, topic); + boolean result = solacePublisher.publish(message, topic); + logHealthMetric(message, result); + } + + private void logHealthMetric(HeartbeatMessage message, boolean isHealthy) { + List tags = new ArrayList<>(); + if (Objects.nonNull(message.getOrgId())) { + tags.add(Tag.of(ORG_ID_TAG, message.getOrgId())); + } + meterRegistry.gauge(MAAS_EMA_HEARTBEAT_EVENT_SENT, tags, isHealthy ? 1 : 0); } private String getFormattedVersion(String version) { diff --git a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/ScanDataPublisher.java b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/ScanDataPublisher.java index e334d584c..0b1e35b1a 100644 --- a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/ScanDataPublisher.java +++ b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/ScanDataPublisher.java @@ -1,20 +1,30 @@ package com.solace.maas.ep.event.management.agent.publisher; +import com.solace.maas.ep.event.management.agent.plugin.constants.ScanStatus; import com.solace.maas.ep.event.management.agent.plugin.mop.MOPMessage; import com.solace.maas.ep.event.management.agent.plugin.publisher.SolacePublisher; +import io.micrometer.core.instrument.MeterRegistry; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import java.util.Map; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.MAAS_EMA_SCAN_EVENT_SENT; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.ORG_ID_TAG; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.SCAN_ID_TAG; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.STATUS_TAG; + @Component @ConditionalOnProperty(name = "event-portal.gateway.messaging.standalone", havingValue = "false") public class ScanDataPublisher { private final SolacePublisher solacePublisher; + private final MeterRegistry meterRegistry; - public ScanDataPublisher(SolacePublisher solacePublisher) { + public ScanDataPublisher(SolacePublisher solacePublisher, + MeterRegistry meterRegistry) { this.solacePublisher = solacePublisher; + this.meterRegistry = meterRegistry; } /** @@ -43,6 +53,11 @@ public void sendScanData(MOPMessage message, Map topicDetails) { topicDetails.get("scanId"), topicDetails.get("scanType")); - solacePublisher.publish(message, topicString); + boolean isSuccessful = solacePublisher.publish(message, topicString); + + meterRegistry.counter(MAAS_EMA_SCAN_EVENT_SENT, + STATUS_TAG, isSuccessful ? ScanStatus.COMPLETE.name() : ScanStatus.FAILED.name(), + SCAN_ID_TAG, topicDetails.get("scanId"), + ORG_ID_TAG, topicDetails.get("orgId")).increment(); } } diff --git a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/ScanStatusPublisher.java b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/ScanStatusPublisher.java index b71228367..077a63fc7 100644 --- a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/ScanStatusPublisher.java +++ b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/publisher/ScanStatusPublisher.java @@ -6,6 +6,7 @@ import com.solace.maas.ep.event.management.agent.plugin.publisher.SolacePublisher; import com.solace.maas.ep.event.management.agent.plugin.route.exceptions.ScanOverallStatusException; import com.solace.maas.ep.event.management.agent.plugin.route.exceptions.ScanStatusException; +import io.micrometer.core.instrument.MeterRegistry; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; @@ -14,15 +15,23 @@ import java.util.List; import java.util.Map; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.MAAS_EMA_SCAN_EVENT_SENT; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.ORG_ID_TAG; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.SCAN_ID_TAG; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.STATUS_TAG; + @Slf4j @Component @ConditionalOnProperty(name = "event-portal.gateway.messaging.standalone", havingValue = "false") public class ScanStatusPublisher { private final SolacePublisher solacePublisher; + private final MeterRegistry meterRegistry; - public ScanStatusPublisher(SolacePublisher solacePublisher) { + public ScanStatusPublisher(SolacePublisher solacePublisher, + MeterRegistry meterRegistry) { this.solacePublisher = solacePublisher; + this.meterRegistry = meterRegistry; } /** @@ -46,6 +55,9 @@ public void sendOverallScanStatus(ScanStatusMessage message, Map } catch (Exception e) { throw new ScanOverallStatusException("Over all status exception: " + e.getMessage(), Map.of(scanId, List.of(e)), "Overall status", Arrays.asList(scanType.split(",")), ScanStatus.valueOf(status)); + } finally { + meterRegistry.counter(MAAS_EMA_SCAN_EVENT_SENT, STATUS_TAG, status, SCAN_ID_TAG, scanId, + ORG_ID_TAG, topicDetails.get("orgId")).increment(); } } @@ -72,6 +84,9 @@ public void sendScanDataStatus(ScanDataStatusMessage message, Map !list.isEmpty()) - .collect(Collectors.toList()).stream() + .toList().stream() ) - .collect(Collectors.toList()).stream().flatMap(List::stream).collect(Collectors.toList()); + .toList().stream().flatMap(List::stream).toList(); return scanService.singleScan(routes, groupId, scanId, traceId, actorId, messagingServiceEntity, runtimeAgentId); } diff --git a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/service/ScanService.java b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/service/ScanService.java index 53a8f5fed..772dd8943 100644 --- a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/service/ScanService.java +++ b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/service/ScanService.java @@ -21,6 +21,7 @@ import com.solace.maas.ep.event.management.agent.scanManager.model.ScanItemBO; import com.solace.maas.ep.event.management.agent.scanManager.model.ScanTypeBO; import com.solace.maas.ep.event.management.agent.util.IDGenerator; +import io.micrometer.core.instrument.MeterRegistry; import lombok.extern.slf4j.Slf4j; import net.logstash.logback.encoder.org.apache.commons.lang3.StringUtils; import org.apache.camel.Exchange; @@ -40,6 +41,10 @@ import java.util.stream.Collectors; import java.util.stream.StreamSupport; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.MAAS_EMA_SCAN_EVENT_SENT; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.SCAN_ID_TAG; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.STATUS_TAG; + /** * Responsible for initiating and managing Messaging Service scans. */ @@ -62,11 +67,17 @@ public class ScanService { private final IDGenerator idGenerator; + private final MeterRegistry meterRegistry; + public ScanService(ScanRepository repository, ScanRecipientHierarchyRepository scanRecipientHierarchyRepository, - ScanTypeRepository scanTypeRepository, ScanStatusRepository scanStatusRepository, ScanRouteService scanRouteService, - RouteService routeService, ProducerTemplate producerTemplate, - IDGenerator idGenerator) { + ScanTypeRepository scanTypeRepository, + ScanStatusRepository scanStatusRepository, + ScanRouteService scanRouteService, + RouteService routeService, + ProducerTemplate producerTemplate, + IDGenerator idGenerator, + MeterRegistry meterRegistry) { this.repository = repository; this.scanRecipientHierarchyRepository = scanRecipientHierarchyRepository; this.scanTypeRepository = scanTypeRepository; @@ -75,6 +86,7 @@ public ScanService(ScanRepository repository, this.routeService = routeService; this.producerTemplate = producerTemplate; this.idGenerator = idGenerator; + this.meterRegistry = meterRegistry; } /** @@ -284,6 +296,7 @@ public void sendScanStatus(String groupId, String scanId, String traceId, String exchange.getIn().setHeader(RouteConstants.SCAN_STATUS, status); exchange.getIn().setHeader(RouteConstants.SCAN_STATUS_DESC, ""); }); + meterRegistry.counter(MAAS_EMA_SCAN_EVENT_SENT, STATUS_TAG, status.name(), SCAN_ID_TAG, scanId).increment(); } protected CompletableFuture scanAsync(String groupId, String scanId, String traceId, String actorId, diff --git a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/CommandMessageHandler.java b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/CommandMessageHandler.java index e64ea5b32..5e2a10895 100644 --- a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/CommandMessageHandler.java +++ b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/CommandMessageHandler.java @@ -16,7 +16,8 @@ public class CommandMessageHandler extends SolaceDirectMessageHandler", solaceSubscriber); this.commandMessageProcessor = commandMessageProcessor; } diff --git a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/messageProcessors/CommandMessageProcessor.java b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/messageProcessors/CommandMessageProcessor.java index 8a9e30fe1..e106c057d 100644 --- a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/messageProcessors/CommandMessageProcessor.java +++ b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/messageProcessors/CommandMessageProcessor.java @@ -2,11 +2,22 @@ import com.solace.maas.ep.common.messages.CommandMessage; import com.solace.maas.ep.event.management.agent.command.CommandManager; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.MAAS_EMA_CONFIG_PUSH_EVENT_RECEIVED; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.ORG_ID_TAG; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.STATUS_TAG; + @Slf4j @Component @ConditionalOnProperty(name = "event-portal.gateway.messaging.standalone", havingValue = "false") @@ -15,21 +26,37 @@ public class CommandMessageProcessor implements MessageProcessor private final CommandManager commandManager; private final DynamicResourceConfigurationHelper dynamicResourceConfigurationHelper; + private final MeterRegistry meterRegistry; public CommandMessageProcessor(CommandManager commandManager, - DynamicResourceConfigurationHelper dynamicResourceConfigurationHelper) { + DynamicResourceConfigurationHelper dynamicResourceConfigurationHelper, + MeterRegistry meterRegistry) { this.commandManager = commandManager; this.dynamicResourceConfigurationHelper = dynamicResourceConfigurationHelper; + this.meterRegistry = meterRegistry; } @Override public void processMessage(CommandMessage message) { + log.info("Config push command processor started. context={} actorId={} ", message.getContext(), message.getActorId()); + logConfigPushMetric(message); if (CollectionUtils.isNotEmpty(message.getResources())) { dynamicResourceConfigurationHelper.loadSolaceBrokerResourceConfigurations(message.getResources()); } commandManager.execute(message); } + private void logConfigPushMetric(CommandMessage message) { + List tags = new ArrayList<>(); + if (Objects.nonNull(message.getStatus())) { + tags.add(Tag.of(STATUS_TAG, message.getStatus().name())); + } + if (StringUtils.isNotBlank(message.getOrgId())) { + tags.add(Tag.of(ORG_ID_TAG, message.getOrgId())); + } + meterRegistry.counter(MAAS_EMA_CONFIG_PUSH_EVENT_RECEIVED, tags).increment(); + } + @Override public Class supportedClass() { return CommandMessage.class; diff --git a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/messageProcessors/ScanCommandMessageProcessor.java b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/messageProcessors/ScanCommandMessageProcessor.java index 1a61d6529..7bcd5995e 100644 --- a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/messageProcessors/ScanCommandMessageProcessor.java +++ b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/subscriber/messageProcessors/ScanCommandMessageProcessor.java @@ -3,6 +3,7 @@ import com.solace.maas.ep.common.messages.ScanCommandMessage; import com.solace.maas.ep.event.management.agent.scanManager.ScanManager; import com.solace.maas.ep.event.management.agent.scanManager.model.ScanRequestBO; +import io.micrometer.core.instrument.MeterRegistry; import lombok.extern.slf4j.Slf4j; import net.logstash.logback.encoder.org.apache.commons.lang3.StringUtils; import org.apache.commons.collections4.CollectionUtils; @@ -14,6 +15,9 @@ import java.util.List; import java.util.UUID; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.MAAS_EMA_SCAN_EVENT_RECEIVED; +import static com.solace.maas.ep.common.metrics.ObservabilityConstants.SCAN_ID_TAG; + @Slf4j @Component @ConditionalOnProperty(name = "event-portal.gateway.messaging.standalone", havingValue = "false") @@ -22,16 +26,21 @@ public class ScanCommandMessageProcessor implements MessageProcessor destinations = new ArrayList<>(); List entityTypes = new ArrayList<>(); @@ -59,7 +68,7 @@ public void processMessage(ScanCommandMessage message) { ScanRequestBO scanRequestBO = ScanRequestBO.builder() .messagingServiceId(message.getMessagingServiceId()) - .scanId(!StringUtils.isEmpty(message.getScanId()) ? message.getScanId() : UUID.randomUUID().toString()) + .scanId(scanId) .traceId(message.getTraceId()) .actorId(message.getActorId()) .scanTypes(entityTypes) diff --git a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/TestConfig.java b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/TestConfig.java index c98216782..55d7d51f7 100644 --- a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/TestConfig.java +++ b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/TestConfig.java @@ -25,6 +25,7 @@ import com.solace.maas.ep.event.management.agent.util.config.idgenerator.IDGeneratorProperties; import com.solace.messaging.publisher.OutboundMessageBuilder; import com.solace.messaging.resources.Topic; +import io.micrometer.core.instrument.MeterRegistry; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.ProducerTemplate; @@ -167,14 +168,16 @@ public CommandManager getCommandManager(TerraformManager terraformManager, CommandPublisher commandPublisher, MessagingServiceDelegateService messagingServiceDelegateService, EventPortalProperties eventPortalProperties, - Optional commandLogStreamingProcessor) { + Optional commandLogStreamingProcessor, + MeterRegistry meterRegistry) { return new CommandManager( terraformManager, commandMapper, commandPublisher, messagingServiceDelegateService, eventPortalProperties, - commandLogStreamingProcessor + commandLogStreamingProcessor, + meterRegistry ); } diff --git a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/commandManager/CommandManagerTests.java b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/commandManager/CommandManagerTests.java index a27ec7d07..2639f4677 100644 --- a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/commandManager/CommandManagerTests.java +++ b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/commandManager/CommandManagerTests.java @@ -218,7 +218,7 @@ void failConfigPushCommand() { CommandMessage message = getCommandMessage("1"); doNothing().when(commandPublisher).sendCommandResponse(any(), any()); - doThrow(new RuntimeException("Error running command.")).when(commandManager).configPush(commandMapper.map(message)); + doThrow(new RuntimeException("Error running command.")).when(commandManager).configPush(any()); commandManager.execute(message); await().atMost(10, TimeUnit.SECONDS).until(() -> CommandManagerTestHelper.verifyCommandPublisherIsInvoked(commandPublisher, 1)); diff --git a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/plugin/route/handler/ScanDataPublisherRouteBuilderTests.java b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/plugin/route/handler/ScanDataPublisherRouteBuilderTests.java index de9d124ab..b8e163092 100644 --- a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/plugin/route/handler/ScanDataPublisherRouteBuilderTests.java +++ b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/plugin/route/handler/ScanDataPublisherRouteBuilderTests.java @@ -6,6 +6,9 @@ import com.solace.maas.ep.event.management.agent.processor.ScanDataProcessor; import com.solace.maas.ep.event.management.agent.publisher.ScanDataPublisher; import com.solace.maas.ep.event.management.agent.route.ep.ScanDataPublisherRouteBuilder; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.noop.NoopCounter; import lombok.SneakyThrows; import org.apache.camel.CamelContext; import org.apache.camel.EndpointInject; @@ -23,7 +26,9 @@ import org.springframework.context.annotation.Primary; import org.springframework.test.context.ActiveProfiles; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @CamelSpringBootTest @@ -65,8 +70,11 @@ static class TestConfig { public static RoutesBuilder createRouteBuilder() { SolacePublisher solacePublisher = mock(SolacePublisher.class); EventPortalProperties eventPortalProperties = mock(EventPortalProperties.class); + MeterRegistry meterRegistry = mock(MeterRegistry.class); + when(meterRegistry.counter(any(), any(String[].class))) + .thenReturn(new NoopCounter(new Meter.Id("noop", null, null, null, null))); - ScanDataPublisher scanDataPublisher = new ScanDataPublisher(solacePublisher); + ScanDataPublisher scanDataPublisher = new ScanDataPublisher(solacePublisher, meterRegistry); ScanDataProcessor scanDataProcessor = new ScanDataProcessor(scanDataPublisher, eventPortalProperties); ScanTypeDescendentsProcessor scanTypeDescendentsProcessor = mock(ScanTypeDescendentsProcessor.class); diff --git a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/service/ScanServiceTests.java b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/service/ScanServiceTests.java index df7924698..e7a810b1a 100644 --- a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/service/ScanServiceTests.java +++ b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/service/ScanServiceTests.java @@ -18,6 +18,9 @@ import com.solace.maas.ep.event.management.agent.repository.scan.ScanTypeRepository; import com.solace.maas.ep.event.management.agent.service.logging.LoggingService; import com.solace.maas.ep.event.management.agent.util.IDGenerator; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.noop.NoopCounter; import lombok.SneakyThrows; import org.apache.camel.Processor; import org.apache.camel.Produce; @@ -95,6 +98,9 @@ public class ScanServiceTests { @Autowired private ScanServiceHelper scanServiceHelper; + @Mock + private MeterRegistry meterRegistry; + @Test @SneakyThrows public void testSingleScanWithRouteBundle() { @@ -143,9 +149,10 @@ public void testSingleScanWithRouteBundle() { .thenReturn(scanType); when(scanStatusRepository.save(scanStatus)) .thenReturn(scanStatus); - when(scanRecipientHierarchyRepository.save(any(ScanRecipientHierarchyEntity.class))) .thenReturn(mock(ScanRecipientHierarchyEntity.class)); + when(meterRegistry.counter(any(), any(String[].class))) + .thenReturn(new NoopCounter(new Meter.Id("noop", null, null, null, null))); scanService.singleScan(List.of(topicListing, consumerGroups, additionalConsumerGroupConfigBundle), "groupId", @@ -310,9 +317,12 @@ public void testParseRouteRecipients() { @Test @SneakyThrows public void testSendScanStatus() { + when(meterRegistry.counter(any(), any(String[].class))) + .thenReturn(new NoopCounter(new Meter.Id("noop", null, null, null, null))); ScanService service = new ScanService(mock(ScanRepository.class), mock(ScanRecipientHierarchyRepository.class), mock(ScanTypeRepository.class), - mock(ScanStatusRepository.class), mock(ScanRouteService.class), mock(RouteService.class), template, idGenerator); + mock(ScanStatusRepository.class), mock(ScanRouteService.class), mock(RouteService.class), + template, idGenerator, meterRegistry); service.sendScanStatus("scanId", "groupId", "messagingServiceId", "traceId", "actorId", "queueListing", ScanStatus.IN_PROGRESS); diff --git a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/subscriber/MessageReceiverTests.java b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/subscriber/MessageReceiverTests.java index 9e95aea00..9e522d1e6 100644 --- a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/subscriber/MessageReceiverTests.java +++ b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/subscriber/MessageReceiverTests.java @@ -12,6 +12,9 @@ import com.solace.maas.ep.event.management.agent.service.ManualImportFilesService; import com.solace.maas.ep.event.management.agent.subscriber.messageProcessors.ScanCommandMessageProcessor; import com.solace.messaging.receiver.InboundMessage; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.noop.NoopCounter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.camel.ProducerTemplate; @@ -33,6 +36,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatNoException; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; @@ -66,6 +70,9 @@ public class MessageReceiverTests { @Mock ManualImportDetailsService manualImportDetailsService; + @Mock + MeterRegistry meterRegistry; + @Test @SneakyThrows public void scanReceiver() { @@ -87,6 +94,8 @@ public void scanReceiver() { when(inboundMessage.getProperty(MOPConstants.MOP_MSG_META_DECODER)).thenReturn( "com.solace.maas.ep.common.messages.ScanCommandMessage"); when(inboundMessage.getDestinationName()).thenReturn("anyTopic"); + when(meterRegistry.counter(any(), any(String[].class))).thenReturn(new NoopCounter( + new Meter.Id("mockMeterId", null, null, null, null))); ScanCommandMessageHandler scanCommandMessageHandler = new ScanCommandMessageHandler( solaceConfiguration, solaceSubscriber, scanCommandMessageProcessor); @@ -114,6 +123,8 @@ public void testBadClass() { @Test @SneakyThrows public void testScanCommandMessage() { + when(meterRegistry.counter(any(), any(String[].class))).thenReturn(new NoopCounter( + new Meter.Id("mockMeterId", null, null, null, null))); ScanCommandMessageHandler scanCommandMessageHandler = new ScanCommandMessageHandler( solaceConfiguration, solaceSubscriber, scanCommandMessageProcessor); @@ -232,8 +243,7 @@ public void heartbeatReceiverTest() { "com.solace.maas.ep.common.messages.HeartbeatMessage"); when(inboundMessage.getDestinationName()).thenReturn("anyTopic"); - HeartbeatMessageHandler heartbeatMessageHandler = new HeartbeatMessageHandler(solaceConfiguration, - solaceSubscriber); + HeartbeatMessageHandler heartbeatMessageHandler = new HeartbeatMessageHandler(solaceConfiguration, solaceSubscriber); heartbeatMessageHandler.onMessage(inboundMessage); } diff --git a/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/command/model/CommandRequest.java b/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/command/model/CommandRequest.java index 6ad491c51..e8909fd53 100644 --- a/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/command/model/CommandRequest.java +++ b/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/command/model/CommandRequest.java @@ -6,6 +6,8 @@ import lombok.NoArgsConstructor; import org.apache.commons.collections4.CollectionUtils; +import java.time.Instant; +import java.time.temporal.TemporalUnit; import java.util.List; @Data @@ -18,6 +20,19 @@ public class CommandRequest { private String serviceId; private JobStatus status; private List commandBundles; + private Instant createdTime; + private Instant updatedTime; + + public long getLifetime(TemporalUnit timeUnit) { + if (createdTime == null) { + // micrometer won't record negative numbers + return -1L; + } + if (updatedTime == null) { + return createdTime.until(Instant.now(), timeUnit); + } + return createdTime.until(updatedTime, timeUnit); + } public void determineStatus() { boolean hasAtLeastOneError = false; diff --git a/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/publisher/SolacePublisher.java b/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/publisher/SolacePublisher.java index 28a121c4c..222b5ddba 100644 --- a/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/publisher/SolacePublisher.java +++ b/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/publisher/SolacePublisher.java @@ -38,7 +38,7 @@ public SolacePublisher(OutboundMessageBuilder outboundMessageBuilder, this.directMessagePublisher = directMessagePublisher; } - public void publish(MOPMessage message, String topicString) { + public boolean publish(MOPMessage message, String topicString) { Topic topic = Topic.of(topicString); try { @@ -51,6 +51,7 @@ public void publish(MOPMessage message, String topicString) { log.trace("publishing to {}:\n{}", topicString, messageString); directMessagePublisher.publish(outboundMessage, topic, properties); } + return true; } catch (PubSubPlusClientException e) { log.error("PubSubPlus Client Exception while attempting to publish message: {}", message.toString(), e); } catch (IllegalStateException e) { @@ -60,6 +61,7 @@ public void publish(MOPMessage message, String topicString) { } catch (JsonProcessingException e) { log.error("JsonProcessingException while attempting to publish message: {}", message.toString(), e); } + return false; } private Properties getProperties(MOPMessage message) {