diff --git a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/LogIngestionController.java b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/LogIngestionController.java index 21f580cd..073b9cd9 100644 --- a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/LogIngestionController.java +++ b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/LogIngestionController.java @@ -2,15 +2,18 @@ package com.cameleer3.server.app.controller; import com.cameleer3.common.model.LogEntry; import com.cameleer3.server.app.metrics.ServerMetrics; +import com.cameleer3.server.app.security.JwtAuthenticationFilter; import com.cameleer3.server.core.ingestion.BufferedLogEntry; import java.util.List; import com.cameleer3.server.core.ingestion.WriteBuffer; import com.cameleer3.server.core.agent.AgentInfo; import com.cameleer3.server.core.agent.AgentRegistryService; +import com.cameleer3.server.core.security.JwtService.JwtValidationResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import com.cameleer3.server.app.config.TenantProperties; +import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; @@ -49,7 +52,8 @@ public class LogIngestionController { @Operation(summary = "Ingest application log entries", description = "Accepts a batch of log entries from an agent. Entries are buffered and flushed periodically.") @ApiResponse(responseCode = "202", description = "Logs accepted for indexing") - public ResponseEntity ingestLogs(@RequestBody List entries) { + public ResponseEntity ingestLogs(@RequestBody List entries, + HttpServletRequest request) { String instanceId = extractAgentId(); if (instanceId == null || instanceId.isBlank()) { log.warn("Log ingestion rejected: no agent identity in request (unauthenticated or missing principal)"); @@ -62,19 +66,28 @@ public class LogIngestionController { return ResponseEntity.accepted().build(); } + String applicationId; + String environment; + AgentInfo agent = registryService.findById(instanceId); - if (agent == null) { - log.warn("Log ingestion from instance={}: agent not found in registry (not registered or expired). {} entries dropped.", - instanceId, entries.size()); - serverMetrics.recordIngestionDrops("no_agent", entries.size()); - return ResponseEntity.accepted().build(); + if (agent != null) { + applicationId = agent.applicationId(); + environment = agent.environmentId() != null ? agent.environmentId() : "default"; + } else { + // Agent not yet in registry (e.g. server just restarted) — fall back to JWT claims + JwtValidationResult jwt = (JwtValidationResult) request.getAttribute(JwtAuthenticationFilter.JWT_RESULT_ATTR); + applicationId = jwt != null ? jwt.application() : null; + environment = jwt != null && jwt.environment() != null ? jwt.environment() : "default"; + if (applicationId != null) { + log.debug("Log ingestion from instance={}: agent not in registry, using JWT claims (app={}, env={})", + instanceId, applicationId, environment); + } } - String applicationId = agent.applicationId(); - String environment = agent.environmentId() != null ? agent.environmentId() : "default"; - if (applicationId == null || applicationId.isBlank()) { - log.warn("Log ingestion from instance={}: agent has no applicationId. {} entries dropped.", instanceId, entries.size()); + log.warn("Log ingestion from instance={}: no applicationId from registry or JWT. {} entries dropped.", + instanceId, entries.size()); + serverMetrics.recordIngestionDrops("no_agent", entries.size()); return ResponseEntity.accepted().build(); }