prototype: dashed lineStyle against real InfluxDB time series #33

Open
opened 2026-05-26 15:13:01 +00:00 by vps1_gitea_admin · 1 comment

Type: spike / prototype

Depends on: none

Estimate: S (½ day)

Slice — layers touched

InfluxDB write → Grafana panel override → visual confirmation.

Context

PRD Open Question O-2. Two open Grafana bugs (#75259, #86546) affect fieldConfig.custom.lineStyle. Need to confirm the dashed-bounds pattern actually renders before committing the dependent dashed-bounds issue.

Scope

  • Write three Influx fields (flow, flow.min, flow.max) for ~5 minutes into the existing telemetry bucket via a Node-RED inject + influxdb-out (no EVOLV code change).
  • Hand-author a Grafana panel JSON with fieldConfig.overrides[] matching byName: "flow.min" and "flow.max" to custom.lineStyle = {fill: "dash", dash: [10,10]}.
  • Confirm visually: act line solid, bounds dashed, no rendering bug, no "overlapping dashed → solid" artifact (#86546).
  • Screenshot in issue comment.

Out of scope

  • Productionizing the field convention — that's the dependent issue.

Acceptance criteria

  • Screenshot of working dashed bounds against live Influx data attached to this issue.
  • Verdict recorded: "use lineStyle per F-10" OR "fallback to ."
  • If alternative needed, document it.
**Type:** spike / prototype **Depends on:** none **Estimate:** S (½ day) ## Slice — layers touched InfluxDB write → Grafana panel override → visual confirmation. ## Context PRD Open Question O-2. Two open Grafana bugs ([#75259](https://github.com/grafana/grafana/issues/75259), [#86546](https://github.com/grafana/grafana/issues/86546)) affect `fieldConfig.custom.lineStyle`. Need to confirm the dashed-bounds pattern actually renders before committing the dependent dashed-bounds issue. ## Scope - Write three Influx fields (`flow`, `flow.min`, `flow.max`) for ~5 minutes into the existing `telemetry` bucket via a Node-RED inject + influxdb-out (no EVOLV code change). - Hand-author a Grafana panel JSON with `fieldConfig.overrides[]` matching `byName: "flow.min"` and `"flow.max"` to `custom.lineStyle = {fill: "dash", dash: [10,10]}`. - Confirm visually: act line solid, bounds dashed, no rendering bug, no "overlapping dashed → solid" artifact ([#86546](https://github.com/grafana/grafana/issues/86546)). - Screenshot in issue comment. ## Out of scope - Productionizing the field convention — that's the dependent issue. ## Acceptance criteria - [ ] Screenshot of working dashed bounds against live Influx data attached to this issue. - [ ] Verdict recorded: "use `lineStyle` per F-10" OR "fallback to <alternative>." - [ ] If alternative needed, document it.
Author
Owner

Spike findings: confirmed — custom.lineStyle works for dynamic dashed bounds

Verdict: confirmed.

What I did

Wrote 5 minutes (300 points @ 1 Hz) of spike_bounds measurement with three Influx fields (flow, flow.min, flow.max) via POST /api/v2/write with line protocol. Authored a Grafana time-series panel JSON with fieldConfig.overrides[].matcher = byName matching flow.min and flow.max to custom.lineStyle = {fill: "dash", dash: [10, 10]}, plus distinct colors per series. POSTed via POST /api/dashboards/db with overwrite: true. Rendered headless via Playwright + Chromium.

Evidence

dashed-bounds screenshot

Visual outcome:

  • Blue solid line: flow (actual oscillating ~30..70)
  • Red dashed line: flow.max (upper bound, time-varying with cosine)
  • Orange dashed line: flow.min (lower bound, time-varying with sine)
  • No collapse-to-solid on overlap (#86546 not triggered for non-overlapping dashed series).
  • No transform used → #75259 not applicable.

Screenshot lives in repo at .prototypes/spike-dashed-bounds/screenshot.png (gitignored).

Decision points worth recording in issue #38

  1. Influx field names with dots work. flow, flow.min, flow.max round-trip cleanly through line protocol → Flux query → Grafana. No pivot needed when using |> keep(columns: ["_time","_value","_field"]) — Grafana renders each _field value as a separate series and byName matches on the field name.

  2. Use byRegexp for a generic rule, not per-field byName overrides. Production EVOLV fields are 4-segment type.variant.position.childId (e.g. flow.predicted.downstream.default). The per-field-name override pattern would balloon to one override per quantity. Better: one regexp override matching \.min$ and one matching \.max$:

    "overrides": [
      { "matcher": { "id": "byRegexp", "options": "\\.min$" },
        "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash", "dash": [10,10] } } ] },
      { "matcher": { "id": "byRegexp", "options": "\\.max$" },
        "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash", "dash": [10,10] } } ] }
    ]
    

    This rule lives once in the template fragment for any panel that supports bounds, regardless of how many quantities are plotted.

  3. Field-name collision risk. If any real EVOLV field already ends in .min or .max for unrelated reasons, the generic regexp would dash them too. Quick scan against nodes/generalFunctions/src/helper/outputUtils.js and the MeasurementContainer keys is recommended before committing to the .min/.max suffix convention. If collisions exist, fall back to _min / _max suffix or a dedicated tag.

  4. Single-bucket Influx works fine. No need for a separate bucket for bounds — same _measurement = nodeName, same tags, just additional _field entries. Existing Influx schema in PRD is unaffected.

