Add DELETE /api/metrics/{name} to allow deleting a declared metric (ticket 051)
Wires the engine's existing RemoveMetricDeclaration message (previously only used internally by delete_profile's cleanup) up to a new DELETE route, persists the removal into the active profile so it survives a restart, and adds a delete affordance in the Metrics UI. Decisions: - Bucket-value history under the deleted metric's name is purged, not left orphaned (engine.rs's new remove_metric_declaration reuses update_metric's clear_metric_data helper). This is what lets a dashboard panel or PromQL query still referencing the metric by name fail with a readable "unknown metric" error instead of silently returning stale data. - evaluate_promql now errors when a metric has neither a declaration nor any bucket data, since a metric ingested via --metrics-url scraping never gets a MetricDeclaration but must stay queryable. Verified with a seeded fixture (promql_query_against_deleted_metric_fails_with_readable_error in src/api.rs). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
d17cfe9b83
commit
466c81fa94
@@ -3,6 +3,7 @@ import type { TimeRange, TimeRangePresetId } from './LogTimeline'
|
||||
import {
|
||||
ApiError,
|
||||
declareMetric,
|
||||
deleteMetric,
|
||||
fetchMetricBucketValues,
|
||||
fetchMetricDeclarations,
|
||||
fetchParamDeclarations,
|
||||
@@ -166,6 +167,19 @@ export function Metrics({ range, activePreset }: { range: TimeRange | null; acti
|
||||
editMetric(metric)
|
||||
}
|
||||
|
||||
// No confirm-before-delete dialog — matches the rest of this settings UI (e.g. CSS entry / profile
|
||||
// deletion in NavMenu.tsx), which also deletes directly on click rather than prompting first.
|
||||
async function handleDelete(metricName: string) {
|
||||
try {
|
||||
await deleteMetric(metricName)
|
||||
if (selected === metricName) setSelected(null)
|
||||
if (editingName === metricName) resetForm()
|
||||
await loadMetrics()
|
||||
} catch {
|
||||
// best-effort; the declared-metrics list simply keeps showing it if the delete failed
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSubmit(e: React.FormEvent) {
|
||||
e.preventDefault()
|
||||
setSubmitError(null)
|
||||
@@ -312,18 +326,27 @@ export function Metrics({ range, activePreset }: { range: TimeRange | null; acti
|
||||
<div className="mb-3 flex flex-wrap gap-1">
|
||||
{metrics.length === 0 && <span className="text-xs text-text-faint">No metrics declared yet.</span>}
|
||||
{metrics.map((m) => (
|
||||
<button
|
||||
<div
|
||||
key={m.name}
|
||||
onClick={() => selectMetric(m)}
|
||||
className={`rounded border px-2 py-1 text-xs ${
|
||||
className={`flex items-center gap-0.5 rounded border pl-2 pr-1 py-1 text-xs ${
|
||||
selected === m.name
|
||||
? 'border-accent bg-accent/10 text-accent-text'
|
||||
: 'border-border-soft text-text-secondary hover:bg-surface-2'
|
||||
}`}
|
||||
title={m.message_match_regex}
|
||||
>
|
||||
{m.name} ({m.label_params.join(', ') || 'no params'})
|
||||
</button>
|
||||
<button type="button" onClick={() => selectMetric(m)} title={m.message_match_regex}>
|
||||
{m.name} ({m.label_params.join(', ') || 'no params'})
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleDelete(m.name)}
|
||||
className="rounded px-1 text-text-faint hover:bg-danger-bg/50 hover:text-danger-text"
|
||||
aria-label={`Delete metric ${m.name}`}
|
||||
title={`Delete metric "${m.name}"`}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -300,6 +300,10 @@ export function updateMetric(existingName: string, request: MetricDeclaration):
|
||||
return putJson(`/api/metrics/${encodeURIComponent(existingName)}`, request)
|
||||
}
|
||||
|
||||
export function deleteMetric(name: string): Promise<void> {
|
||||
return sendJson(`/api/metrics/${encodeURIComponent(name)}`, 'DELETE')
|
||||
}
|
||||
|
||||
export function fetchMetricBucketValues(
|
||||
name: string,
|
||||
params: {
|
||||
|
||||
Reference in New Issue
Block a user