Skip to content

Commit

Permalink
Add HeartBeatService and HeartBeatController (#244)
Browse files Browse the repository at this point in the history
  • Loading branch information
saschadoemer authored Sep 4, 2024
1 parent 6d75454 commit ddb8e38
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 6 deletions.
16 changes: 10 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,6 @@
<version>2.10.1</version>
</dependency>

<!-- PROMETHEUS -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

<!-- JAXB -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
Expand Down Expand Up @@ -164,6 +158,16 @@
<version>8.5.10</version>
</dependency>

<!-- MICROMEETER -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

</dependencies>

<build>
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/de/app/fivegla/business/HeartBeatService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package de.app.fivegla.business;

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
* The HeartBeatService class provides functionality to register heartbeats.
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class HeartBeatService {

private final MeterRegistry meterRegistry;
private final ConcurrentHashMap<String, AtomicLong> lastHeartbeatTimestamps = new ConcurrentHashMap<>();

/**
* Register a heartbeat using Micrometer.
*/
public void registerHeartBeat(String id) {
log.info("Registering heartbeat using Micrometer for sensor id: {}", id);
var counter = meterRegistry.counter("heartbeat", "id", id);
counter.increment();

lastHeartbeatTimestamps.computeIfAbsent(id, key -> {
AtomicLong timestamp = new AtomicLong();
Gauge.builder("heartbeat.lastTimestamp", timestamp, AtomicLong::get)
.description("The timestamp of the last heartbeat for sensor id: " + id)
.tags("sensorId", id)
.register(meterRegistry);
return timestamp;
}).set(System.currentTimeMillis());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class BaseMappings {
public static final String MAINTENANCE = SECURED_BY_API_KEY + "/maintenance";
public static final String INFO = SECURED_BY_API_KEY + "/info";
public static final String TENANT = SECURED_BY_API_KEY + "/tenant";
public static final String HEARTBEAT = SECURED_BY_API_KEY + "/heartbeat";

// SECURED_BY_TENANT

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package de.app.fivegla.controller.global;

import de.app.fivegla.business.HeartBeatService;
import de.app.fivegla.config.security.marker.ApiKeyApiAccess;
import de.app.fivegla.controller.api.BaseMappings;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* The HeartBeatController class handles heartbeat-related operations.
* It provides a method to register a heartbeat.
* <p>
* This controller is mapped to the /heartbeat endpoint.
*/
@Slf4j
@RestController
@RequestMapping(BaseMappings.HEARTBEAT)
@RequiredArgsConstructor
public class HeartBeatController implements ApiKeyApiAccess {

private final HeartBeatService heartBeatService;

@Operation(
operationId = "heartbeat",
description = "Heartbeat endpoint.",
tags = BaseMappings.HEARTBEAT
)
@ApiResponse(
responseCode = "200",
description = "The heartbeat was successful."
)
@PostMapping("/{id}")
public ResponseEntity<Void> heartBeat(@PathVariable @Schema(description = "The ID") String id) {
heartBeatService.registerHeartBeat(id);
return ResponseEntity.ok().build();
}

}

0 comments on commit ddb8e38

Please sign in to comment.