Recommendation for issue #38

Use lineStyle per F-10. Adopt the byRegexp \.min$ / \.max$ matcher pattern in rotatingMachine.json template so the rule is generic across quantities. Before merging: grep the field-name convention to rule out collisions.

Prototype location (do not import)

.prototypes/spike-dashed-bounds/ — dashboard.json, screenshot.png

## Spike findings: confirmed — `custom.lineStyle` works for dynamic dashed bounds **Verdict:** confirmed. ### What I did Wrote 5 minutes (300 points @ 1 Hz) of `spike_bounds` measurement with three Influx fields (`flow`, `flow.min`, `flow.max`) via `POST /api/v2/write` with line protocol. Authored a Grafana time-series panel JSON with `fieldConfig.overrides[].matcher = byName` matching `flow.min` and `flow.max` to `custom.lineStyle = {fill: "dash", dash: [10, 10]}`, plus distinct colors per series. POSTed via `POST /api/dashboards/db` with `overwrite: true`. Rendered headless via Playwright + Chromium. ### Evidence ![dashed-bounds screenshot](attachment-pending-upload) Visual outcome: - Blue solid line: `flow` (actual oscillating ~30..70) - Red dashed line: `flow.max` (upper bound, time-varying with cosine) - Orange dashed line: `flow.min` (lower bound, time-varying with sine) - No collapse-to-solid on overlap (#86546 not triggered for non-overlapping dashed series). - No transform used → #75259 not applicable. Screenshot lives in repo at `.prototypes/spike-dashed-bounds/screenshot.png` (gitignored). ### Decision points worth recording in issue #38 1. **Influx field names with dots work.** `flow`, `flow.min`, `flow.max` round-trip cleanly through line protocol → Flux query → Grafana. No pivot needed when using `|> keep(columns: ["_time","_value","_field"])` — Grafana renders each `_field` value as a separate series and `byName` matches on the field name. 2. **Use `byRegexp` for a generic rule, not per-field `byName` overrides.** Production EVOLV fields are 4-segment `type.variant.position.childId` (e.g. `flow.predicted.downstream.default`). The per-field-name override pattern would balloon to one override per quantity. Better: one regexp override matching `\.min$` and one matching `\.max$`: ```json "overrides": [ { "matcher": { "id": "byRegexp", "options": "\\.min$" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash", "dash": [10,10] } } ] }, { "matcher": { "id": "byRegexp", "options": "\\.max$" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash", "dash": [10,10] } } ] } ] ``` This rule lives **once** in the template fragment for any panel that supports bounds, regardless of how many quantities are plotted. 3. **Field-name collision risk.** If any real EVOLV field already ends in `.min` or `.max` for unrelated reasons, the generic regexp would dash them too. Quick scan against `nodes/generalFunctions/src/helper/outputUtils.js` and the MeasurementContainer keys is recommended before committing to the `.min/.max` suffix convention. If collisions exist, fall back to `_min` / `_max` suffix or a dedicated tag. 4. **Single-bucket Influx works fine.** No need for a separate bucket for bounds — same `_measurement = nodeName`, same tags, just additional `_field` entries. Existing Influx schema in PRD is unaffected. ### Recommendation for issue #38 Use `lineStyle` per F-10. Adopt the `byRegexp` `\.min$` / `\.max$` matcher pattern in `rotatingMachine.json` template so the rule is generic across quantities. Before merging: grep the field-name convention to rule out collisions. ### Prototype location (do not import) `.prototypes/spike-dashed-bounds/` — dashboard.json, screenshot.png
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RnD/EVOLV#33