fix: stamp environment on agent_events rows
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m28s
CI / docker (push) Successful in 1m13s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 43s

The agent_events table has an `environment` column and AgentEventsController
filters on it, but the INSERT never populated it — every row got the
column default ('default'). Result: Timeline on the Application Runtime
page was empty whenever the user's selected env was anything other than
'default'.

Thread env through the write path:
- AgentEventRepository.insert + AgentEventService.recordEvent gain an
  `environment` param; delete the no-env query overload (unused).
- ClickHouseAgentEventRepository.insert writes the column (falls back to
  'default' on null to match column DEFAULT).
- All 5 callers source env from the agent registry (AgentInfo.environmentId)
  or the registration request body; AgentLifecycleMonitor, deregister,
  command ack, event ingestion, register/re-register.
- Integration test updated for the new signatures.

Pre-existing rows in deployed CH will still report environment='default'.
New events from this build forward will carry the correct env. Backfill
(UPDATE ... FROM apps) is left as a manual DB step if historical timeline
is needed for non-default envs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-17 10:30:56 +02:00
parent 5807cfd807
commit 62dd71b860
8 changed files with 35 additions and 41 deletions

View File

@@ -49,15 +49,15 @@ class ClickHouseAgentEventRepositoryIT {
*/
private void insertAt(String instanceId, String applicationId, String eventType, String detail, Instant ts) {
jdbc.update(
"INSERT INTO agent_events (tenant_id, instance_id, application_id, event_type, detail, timestamp) VALUES (?, ?, ?, ?, ?, ?)",
"default", instanceId, applicationId, eventType, detail, Timestamp.from(ts));
"INSERT INTO agent_events (tenant_id, instance_id, application_id, environment, event_type, detail, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)",
"default", instanceId, applicationId, "default", eventType, detail, Timestamp.from(ts));
}
// ── Tests ─────────────────────────────────────────────────────────────────
@Test
void insert_writesEvent() {
repo.insert("agent-1", "app-a", "CONNECTED", "agent came online");
repo.insert("agent-1", "app-a", "default", "CONNECTED", "agent came online");
Long count = jdbc.queryForObject(
"SELECT count() FROM agent_events WHERE instance_id = 'agent-1'",
@@ -67,10 +67,10 @@ class ClickHouseAgentEventRepositoryIT {
@Test
void query_byAppId_filtersCorrectly() {
repo.insert("agent-1", "app-x", "CONNECTED", "");
repo.insert("agent-2", "app-y", "DISCONNECTED", "");
repo.insert("agent-1", "app-x", "default", "CONNECTED", "");
repo.insert("agent-2", "app-y", "default", "DISCONNECTED", "");
List<AgentEventRecord> results = repo.query("app-x", null, null, null, 100);
List<AgentEventRecord> results = repo.query("app-x", null, null, null, null, 100);
assertThat(results).hasSize(1);
assertThat(results.get(0).applicationId()).isEqualTo("app-x");
@@ -79,10 +79,10 @@ class ClickHouseAgentEventRepositoryIT {
@Test
void query_byAgentId_filtersCorrectly() {
repo.insert("agent-alpha", "app-shared", "CONNECTED", "");
repo.insert("agent-beta", "app-shared", "CONNECTED", "");
repo.insert("agent-alpha", "app-shared", "default", "CONNECTED", "");
repo.insert("agent-beta", "app-shared", "default", "CONNECTED", "");
List<AgentEventRecord> results = repo.query(null, "agent-alpha", null, null, 100);
List<AgentEventRecord> results = repo.query(null, "agent-alpha", null, null, null, 100);
assertThat(results).hasSize(1);
assertThat(results.get(0).instanceId()).isEqualTo("agent-alpha");
@@ -99,7 +99,7 @@ class ClickHouseAgentEventRepositoryIT {
insertAt("agent-1", "app-a", "DISCONNECTED", "late", t3);
// Query [t2, t3) — should return only the middle event
List<AgentEventRecord> results = repo.query(null, null, t2, t3, 100);
List<AgentEventRecord> results = repo.query(null, null, null, t2, t3, 100);
assertThat(results).hasSize(1);
assertThat(results.get(0).eventType()).isEqualTo("HEARTBEAT");
@@ -112,16 +112,16 @@ class ClickHouseAgentEventRepositoryIT {
insertAt("agent-1", "app-a", "HEARTBEAT", "beat-" + i, base.plusSeconds(i));
}
List<AgentEventRecord> results = repo.query(null, null, null, null, 3);
List<AgentEventRecord> results = repo.query(null, null, null, null, null, 3);
assertThat(results).hasSize(3);
}
@Test
void query_returnsZeroId() {
repo.insert("agent-1", "app-a", "CONNECTED", "");
repo.insert("agent-1", "app-a", "default", "CONNECTED", "");
List<AgentEventRecord> results = repo.query(null, null, null, null, 10);
List<AgentEventRecord> results = repo.query(null, null, null, null, null, 10);
assertThat(results).hasSize(1);
assertThat(results.get(0).id()).isEqualTo(0L);
@@ -129,10 +129,10 @@ class ClickHouseAgentEventRepositoryIT {
@Test
void query_noFilters_returnsAllEvents() {
repo.insert("agent-1", "app-a", "CONNECTED", "");
repo.insert("agent-2", "app-b", "DISCONNECTED", "");
repo.insert("agent-1", "app-a", "default", "CONNECTED", "");
repo.insert("agent-2", "app-b", "default", "DISCONNECTED", "");
List<AgentEventRecord> results = repo.query(null, null, null, null, 100);
List<AgentEventRecord> results = repo.query(null, null, null, null, null, 100);
assertThat(results).hasSize(2);
}
@@ -147,7 +147,7 @@ class ClickHouseAgentEventRepositoryIT {
insertAt("agent-1", "app-a", "SECOND", "", t2);
insertAt("agent-1", "app-a", "THIRD", "", t3);
List<AgentEventRecord> results = repo.query(null, null, null, null, 100);
List<AgentEventRecord> results = repo.query(null, null, null, null, null, 100);
assertThat(results.get(0).eventType()).isEqualTo("THIRD");
assertThat(results.get(1).eventType()).isEqualTo("SECOND");