feat: add application config overview and inline editing
Some checks failed
CI / cleanup-branch (push) Has been skipped
CI / build (push) Failing after 22s
CI / docker (push) Has been skipped
CI / deploy (push) Has been skipped
CI / deploy-feature (push) Has been skipped

Add admin page at /admin/appconfig with a DataTable showing all
application configurations. Inline dropdowns allow editing log level,
engine level, payload capture mode, and metrics toggle directly from
the table. Changes push to agents via SSE immediately.

Also adds a config bar on the AgentHealth page (/agents/:appId) for
per-application config management with the same 4 settings.

Backend: GET /api/v1/config list endpoint, findAll() on repository,
sensible defaults for logForwardingLevel/engineLevel/payloadCaptureMode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-26 12:51:07 +01:00
parent 056a6f0ff5
commit b0484459a2
10 changed files with 409 additions and 2 deletions

View File

@@ -44,6 +44,14 @@ public class ApplicationConfigController {
this.objectMapper = objectMapper;
}
@GetMapping
@Operation(summary = "List all application configs",
description = "Returns stored configurations for all applications")
@ApiResponse(responseCode = "200", description = "Configs returned")
public ResponseEntity<List<ApplicationConfig>> listConfigs() {
return ResponseEntity.ok(configRepository.findAll());
}
@GetMapping("/{application}")
@Operation(summary = "Get application config",
description = "Returns the current configuration for an application. Returns defaults if none stored.")
@@ -99,6 +107,9 @@ public class ApplicationConfigController {
config.setMetricsEnabled(true);
config.setSamplingRate(1.0);
config.setTracedProcessors(Map.of());
config.setLogForwardingLevel("INFO");
config.setEngineLevel("REGULAR");
config.setPayloadCaptureMode("NONE");
return config;
}
}

View File

@@ -20,6 +20,21 @@ public class PostgresApplicationConfigRepository {
this.objectMapper = objectMapper;
}
public List<ApplicationConfig> findAll() {
return jdbc.query(
"SELECT config_val, version, updated_at FROM application_config ORDER BY application",
(rs, rowNum) -> {
try {
ApplicationConfig cfg = objectMapper.readValue(rs.getString("config_val"), ApplicationConfig.class);
cfg.setVersion(rs.getInt("version"));
cfg.setUpdatedAt(rs.getTimestamp("updated_at").toInstant());
return cfg;
} catch (JsonProcessingException e) {
throw new RuntimeException("Failed to deserialize application config", e);
}
});
}
public Optional<ApplicationConfig> findByApplication(String application) {
List<ApplicationConfig> results = jdbc.query(
"SELECT config_val, version, updated_at FROM application_config WHERE application = ?",