Repository navigation
[monitor-config] feat: add generic Grafana dashboard composition framework - #174
a550580874 wants to merge 16 commits into
Conversation
Code half of the Grafana dashboard Jsonnet refactor (supersedes verl-project#171, split per author request). Adds the composition root, base builder modules, deterministic generator, monitor unit tests, and CI wiring. Depends on the companion data-modules PR (common/vllm/sglang.libsonnet).
|
Thanks for your contribution. |
|
|
Back to the proposal itself: the current framework has really only organized the inference-related content of the two dashboards under verl, namely the vLLM and SGLang dashboards. If I wanted to reuse the trainer dashboards under verl, what would I need to do, and how much additional development work would it take? In my view, this framework or pipeline should not focus on specific dashboards. Instead, it should abstract things into sub-dashboards A, B, C, and D, and then provide configuration options showing how A, B, C, and D can be combined to compose new dashboards. |
Reshape the dashboard-as-code proposal into a standalone generic framework, independent of any production dashboard: composer (explicit composition and conflict rules), deterministic generator (gojsonnet binding, --check mode), A/B/C/D example modules with A+B and A+C+D compositions, generic tests, and a README covering motivation, module interface, and extension paths. The production migration (trainer/controller/storage/trajectory and the engine-specific dashboards) follows in verl-project#173. The only change to an existing file is one dependency line in the pyproject test extra. Co-authored-by: multica-agent <github@multica.ai>
|
Thanks for the direction — done. The PR is reshaped into a standalone generic framework and marked ready for review again (head
Local verification: Could you start with the README plus the A/B/C/D example to confirm the design reads right? On the community-meeting walkthrough — that's the member's call rather than mine to promise; if the docs and example turn out to be enough for you, we can skip it, and the member will arrange whatever format you prefer once you've had a look. |
Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
|
Follow-up on the example question: we removed the committed toy example dashboards and their generated JSON to keep this PR lean (~1.2k added lines, 6 files) - the README now carries a short inline example with semantic modules, and the 13 tests build their inputs in tmp_path. The composition model and test coverage are unchanged, and no production dashboard was touched. All checks are green on the current head. |
…face Co-authored-by: multica-agent <github@multica.ai>
…t wheels) Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
…o refactor/grafana-dashboard-jsonnet-code-156
The generic Grafana Jsonnet renderer was a script under `tools/`, bound to the `gojsonnet` Python binding with a `jsonnet` CLI fallback for Windows, where gojsonnet publishes no wheels. That made the evaluator an install-time portability problem and left the runtime pieces outside the installed package. Extract a real runtime core, `rl_insight.grafana.renderer`, exposing `render_dashboards()`, the deterministic `generated_text()` serializer, `materialize_dashboards()` and `stale_dashboards()`. Evaluation now happens in-process through `rjsonnet>=0.5.6`, a base runtime dependency that ships CPython ABI3 wheels for Windows, macOS and Linux, so no Jsonnet CLI, Go toolchain or compiler is needed anywhere. Move `composer.libsonnet` and `viz.libsonnet` into the package (`rl_insight/config/services/grafana/jsonnet/framework/`) so the wheel carries the generic assets and `tools/` keeps no second source of truth. `tools/grafana/framework/generate.py` becomes a thin optional CLI that imports the same core; it no longer implements or shells out to an evaluator. Composer semantics are unchanged: composition order, duplicate/conflict checks, late `ElementReference` resolution, additive `rowItems`, viz defaults and deterministic rendering. Production dashboard JSON is untouched. Co-authored-by: multica-agent <github@multica.ai>
…enderer materialize_dashboards() gains a keyword-only overwrite flag. The default keeps the existing library and optional-CLI behaviour; with overwrite=False every target path is computed and checked before the first write, so a single existing file aborts the whole run with a JsonnetRenderError that names the conflicting paths instead of leaving a partial set behind.
…cument Consolidate the user, dashboard-developer and framework guidance into the canonical pair tools/grafana/framework/README.md and README.zh-CN.md so the upstream tree keeps exactly one Grafana document per language and one optional CLI (tools/grafana/framework/generate.py). Both languages use the same ten sections: Overview, Dashboard developer scenarios, Configuration, Built-in compositions, User customization, How it works, Framework internals, Optional CLI, Testing, Limitations. They document the stable product state: bundled static JSON plus the startup-generated _jsonnet dashboards coexisting in the same Grafana folder, JSON-only Grafana consumption, the configuration-first workflow, the SGLang composition without the NPU module, and a runtime that calls rl_insight.grafana.renderer directly instead of the optional CLI. Co-authored-by: multica-agent <github@multica.ai>
…ion into the archive
… production PR verl-project#174 keeps only generic framework code, tests, the optional CLI, workflow and dependency wiring. The canonical documentation for the framework lives with the dependent production integration PR (verl-project#173) so that this PR stays under the 2000-added-line review budget. Final paths are unchanged: tools/grafana/framework/README.md and tools/grafana/framework/README.zh-CN.md.
What
A standalone, generic dashboard composition framework reviewed independently of any production migration. It contains the framework core, its packaged Jsonnet assets, the single optional CLI, tests, and evaluator setup; the total diff against
mainis 8 files, +1626/−0.The runtime core lives in the installed package
rl_insight/grafana/renderer.pyis the single implementation of evaluation and serialization:render_dashboards(config: Path) -> dict[str, Any]generated_text(dashboard) -> str— deterministic serializer (sorted object fields from the composer plus fixed indentation)materialize_dashboards(config: Path, output_dir: Path, *, overwrite: bool = True) -> list[Path]stale_dashboards(config: Path, expected_dir: Path) -> list[Path]— the comparison behind--checkFRAMEWORK_DIR— the package path holding the generic Jsonnet assetsJsonnetRenderError; its message always names the config path and keeps the Jsonnet stack trace.materialize_dashboards(..., overwrite=False)makes materialization purely additive: every target path is computed first, and if any of them already exists the call writes nothing at all and raisesJsonnetRenderErrornaming the conflicting paths. The preflight runs before the first write, so a collision never leaves a partially materialized set behind. This is generic behaviour with no knowledge of any production naming; the defaultoverwrite=Truekeeps the existing library and optional-CLI behaviour unchanged.rl_insight/grafana/__init__.pyre-exports that API.rl_insight/config/services/grafana/jsonnet/framework/composer.libsonnetandviz.libsonnet— the generic Jsonnet assets now ship inside the package, so the wheel is self-contained andtools/keeps no second source of truth. Both files are moved byte-for-byte (identical blobs to their previoustools/grafana/framework/copies).composer.compose(modules, dashboard)provides explicit conflict rules for panelkey/outputKey/id, owned rows, variables, and ordering references.ElementReferencenames resolve late from panel key to outputKey.rowItems: { <existing row>: [GridLayoutItem, ...] }. These items append to a supported row in module order without creating or overriding it. Unknown or unsupported targets are eager errors; owned-row duplicates remain errors.viz.libsonnetcontains engine-agnostic visualization defaults.Documentation: introduced by the dependent production PR
tools/grafana/framework/README.mdandtools/grafana/framework/README.zh-CN.md— the only Grafana documents the upstream tree keeps, one per language, each following the same structure (Overview, the four dashboard developer scenarios, and the framework extension points).tools/grafana/framework/README.md,tools/grafana/framework/README.zh-CN.md) are unchanged, and this PR's own diff carries no README. [monitor-config] refactor: split Grafana dashboards into reusable modules #173 now carries the maintainer-provided English and Chinese documents._jsonnetversions.rowItems,framework/viz.libsonnetdefaults). No migration-only material appears in either document.Evaluator:
rjsonnetruntime dependencyrjsonnet>=0.5.6is a base runtime dependency inpyproject.toml. It replaces thegojsonnetPython binding plus the WindowsjsonnetCLI fallback.rjsonnetpublishes CPython ABI3 wheels for Windows (x86/x64), macOS (x86_64/arm64/universal2) and the common Linux glibc/musl architectures, sopip install rl-insightis enough on every platform: no Jsonnet CLI, nogo install, no compiler.go install github.com/google/go-jsonnet/cmd/jsonnet@v0.22.0step is removed from.github/workflows/monitor_unit_test.yml, and its path filter now also coversrl_insight/grafana/**andrl_insight/config/services/grafana/**.CLI is a thin optional wrapper
tools/grafana/framework/generate.pyis the only CLI around the framework. It keeps--config,--out-dir,--check,--expected-dirand exit codes0/1/2, but only parses arguments and calls the package core. It does not implement, copy or shell out to an evaluator, and it renders exactly the bytes the core produces.rl_insight.grafana.rendererdirectly, and nothing in the runtime path calls it.Semantics unchanged
variableOrder/rowOrder, lateElementReferenceresolution, additiverowItems, viz defaults and deterministic rendering are all unchanged.rl_insight/config/services/grafana/dashboards/changes.Testing
Validated at head
ee2d2d6332e1ec01801ec2ddd32f4a6a5b217993on macOS (arm64, CPython 3.12):pytest -q tests/monitor/ut/test_grafana_framework.py). The 25 tests from the previous round are preserved; the 5 new tests cover the default overwrite behaviour, additive materialization when no target exists, a single existing target aborting the run withJsonnetRenderErrornaming that path, preflight ordering (a collision on the second dashboard must not write the first one), and every collision being listed when several targets exist. None of them mentions any production dashboard name.pytest -q tests/monitor/ut).ee2d2d6+ [monitor-config] refactor: split Grafana dashboards into reusable modules #17348f827c, merge never pushed): 132 passed, 1 skipped.rl_insight-0.3.0-py3-none-any.whlcontainsrl_insight/grafana/renderer.pyandrl_insight/config/services/grafana/jsonnet/framework/{composer,viz}.libsonnet; installed into a fresh venv (which pulledrjsonnetautomatically), then imported and rendered a composition from a directory outside the repository, withjsonnetoffPATHandgojsonnet/_gojsonnetabsent. Import, asset presence and render all succeeded. The wheel contains notools/, notests/and no migration script.pre-commit run --all-files(ruff, ruff-format, mypy, license, compileall): pass.git diff --check: clean.git diff main -- rl_insight/config/services/grafana/dashboards/: empty.main: 8 files, +1626/−0 —test_grafana_framework.py646,viz.libsonnet396,composer.libsonnet274,renderer.py157,generate.py109,__init__.py37,pyproject.toml5,monitor_unit_test.yml2. The two framework READMEs (375 + 384 lines) are no longer part of this PR; [monitor-config] refactor: split Grafana dashboards into reusable modules #173 introduces them with the maintainer-provided content (blobse1557768…and1709514e…), which is what brings this PR under the 2000-added-line budget without deleting any framework test or core code.Windows is exercised by this PR's CI: the framework tests run there through the same in-process evaluator, with no CLI install step.
Relation to #173
#173 is the dependent production integration and now owns the canonical Grafana documentation (
tools/grafana/framework/README.md+tools/grafana/framework/README.zh-CN.md; same final paths). It composes production content modules over this generic framework, stages the bundled static dashboards and materializes the Jsonnet dashboards beside them withoverwrite=False. This PR contains no production module or composition; documentation ownership moved to #173 only to keep this PR's diff under 2000 added lines.Merge order: #174 first, then #173 adds the README pair that documents this framework.