fix: unify container/agent log identity and fix multi-replica log capture
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m21s
CI / docker (push) Successful in 1m18s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 42s

Four logging pipeline fixes:

1. Multi-replica startup logs: remove stopLogCaptureByApp from
   SseConnectionManager — container log capture now expires naturally
   after 60s instead of being killed when the first agent connects SSE.
   This ensures all replicas' bootstrap output is captured.

2. Unified instance_id: container logs and agent logs now share the same
   instance identity ({envSlug}-{appSlug}-{replicaIndex}). DeploymentExecutor
   sets CAMELEER_AGENT_INSTANCEID per replica so the agent uses the same
   ID as ContainerLogForwarder. Instance-level log views now show both
   container and agent logs.

3. Labels-first container identity: TraefikLabelBuilder emits cameleer.replica
   and cameleer.instance-id labels. Container names are tenant-prefixed
   ({tenantId}-{envSlug}-{appSlug}-{idx}) for global Docker daemon uniqueness.

4. Environment filter on log queries: useApplicationLogs now passes the
   selected environment to the API, preventing log leakage across environments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-15 10:54:05 +02:00
parent bf2d07f3ba
commit fd806b9f2d
9 changed files with 43 additions and 65 deletions

View File

@@ -3,6 +3,7 @@ import { config } from '../../config';
import { useAuthStore } from '../../auth/auth-store';
import { useRefreshInterval } from './use-refresh-interval';
import { useGlobalFilters } from '@cameleer/design-system';
import { useEnvironmentStore } from '../environment-store';
export interface LogEntryResponse {
timestamp: string;
@@ -98,6 +99,7 @@ export function useApplicationLogs(
) {
const refetchInterval = useRefreshInterval(15_000);
const { timeRange } = useGlobalFilters();
const selectedEnv = useEnvironmentStore((s) => s.environment);
const to = options?.toOverride ?? timeRange.end.toISOString();
const useTimeRange = !options?.exchangeId;
@@ -105,6 +107,7 @@ export function useApplicationLogs(
application: application || undefined,
agentId: agentId || undefined,
source: options?.source || undefined,
environment: selectedEnv || undefined,
exchangeId: options?.exchangeId || undefined,
from: useTimeRange ? timeRange.start.toISOString() : undefined,
to: useTimeRange ? to : undefined,
@@ -112,7 +115,7 @@ export function useApplicationLogs(
};
const query = useQuery({
queryKey: ['logs', 'compat', application, agentId,
queryKey: ['logs', 'compat', application, agentId, selectedEnv,
useTimeRange ? timeRange.start.toISOString() : null,
useTimeRange ? to : null,
options?.limit, options?.exchangeId, options?.source],