Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(instrumentation): add instrumentation around echo event handling #1824

Merged
merged 2 commits into from
Aug 30, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

package com.netflix.spinnaker.gate.services

import com.netflix.spectator.api.Registry
import com.netflix.spectator.api.histogram.PercentileTimer
import com.netflix.spectator.api.patterns.IntervalCounter;
import com.netflix.spinnaker.gate.services.internal.EchoService
import com.netflix.spinnaker.gate.services.internal.Front50Service
import com.netflix.spinnaker.gate.services.internal.OrcaServiceSelector
Expand All @@ -27,6 +30,9 @@ import groovy.util.logging.Slf4j
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component

import javax.annotation.PostConstruct
import java.util.concurrent.TimeUnit

@Component
@Slf4j
class PipelineService {
Expand All @@ -48,6 +54,27 @@ class PipelineService {

private final RetrySupport retrySupport = new RetrySupport()

@Autowired
Registry registry

// Echo Event Metrics
private IntervalCounter echoEventsIntervalCounter;
private PercentileTimer echoEventsPercentileTimer;
private IntervalCounter echoEventsErrorIntervalCounter;

@PostConstruct
public void postConstruct() {
// Metrics for Echo Event handling.
final String idPrefix = "echo.events";

this.echoEventsIntervalCounter =
IntervalCounter.get(this.registry, this.registry.createId(idPrefix + ".count"));
this.echoEventsPercentileTimer =
PercentileTimer.get(this.registry, this.registry.createId(idPrefix + ".duration"));
this.echoEventsErrorIntervalCounter =
IntervalCounter.get(this.registry, this.registry.createId(idPrefix + ".error"));
}

void deleteForApplication(String applicationName, String pipelineName) {
front50Service.deletePipelineConfig(applicationName, pipelineName)
}
Expand Down Expand Up @@ -97,6 +124,9 @@ class PipelineService {
parameters.put("eventId", eventId)
parameters.put("executionId", executionId)

// Note that the Gate generated UUID is used as the event id and set it at the top level of the Map.
// This conforms to Event.java as used by Echo to deserialize the event upon receipt.
// This also prevents Echo from generating yet another UUID.
Map eventMap = [
content: [
application : application,
Expand All @@ -106,9 +136,29 @@ class PipelineService {
],
details: [
type: "manual"
]
],
eventId: eventId
]
echoService.postEvent(eventMap)

final long startTimeNanos = registry.clock().monotonicTime();

try {
echoService.postEvent(eventMap)
} catch (Exception e) {
echoEventsErrorIntervalCounter.increment();
log.error("Event processing failure: eventId={}, event={}", eventId, eventMap, e);
throw(e)
}

// Echo Event Metrics
final long durationInNanos = registry.clock().monotonicTime() - startTimeNanos;
echoEventsIntervalCounter.increment();
echoEventsPercentileTimer.record(durationInNanos, TimeUnit.NANOSECONDS);

log.debug(
"Event processing success: durationInNanos={}, eventId={}",
durationInNanos, eventId);

return [
eventId: eventId,
ref : String.format("/pipelines/%s", executionId)
Expand Down