feat: integrate log template mining into audit report and logs#24328
feat: integrate log template mining into audit report and logs#24328
Conversation
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/850383e4-6ce1-4a3d-aa07-dae32343caa6 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/850383e4-6ce1-4a3d-aa07-dae32343caa6 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/850383e4-6ce1-4a3d-aa07-dae32343caa6 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
add a flag "--train" to the "logs" command that runs the drain3 pre training to build the weights file which should be embedded to the compiler as default |
|
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/621cd144-30cc-44cd-9e7c-37361cee1b70 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…return train error Agent-Logs-Url: https://github.com/github/gh-aw/sessions/621cd144-30cc-44cd-9e7c-37361cee1b70 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in commit
How it works:
Embedding as default: The |
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/1361e355-3eb5-4c65-9f64-ee483320bd65 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/1361e355-3eb5-4c65-9f64-ee483320bd65 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in commit Drain3 multi-run pattern analysis is now part of What was added:
Markdown output example: ## Agent Event Pattern Analysis (Drain3)
### ℹ Log template patterns mined
**Category:** execution | **Severity:** info
Drain3 analysis identified 4 distinct event templates across 3 pipeline stages from 12 events.
_Evidence:_ `error=1 plan=1 tool_call=2` |
|
@copilot don't mention drain3 in report (internal detail) |
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/89ebe149-2934-400a-a97e-a8f73ee6bbe4 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in commit |
cmd/agentdrain-demo/main.go
Outdated
| // - printing matched cluster ID, template, extracted params, and anomaly report | ||
| // - saving and reloading a snapshot | ||
| // - running inference on a new event after restore | ||
| package main |
…emo binary (#24344) * Initial plan * feat: add daily drain3 weight training workflow and delete demo binary Agent-Logs-Url: https://github.com/github/gh-aw/sessions/c5c57258-f0a1-4ade-8afc-9c4464b162cc Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds an embedded, production-oriented Drain3-style log template mining module and wires it into existing gh aw audit, gh aw audit report, and gh aw logs observability outputs, including an opt-in --train workflow to generate and persist default weights.
Changes:
- Introduces
pkg/agentdrain(masking, mining, persistence, coordinator, anomaly scoring) with unit tests and embedded default weights. - Integrates mined template/anomaly/stage-sequence insights into logs/audit single-run and cross-run reports.
- Adds
gh aw logs --trainto writedrain3_weights.json, plus a scheduled workflow to retrain and open a PR updating embedded defaults.
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/cli/logs_report.go | Appends multi-run Drain3 insights to logs report observability output. |
| pkg/cli/logs_orchestrator.go | Adds train parameter and triggers weight training after processing runs. |
| pkg/cli/logs_json_stderr_order_test.go | Updates orchestrator calls to include the new train arg. |
| pkg/cli/logs_download_test.go | Updates orchestrator calls to include the new train arg. |
| pkg/cli/logs_command.go | Adds --train flag and passes it through to the orchestrator. |
| pkg/cli/logs_ci_scenario_test.go | Updates orchestrator calls to include the new train arg. |
| pkg/cli/drain3_train.go | Implements coordinator training + drain3_weights.json writing and instructions. |
| pkg/cli/drain3_train_test.go | Adds tests for training behavior and --train flag presence. |
| pkg/cli/drain3_integration.go | Adds integration layer that converts run data into events and emits insights. |
| pkg/cli/drain3_integration_test.go | Adds tests validating insight generation and event conversion behavior. |
| pkg/cli/context_cancellation_test.go | Updates orchestrator calls to include the new train arg. |
| pkg/cli/audit_report.go | Appends single-run Drain3 insights to audit report observability insights. |
| pkg/cli/audit_cross_run.go | Adds drain3_insights field and builds cross-run Drain3 insights. |
| pkg/cli/audit_cross_run_test.go | Adds tests for cross-run Drain3 mapping, inclusion, and rendering. |
| pkg/cli/audit_cross_run_render.go | Renders Drain3 insights in markdown and pretty cross-run reports. |
| pkg/agentdrain/types.go | Defines exported config/event/cluster/match/anomaly types. |
| pkg/agentdrain/tree.go | Implements the parse tree used to bucket candidate clusters. |
| pkg/agentdrain/pretrain.go | Adds pretraining helpers for seeding templates/counts. |
| pkg/agentdrain/persist.go | Adds JSON snapshot save/load and miner restore constructor. |
| pkg/agentdrain/miner.go | Implements the concurrent miner (train/match/analyze/event ingestion). |
| pkg/agentdrain/miner_test.go | Adds miner/coordinator/masking/persistence/concurrency tests. |
| pkg/agentdrain/mask.go | Implements regex-based masking plus deterministic event flattening/tokenization. |
| pkg/agentdrain/defaults.go | Embeds data/default_weights.json and loads it into a coordinator. |
| pkg/agentdrain/data/default_weights.json | Adds an initial empty embedded weights file ({}). |
| pkg/agentdrain/coordinator.go | Adds stage-based coordinator and combined weights save/load helpers. |
| pkg/agentdrain/config.go | Provides default configuration and masking rules. |
| pkg/agentdrain/cluster.go | Implements cluster store, similarity, and template merging utilities. |
| pkg/agentdrain/anomaly.go | Implements weighted anomaly scoring and reason strings. |
| pkg/agentdrain/anomaly_test.go | Adds anomaly detector and end-to-end AnalyzeEvent tests. |
| .github/workflows/train-drain3-weights.yml | Adds scheduled/manual workflow to retrain weights and open a PR with updates. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| for g := range goroutines { | ||
| wg.Add(1) | ||
| go func(id int) { | ||
| defer wg.Done() | ||
| for i := range linesEach { |
There was a problem hiding this comment.
TestConcurrency uses for g := range goroutines / for i := range linesEach, but goroutines and linesEach are integers, so ranging over them does not compile. Use a standard index loop (e.g., for g := 0; g < goroutines; g++ { ... }) for both loops.
| for g := range goroutines { | |
| wg.Add(1) | |
| go func(id int) { | |
| defer wg.Done() | |
| for i := range linesEach { | |
| for g := 0; g < goroutines; g++ { | |
| wg.Add(1) | |
| go func(id int) { | |
| defer wg.Done() | |
| for i := 0; i < linesEach; i++ { |
| if !isNew { | ||
| report.LowSimilarity = result.Similarity < d.threshold | ||
| } |
There was a problem hiding this comment.
LowSimilarity is effectively unreachable in the current pipeline: Miner.match only returns results when Similarity >= SimThreshold, and AnalyzeEvent constructs the detector with the same threshold (m.cfg.SimThreshold). That means result.Similarity < d.threshold can never be true when isNew == false, so the low-similarity anomaly path won't trigger. Consider returning the best match even when it is below the threshold (so you can report low similarity), or using a separate (higher) detector threshold than the match threshold.
| parts := make([]string, 0, len(allClusters)) | ||
| for stage, clusters := range allClusters { | ||
| if len(clusters) > 0 { | ||
| parts = append(parts, fmt.Sprintf("%s=%d", stage, len(clusters))) | ||
| } | ||
| } | ||
| return strings.Join(parts, " ") |
There was a problem hiding this comment.
buildStageBreakdown iterates over a Go map (allClusters), so the resulting evidence string order is nondeterministic across runs. This can lead to unstable CLI/report output (and flaky golden tests if added later). Consider sorting the stage keys before building parts so the output is deterministic.
| MaskRules: []MaskRule{ | ||
| { | ||
| Name: "uuid", | ||
| Pattern: `[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`, |
There was a problem hiding this comment.
The UUID masking regex only matches lowercase hex ([0-9a-f]). If log lines contain uppercase UUIDs, they won't be masked and could leak identifiers into templates/params. Consider making the pattern case-insensitive or expanding the character classes to include A-F.
| Pattern: `[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`, | |
| Pattern: `(?i)[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`, |
| fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Log pattern weights written to: "+outputPath)) | ||
| fmt.Fprintln(os.Stderr, console.FormatInfoMessage( | ||
| "To embed these weights as default, copy the file and rebuild:\n"+ | ||
| " cp "+outputPath+" pkg/agentdrain/data/default_weights.json\n"+ | ||
| " make build", | ||
| )) |
There was a problem hiding this comment.
The copy/paste instructions build a cp command by concatenating paths without quoting. If outputDir contains spaces (or shell-special characters), the suggested command will fail. Consider quoting/escaping outputPath in the printed instructions.
Summary
Implements a production-oriented log template mining module (
pkg/agentdrain) and integrates it into thegh aw audit,gh aw audit report, andgh aw logsobservability pipeline. Includes a--trainflag on thelogscommand to build and embed default weights.What this PR does
New package:
pkg/agentdrainA standalone, zero-dependency Go package implementing online log template mining (Drain3-style algorithm), specifically designed for agent session observability:
types.goConfig,MaskRule,Cluster,MatchResult,AnomalyReport,AgentEventconfig.goDefaultConfig()with sensible defaults and built-in masking rulesmask.goMasker(UUID, session ID, number, URL, timestamp, quoted-string),FlattenEvent,Tokenizetree.gocluster.goclusterStore,computeSimilarity,mergeTemplateminer.goMiner:Train/Match/TrainEvent/AnalyzeEventanomaly.goAnomalyDetector— weighted anomaly score (new=1.0, low-sim=0.7, rare=0.3)pretrain.goPreTrainTemplate/PreTrainTemplates/PreTrainTemplateCountspersist.goSaveJSON/LoadJSON/LoadMinerJSONcoordinator.goCoordinator(plan, tool_call, tool_result, retry, error, finish) +StageSequence+SaveWeightsJSON/LoadWeightsJSONdefaults.godata/default_weights.json;LoadDefaultWeights()preloads embedded templatesminer_test.goanomaly_test.goNew:
pkg/cli/drain3_integration.goIntegration layer connecting
pkg/agentdrainto the existing audit pipeline. Coordinators callLoadDefaultWeights()on startup so trained templates are available immediately:buildDrain3Insights(processedRun, metrics, toolUsage)— converts a single run's structured data intoAgentEvents, mines templates, and returnsObservabilityInsights covering cluster summary, anomaly report, and stage sequence evidence.buildDrain3InsightsMultiRun(processedRuns)— same for cross-run analysis with a shared coordinator, detecting patterns across ≤50 runs.buildDrain3InsightsFromCrossRunInputs(inputs)— convertscrossRunInputentries toProcessedRuns and delegates tobuildDrain3InsightsMultiRun, used by theaudit reportsubcommand.New:
pkg/cli/drain3_train.goTrainDrain3Weights(processedRuns, outputDir, verbose)trains a coordinator across all processed runs and writesdrain3_weights.jsonto the output directory. The file can be committed topkg/agentdrain/data/default_weights.jsonand rebuilt to embed it as the binary default.Modified:
pkg/cli/logs_command.go—--trainflagWhen
--trainis set,DownloadWorkflowLogsrunsTrainDrain3Weightsafter processing all runs and returns an error if training fails.Modified:
pkg/cli/audit_report.goAppends log pattern insights to
ObservabilityInsightsinbuildAuditData():Modified:
pkg/cli/logs_report.goAppends cross-run log pattern insights to
ObservabilityinBuildLogsData():Modified:
pkg/cli/audit_cross_run.go—gh aw audit reportintegrationCrossRunAuditReportnow includes adrain3_insightsfield ([]ObservabilityInsight). Phase 7 ofbuildCrossRunAuditReportmines event templates across all runs in the report. Both markdown and pretty renderers include an "Agent Event Pattern Analysis" section with severity icons (🔴/🟠/🟡/ℹ), category labels, summaries, and evidence strings.New:
cmd/agentdrain-demo/main.goRunnable demo that shows the full pipeline: coordinator setup → pretraining → event ingestion → cluster/template/param/anomaly output → snapshot save/reload → post-restore inference.
Embedding default weights workflow
gh aw logs --train -c 100 cp .github/aw/logs/drain3_weights.json pkg/agentdrain/data/default_weights.json make build # re-embeds the trained weights into the binaryAfter this, all future
gh aw auditandgh aw logsruns preload those templates before processing new events, giving better anomaly detection from the first observation.Testing
pkg/agentdrain/— all passpkg/cli/drain3_integration_test.go— all passpkg/cli/drain3_train_test.go— all pass (including--trainflag presence, JSON structure, stage key assertions)pkg/cli/audit_cross_run_test.go— all pass (field-mapping assertions, insight field validation, markdown rendering)make lint— 0 issuesmake test-unit— all pre-existing failures are unrelated (require live GitHub API access)Design decisions
sync.RWMutexthroughout;MatchusesRLock,Trainuses fullLock--trainreturns error — since the user explicitly requested training, failures are surfaced rather than silently warned