Merge ticket 055: make ottyl_* reserved params usable in dashboard PromQL queries
Resolved conflicts with ticket 051's unknown-metric guard in evaluate_promql (reordered so ottyl_fmt's categorical rejection and the reserved-name skip both run before 051's declaration/bucket-data check, since ottyl_seq/ottyl_ts are synthesized from the log index and never have a MetricDeclaration or bucket entries) and merged both tickets' additions to the reserved-params Docs.tsx paragraph. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
This commit is contained in:
@@ -107,7 +107,9 @@ const SECTIONS: DocSection[] = [
|
||||
auto-detected format of the line's text — <Code>log_stream</Code> (macOS <Code>log stream</Code> output),{' '}
|
||||
<Code>json</Code>, <Code>logfmt</Code>, or <Code>none</Code>. A <Code>log_stream</Code> line also gets{' '}
|
||||
<Code>log_type</Code>, <Code>process</Code>, and <Code>pid</Code> params derived automatically from its
|
||||
fixed-column header.
|
||||
fixed-column header. All three reserved names also appear (flagged <Code>reserved</Code>) in{' '}
|
||||
<Code>GET /api/params</Code> for discoverability, though there's no UI to edit or remove them — see also{' '}
|
||||
<em>Dashboards</em> below for using <Code>ottyl_seq</Code>/<Code>ottyl_ts</Code> in a panel query.
|
||||
</p>
|
||||
<p className="font-semibold text-text">Date/time formats</p>
|
||||
<p>Timestamp comparisons accept three forms:</p>
|
||||
@@ -338,6 +340,14 @@ const SECTIONS: DocSection[] = [
|
||||
Dashboards are saved per profile, so they travel with it when you switch or copy it — an active profile is
|
||||
required to create or save one; pick or create one from the settings menu first.
|
||||
</p>
|
||||
<p>
|
||||
The reserved <Code>ottyl_seq</Code>/<Code>ottyl_ts</Code> names (see <em>Filtering</em> above) work in panel
|
||||
queries the same as any declared metric — e.g. <Code>count(ottyl_seq)</Code> for log volume, or{' '}
|
||||
<Code>rate(ottyl_ts[1m])</Code> for ingest rate — since every log line carries them without a metric
|
||||
declaration. <Code>ottyl_fmt</Code> is categorical (<Code>json</Code>/<Code>logfmt</Code>/<Code>none</Code>
|
||||
), not a number, so it's rejected in a panel query with an explicit error rather than silently charting
|
||||
nothing — filter on it in the filter bar instead.
|
||||
</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -52,6 +52,12 @@ export function Params({ params, onDeclared }: { params: ParamDeclaration[]; onD
|
||||
const [clearResult, setClearResult] = useState<string | null>(null)
|
||||
const [clearError, setClearError] = useState<string | null>(null)
|
||||
|
||||
// `reserved` params (`ottyl_seq`/`ottyl_ts`/`ottyl_fmt`) are synthesized server-side purely for
|
||||
// discoverability (see `GET /api/params`) — they aren't real declarations, so they're kept out of
|
||||
// the editable/clickable list and shown separately, non-interactively.
|
||||
const declaredParams = useMemo(() => params.filter((p) => !p.reserved), [params])
|
||||
const reservedParams = useMemo(() => params.filter((p) => p.reserved), [params])
|
||||
|
||||
const isBoolean = kind === 'boolean'
|
||||
const isElapsedSinceLast = source === 'elapsed_since_last'
|
||||
// The message match regex doubles as a sample line here so a pasted JSON log line unlocks the
|
||||
@@ -307,8 +313,10 @@ export function Params({ params, onDeclared }: { params: ParamDeclaration[]; onD
|
||||
{clearResult && <div className="mb-1 text-xs text-text-subtle">{clearResult}</div>}
|
||||
{clearError && <div className="mb-1 text-xs text-danger-text">{clearError}</div>}
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{params.length === 0 && <span className="text-xs text-text-faint">No params declared yet.</span>}
|
||||
{params.map((p) => (
|
||||
{declaredParams.length === 0 && (
|
||||
<span className="text-xs text-text-faint">No params declared yet.</span>
|
||||
)}
|
||||
{declaredParams.map((p) => (
|
||||
<button
|
||||
key={p.name}
|
||||
type="button"
|
||||
@@ -330,6 +338,24 @@ export function Params({ params, onDeclared }: { params: ParamDeclaration[]; onD
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
{reservedParams.length > 0 && (
|
||||
<>
|
||||
<div className="mb-1 mt-2 text-xs text-text-subtle">
|
||||
Reserved (built in — present on every line, not editable)
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{reservedParams.map((p) => (
|
||||
<span
|
||||
key={p.name}
|
||||
className="rounded border border-dashed border-border-soft px-2 py-1 text-xs text-text-faint"
|
||||
title={`${p.name} (${p.kind}, reserved)`}
|
||||
>
|
||||
{p.name} ({p.kind})
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user