feat(plugins): add playground plugin for filter/rule simulation#2346
Merged
Conversation
🛑 AI review — Sensitive area, extra care recommendedThis PR touches critical paths or introduces changes the model cannot judge with sufficient confidence. Review carefully before merging. 🛑
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
Adds a new event-processor plugin
com.utmstack.playgroundthat exposes an HTTP REST API for testing filters and rules against sample logs without touching production. Runs colocated with the event-processor manager, gated byMODE=manager, and supervises the EPplayground -watchdaemon as a child process.What ships
New plugin —
plugins/playground/:8091, internal to the swarm network (not published to the host).X-Internal-Keyheader, matched against the sharedcom.utmstackSDK config (same pattern assoc-aiandinputs).playground -initonce to scaffold/playground-workdir, then supervisesplayground -watchas a child process with automatic restart on exit.X-Internal-Keygated except/health):POST /playground/filters— write a filter YAMLPOST /playground/rules— write a rule YAMLPOST /playground/filters/copy— clear-then-copy production filtersPOST /playground/rules/copy— clear-then-copy production rulesDELETE /playground/filters— clear playground filter filesDELETE /playground/rules— clear playground rule filesPOST /playground/run— submit a log, wait for parsed event + optional alertGET /playground/status— idle | running (with current uuid)GET /health— unauthenticated healthcheckInstaller (
installer/docker/compose.go)PLAYGROUND_BASE_URL=http://event-processor-manager:8091added to the backend service (same pattern asSOC_AI_BASE_URL)./playground-workdirhost volume mount added toevent-processor-managerso the plugin's shared filesystem survives container restarts.CI (
.github/workflows/v12-deployment-pipeline.yml)playgroundadded to thebuild_pluginsmatrix. No Dockerfile change is needed —event_processor.Dockerfilealready copies the entire./plugin-binaries/directory, and the new artifact is picked up automatically via theplugin-bin-*merge pattern.Why
Testing new filters or correlation rules currently requires modifying production configuration and observing live traffic, which is risky. The playground provides a safe, scripted way to submit a log and observe how it flows through the parsing and correlation pipelines — enabling both manual debugging (via
curl/Postman) and future analyst-facing UI features (the backend consumesPLAYGROUND_BASE_URL).Key design decisions
playground -watchas a long-running child so the pipeline stays warm between calls.POST /runwritesinput/<uuid>.json, then polls the JSONL outputs the daemon appends.Alert.events[].id, notAlert.id.cel/generateAlertin the EP assigns a fresh UUID toAlert.idthat is unrelated to the triggering event. The original event id only survives insideAlert.events[], so that's what we match on. Documented inrunner/scan.go.protojson.Marshal, notencoding/json. The daemon reads inputs withutils.StringToProtoMessage(protojson-backed). The two serializations diverge on fields whose protobuf JSON name differs from the Go json tag — notablyTimestamp, which protojson emits as@timestampandencoding/jsonwould emit astimestamp(silently dropped by the daemon).TimedOutis a normal outcome (HTTP 200 withtimedOut: true), not a 504. A log that doesn't match any filter is a valid debugging result, not a server error.log.id, the Runner generates one viauuid.NewString()and returns it in the response so clients can submit lightweight requests without pre-generating IDs.POST /runuseshttp.MaxBytesReader(1 MiB) on the request body.Reference
No tracking issue — internal feature request.