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());
+ }
+
+}
diff --git a/src/main/java/de/app/fivegla/controller/api/BaseMappings.java b/src/main/java/de/app/fivegla/controller/api/BaseMappings.java
index f0bbc87..53fae14 100644
--- a/src/main/java/de/app/fivegla/controller/api/BaseMappings.java
+++ b/src/main/java/de/app/fivegla/controller/api/BaseMappings.java
@@ -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
diff --git a/src/main/java/de/app/fivegla/controller/global/HeartBeatController.java b/src/main/java/de/app/fivegla/controller/global/HeartBeatController.java
new file mode 100644
index 0000000..13e2c38
--- /dev/null
+++ b/src/main/java/de/app/fivegla/controller/global/HeartBeatController.java
@@ -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.
+ *
+ * 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 heartBeat(@PathVariable @Schema(description = "The ID") String id) {
+ heartBeatService.registerHeartBeat(id);
+ return ResponseEntity.ok().build();
+ }
+
+}