Skip to content

Commit ec4d5a5

Browse files
745 add a "bytechef_job_execution" counter metric that is indexed by job name and job execution status
1 parent d16a88b commit ec4d5a5

File tree

3 files changed

+74
-8
lines changed

3 files changed

+74
-8
lines changed

server/libs/platform/platform-coordinator/src/main/java/com/bytechef/platform/coordinator/config/PlatformCoordinatorConfiguration.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@
2424
import com.bytechef.platform.coordinator.event.listener.JobStatusApplicationEventListener;
2525
import com.bytechef.platform.coordinator.event.listener.WebhookJobStatusApplicationEventListener;
2626
import com.bytechef.platform.coordinator.event.listener.WebhookTaskStartedApplicationEventListener;
27+
import com.bytechef.platform.coordinator.metrics.JobExecutionCounter;
2728
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
29+
import io.micrometer.core.instrument.MeterRegistry;
30+
import java.util.Optional;
31+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
2832
import org.springframework.context.annotation.Bean;
2933
import org.springframework.context.annotation.Configuration;
3034

@@ -43,14 +47,21 @@ public class PlatformCoordinatorConfiguration {
4347
@SuppressFBWarnings("EI")
4448
public PlatformCoordinatorConfiguration(
4549
JobService jobService, NotificationHandlerRegistry notificationHandlerRegistry,
46-
NotificationSenderRegistry notificationSenderRegistry, NotificationService notificationService) {
50+
NotificationSenderRegistry notificationSenderRegistry, NotificationService notificationService,
51+
MeterRegistry meterRegistry) {
4752

4853
this.jobService = jobService;
4954
this.notificationHandlerRegistry = notificationHandlerRegistry;
5055
this.notificationSenderRegistry = notificationSenderRegistry;
5156
this.notificationService = notificationService;
5257
}
5358

59+
@Bean
60+
@ConditionalOnProperty(name = "bytechef.observability.enabled", havingValue = "true")
61+
JobExecutionCounter jobExecutionCounter(MeterRegistry meterRegistry) {
62+
return new JobExecutionCounter(meterRegistry);
63+
}
64+
5465
@Bean
5566
WebhookJobStatusApplicationEventListener webhookJobStatusApplicationEventListener() {
5667
return new WebhookJobStatusApplicationEventListener(jobService);
@@ -62,9 +73,12 @@ WebhookTaskStartedApplicationEventListener taskStartedWebhookEventListener() {
6273
}
6374

6475
@Bean
65-
JobStatusApplicationEventListener jobStatusApplicationEventListener() {
76+
JobStatusApplicationEventListener jobStatusApplicationEventListener(
77+
Optional<JobExecutionCounter> jobExecutionCounter) {
78+
6679
return new JobStatusApplicationEventListener(
67-
jobService, notificationHandlerRegistry, notificationSenderRegistry, notificationService);
80+
jobExecutionCounter, jobService, notificationHandlerRegistry, notificationSenderRegistry,
81+
notificationService);
6882
}
6983

7084
}

server/libs/platform/platform-coordinator/src/main/java/com/bytechef/platform/coordinator/event/listener/JobStatusApplicationEventListener.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,31 +29,33 @@
2929
import com.bytechef.platform.configuration.notification.NotificationSender;
3030
import com.bytechef.platform.configuration.notification.NotificationSenderRegistry;
3131
import com.bytechef.platform.configuration.service.NotificationService;
32+
import com.bytechef.platform.coordinator.metrics.JobExecutionCounter;
3233
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
3334
import java.util.List;
34-
import org.springframework.stereotype.Component;
35+
import java.util.Optional;
3536

3637
/**
3738
* @author Matija Petanjek
3839
*/
39-
@Component
4040
public class JobStatusApplicationEventListener implements ApplicationEventListener {
4141

42+
private final Optional<JobExecutionCounter> jobExecutionCounter;
4243
private final JobService jobService;
4344
private final NotificationHandlerRegistry notificationHandlerRegistry;
4445
private final NotificationSenderRegistry notificationSenderRegistry;
4546
private final NotificationService notificationService;
4647

4748
@SuppressFBWarnings("EI")
4849
public JobStatusApplicationEventListener(
49-
JobService jobService, NotificationHandlerRegistry notificationHandlerRegistry,
50+
Optional<JobExecutionCounter> jobExecutionCounter, JobService jobService,
51+
NotificationHandlerRegistry notificationHandlerRegistry,
5052
NotificationSenderRegistry notificationSenderRegistry, NotificationService notificationService) {
5153

54+
this.jobExecutionCounter = jobExecutionCounter;
5255
this.jobService = jobService;
5356
this.notificationHandlerRegistry = notificationHandlerRegistry;
5457
this.notificationService = notificationService;
5558
this.notificationSenderRegistry = notificationSenderRegistry;
56-
5759
}
5860

5961
@SuppressWarnings({
@@ -62,13 +64,18 @@ public JobStatusApplicationEventListener(
6264
public void onApplicationEvent(ApplicationEvent applicationEvent) {
6365
if (applicationEvent instanceof JobStatusApplicationEvent jobStatusApplicationEvent) {
6466

67+
Job job = jobService.getJob(jobStatusApplicationEvent.getJobId());
68+
69+
jobExecutionCounter.ifPresent(
70+
jobExecutionCounter -> jobExecutionCounter.process(jobStatusApplicationEvent, job));
71+
6572
Job.Status status = jobStatusApplicationEvent.getStatus();
6673

6774
NotificationEvent.Type eventType =
6875
NotificationEvent.Type.of(NotificationEvent.Source.JOB, status.toString());
6976

7077
NotificationHandlerContext notificationHandlerContext = getNotificationHandlerContext(
71-
eventType, jobService.getJob(jobStatusApplicationEvent.getJobId()));
78+
eventType, job);
7279

7380
List<Notification> notifications = notificationService.getNotifications(eventType);
7481

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2025 ByteChef
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.bytechef.platform.coordinator.metrics;
18+
19+
import com.bytechef.atlas.coordinator.event.JobStatusApplicationEvent;
20+
import com.bytechef.atlas.execution.domain.Job;
21+
import io.micrometer.core.instrument.Counter;
22+
import io.micrometer.core.instrument.MeterRegistry;
23+
24+
/**
25+
* @author Matija Petanjek
26+
*/
27+
public class JobExecutionCounter {
28+
private final MeterRegistry meterRegistry;
29+
30+
public JobExecutionCounter(MeterRegistry meterRegistry) {
31+
this.meterRegistry = meterRegistry;
32+
}
33+
34+
public void process(JobStatusApplicationEvent jobStatusApplicationEvent, Job job) {
35+
Counter
36+
.builder("bytechef_job_execution")
37+
.tag("job_name", job.getLabel())
38+
.tag("job_status", jobStatusApplicationEvent.getStatus()
39+
.toString()
40+
.toLowerCase())
41+
.description("Inspect how many 'started' jobs ended with 'completed', 'stopped' or 'failed' status")
42+
.register(meterRegistry)
43+
.increment();
44+
}
45+
}

0 commit comments

Comments
 (0)