v0.111.0: remote app-log diagnostics — error context capture (±5 lines, capped+redacted) + on-demand log tails via ACK pull pattern
- metrics: LogIssue.Context on first-occurrence errors (≤11 lines, ≤400 chars/line, warns carry none); RedactLine sanitizer (password/token/api-key/bearer/64-hex) applied to everything shipped; FetchContainerLogTail - report: 16KB per-report context budget (lowest-count issues dropped first); log_tail_requests ACK flag → next report ships log_tails (200 lines, ≤64KB/app head-truncated, ordered, redacted); consume-once drain - tests: synthetic-window context capture, caps, redaction, budget order, consume-once, fetch-error skip Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -59,9 +59,52 @@ func buildAppTelemetrySection(stackMgr *stacks.Manager, metricsStore *metrics.Me
|
||||
if result == nil {
|
||||
result = []AppTelemetry{}
|
||||
}
|
||||
|
||||
// 7. Enforce the per-report context budget (v0.111.0): drop context from the
|
||||
// lowest-count issues first until under 16KB. Warns never carry context (scanner).
|
||||
enforceContextBudget(result, contextBudgetBytes)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// contextBudgetBytes is the HARD per-report total for all LogIssue.Context lines.
|
||||
const contextBudgetBytes = 16 * 1024
|
||||
|
||||
// enforceContextBudget drops Context from the lowest-count issues (across all apps)
|
||||
// until the summed context bytes fit the budget. Mutates apps in place.
|
||||
func enforceContextBudget(apps []AppTelemetry, budget int) {
|
||||
type ref struct {
|
||||
app, issue, size, count int
|
||||
}
|
||||
var refs []ref
|
||||
total := 0
|
||||
for ai := range apps {
|
||||
for ii := range apps[ai].Issues {
|
||||
ctx := apps[ai].Issues[ii].Context
|
||||
if len(ctx) == 0 {
|
||||
continue
|
||||
}
|
||||
sz := 0
|
||||
for _, l := range ctx {
|
||||
sz += len(l)
|
||||
}
|
||||
refs = append(refs, ref{app: ai, issue: ii, size: sz, count: apps[ai].Issues[ii].Count})
|
||||
total += sz
|
||||
}
|
||||
}
|
||||
if total <= budget {
|
||||
return
|
||||
}
|
||||
sort.Slice(refs, func(i, j int) bool { return refs[i].count < refs[j].count })
|
||||
for _, r := range refs {
|
||||
if total <= budget {
|
||||
break
|
||||
}
|
||||
apps[r.app].Issues[r.issue].Context = nil
|
||||
total -= r.size
|
||||
}
|
||||
}
|
||||
|
||||
// buildAppTelemetry aggregates container-level telemetry and log data into per-stack AppTelemetry entries.
|
||||
func buildAppTelemetry(allStacks []stacks.Stack, telemetry []metrics.ContainerTelemetry, logs []metrics.ContainerLogSummary) []AppTelemetry {
|
||||
// Build lookup maps
|
||||
|
||||
Reference in New Issue
Block a user