Ext Ops Panel
Dashboard öffnen

Start/Doks/Eigene Metriken

Vertrag für eigene Metriken

Vertragsversion 2.1.0 · Payload schema_version 2.0

Mit eigenen Metriken liefert der Dienst Ihrer Erweiterung die Zahlen, auf die es ihm ankommt (Conversions, Umsatz, Backend-Zustand, Trichter), in dasselbe Panel, das bereits Installationen und den Zustand im Chrome Web Store verfolgt. Der Vertrag ist metadatengesteuert und bedient zwei Oberflächen: Jede Metrik deklariert, wo und wie sie im Dashboard und im Telegram-Status erscheint, sodass das Panel ein generischer Renderer ohne produktspezifischen Code bleibt.

↓ OpenAPI 3.1 (YAML) herunterladen /custom-metrics-openapi.yaml · info.version 2.1.0

1. Funktionsweise (zwei Oberflächen)

Ihr Dienst stellt einen Metrik-Endpunkt bereit. Ext Ops Panel ist der Client: Es ruft diesen Endpunkt ab (nie umgekehrt) und stellt die Antwort dar. Die Antwort steuert zwei Oberflächen gleichzeitig:

Das Panel führt Ihre Metriken mit den panel-eigenen Basismetriken zusammen (Installationen / Deinstallationen / Neuinstallationen / Feedback / Chrome Web Store / Zustand), die im reservierten Tab base und in der gleichnamigen Telegram-Zeile liegen.

2. Der Endpunkt und die Authentifizierung

Das Panel ruft Ihren Endpunkt per GET auf und erwartet die v2-Payload als Antwort mit Status 200. Zwei Abrufmodi haben dieselbe Form:

Als Authentifizierung dient eines von none, bearer oder api_key_header. Geheimnisse werden im Panel-Backend verschlüsselt gespeichert und nie an die Dashboard-Erweiterung weitergegeben. Schlägt ein Abruf fehl, degradiert das Panel kontrolliert (letzter Snapshot oder ausgeblendet), ohne die Basismetriken zu beeinträchtigen.

3. Payload-Struktur

Die Payload der obersten Ebene enthält das Layout (Tabs, Abschnitte, Telegram-Zeilen) und das Metrik-Array.

FeldTypHinweise
schema_versionstringErforderlich. Muss "2.0" sein.
generated_atstring (date-time)Wann die Payload erstellt wurde (Frische-/Leerlauferkennung).
tabsTab[]Dashboard-Tabs. Siehe Abschnitt 4.
sectionsSection[]Gruppen von Metriken innerhalb eines Tabs (tab, id, title, order).
telegramTelegramMetaheader-Vorlage + lines[]. Siehe Abschnitt 7.
metricsMetric[]Die Metriken selbst. Siehe Abschnitte 5 und 6.

4. Tabs und Tab-Symbole

Ein Tab ist { id, title, order, icon? }. Der reservierte Tab base gehört dem Panel selbst (icon="layout-dashboard"); Ihr Dienst ergänzt die übrigen. Sind viele Tabs geöffnet, zeigt der aktive Tab Symbol + Titel, die anderen schrumpfen auf das Symbol (der Titel bleibt im Tooltip und im aria-label).

Zwei Tab-IDs sind für das Panel reserviert: base (der Basic-Tab) und monitoring (der eingebaute Monitoring-Tab, den Heartbeat-Berichte füllen, siehe den Monitoring-Vertrag). Deklarieren Sie sie nicht in tabs: eine Deklaration wird ignoriert, Titel, Icon und Reihenfolge legt das Panel fest. Metriken adressieren sie weiterhin über dashboard.tab.

Der Wert icon ist eines von zwei Dingen:

Das Panel liefert einen kuratierten Katalog von 60 Lucide-Namen (schlank für das MV3-Bundle). Derselbe Katalog dient für Tab-Symbole und Ziel-Symbole (Abschnitt 5.3):

5. Metrik: Wert + zwei Platzierungsblöcke

Eine Metrik trägt einen typisierten Wert plus zwei unabhängige Blöcke: dashboard (wo und wie in der Erweiterung) und telegram (wo und wie in der Nachricht). Jeder kann weggelassen oder über show:false ausgeblendet werden, sodass eine Metrik auch nur auf einer Oberfläche erscheinen kann.

FeldHinweise
idStabile Metrik-ID, eindeutig in der Payload.
kindDatentyp (Abschnitt 5.1). Bestimmt, welche Wertfelder gelten.
labelKanonische, menschenlesbare Bezeichnung.
value und die Felder der ArtPayload-Felder hängen von kind ab (Abschnitt 5.1).
severityEiner von ok, info, warn, crit (bestimmt Farbe / Emoji).
shareableOptionaler Boolean, Standard true. Bei false ist die Metrik nur für den Inhaber sichtbar: In einem schreibgeschützt geteilten Projekt wird sie serverseitig entfernt und erreicht nie einen Beobachter / eine öffentliche Ansicht (für Finanzmetriken gedacht). Regelt den Zugriff, nicht die Platzierung.
dashboard{ show, tab, section, order, name, render, options } (Abschnitt 5.2).
telegram{ show, line, pos, format, sep, when } (Abschnitte 6 und 8).

5.1. Arten (Datentyp + Payload)

Arten sind eine offene Menge: Eine unbekannte Art ignoriert der Renderer (vorwärtskompatibel).

kindPayload-FelderAnwendungsbeispiel
numbervalue (+ optional delta, unit)Installations- / Feedback-Zahlen
deltavalue, delta (rendert 1200 (+72))insgesamt (+heute)
percentvalue (0 bis 100)Erfolgsquote der Engine
durationseconds oder minutesp50/p95/avg, Frische
bytesbytes oder kbAusgabegröße (~522 KB)
ratingvalue, count5,0★ (1)
moneyvalue, currency, optional deltaMRR, Ausgaben
statusstate + severityZustandsampel
seriespoints:[{date,count}], optional mehrere series:[{name,points}], gestapelt mit stack: truetägliche Installationen, aktive Nutzer
intradayseries:[{name,intraday:[{minute,value}]}], optional step_min (Standard 15), tzheute in 15-Minuten-Zeitfenstern
hour_histogram{ weekdays:[...], start, end, tz }Conversions pro Stunde
funnelsteps:[{key,label,value}]Preisseite bis Checkout
breakdownitems:[{label,value,unit?,sub?/money?,country?,parts?}], optional ranges:{today,week,month,all}Abos nach Tarif, nach Engine, nach Oberfläche; Besuche nach Quelle oder Land
listitems:[{text,count?,severity?}] auf der obersten Ebene der Metrik, nicht unter valueletzte Fehler
tableitems:[{…}], ein Objekt pro Zeile; Spalten aus dashboard.options.columns, sonst die Schlüssel der ersten ZeileWarteschlangen, letzte Sendungen
textvalue (string)Freitext

Eine Metrik table:

{ "id": "queues", "kind": "table", "label": "Mail queues",
  "items": [ { "queue": "outbound", "size": 3, "oldest": "2m" },
             { "queue": "deferred", "size": 0, "oldest": "-" } ],
  "dashboard": { "show": true, "tab": "backend", "section": "engines", "order": 5, "render": "table",
                 "options": { "columns": ["queue", "size", "oldest"] } } }

5.2. Darstellung (Anzeige im Dashboard)

dashboard.render wählt die Darstellung (entspricht meist kind, kann aber abweichen, z. B. ein percent als badge zeigen). Ebenfalls eine offene Menge.

renderDarstellungOptionen (dashboard.options)
kpiKarte: Name + großer Wert + Delta; mit stack die Teile in einer Reihe unter dem Werttone, stack
badgeStatus-Badge / Piktogramm nach Schweregrad–
chartLiniendiagramm (Monat/Gesamtzeit, gleitender 7-Tage-Durchschnitt, Hover); mit stack: true gestapelte Säulen pro Tag mit einer Zeile „Gesamt“ (Total)series, defaultMode, stack
intradayHeute nach Zeitfenstern (96 pro UTC-Tag): gestapelte Balken oder geglättete Linien, Zeitachse HH:MM, Hover-Anzeige über alle Reihenmode (bars | lines, Standard lines)
hour_histogramStündliche Balken, gruppiert nach Werktagen / Wochenende / Wochentagseries
funnelSchritte mit Conversion-Rate dazwischen–
breakdownHorizontale kategoriale Balken mit Wert + Anteil am Gesamtwert. Mit ranges ein Umschalter heute / 7 Tage / 30 Tage / gesamt; mit map: countries eine Weltkarte über der Liste; mit stack Balken aus umschaltbaren Teilenitems, defaultRange, map, stack
tableTabelle (z. B. Feedback)columns
textAbsatz / inline–
statusAmpelzustand nach Schweregrad–
listListe von Einträgen mit optionaler Anzahl / Schweregrad–

intraday vs. chart. Die Achse von chart ist täglich (points[].date = YYYY-MM-DD), und seine Monatsansicht zeigt nur die letzten 30 Punkte, daher passen die 96 Zeitfenster von heute nicht hinein. intraday ist das panel-eigene Heute-Diagramm, als Vertragsart bereitgestellt: dieselbe Konvention, bei der minute die Minuten ab Beginn des UTC-Tages zählt (0, 15, …, 1425), aber Reihen und Daten deklariert die Quelle. Senden Sie nur nicht leere Zeitfenster, den Rest füllt das Panel auf.

Ein leeres Zeitfenster ist null, nicht 0. Bei einem Durchschnitt (z. B. mittlere Conversion-Zeit) wäre eine Null gelogen, deshalb bricht die Linie ab, statt auf null zu fallen. Ein fehlendes Zeitfenster und value: null sind gleichwertig: Die Linie bricht ab, es wird kein Balken gezeichnet, und die Hover-Anzeige zeigt einen Strich.

Gestapelt: Gesamtwert und Teile in einem Diagramm und einer Liste. Wenn sich eine Metrik aus Teilen zusammensetzt (etwa die Seitenaufrufe zweier Websites), senden Sie Gesamtwert und Teile als EINE Metrik: Das Panel zeichnet die Teile übereinander, und die Legende schaltet jeden Teil ein und aus, ohne zusätzliche Tabs und ohne Dropdown-Filter. Beide Erweiterungen sind additiv: Ein Renderer, der sie nicht kennt, zeichnet dieselbe Metrik wie bisher.

Diagramm: kind: "series" mit dashboard.options.stack: true. Die Reihen werden in Array-Reihenfolge gestapelt, die erste ist die unterste Schicht. Das Panel zeichnet eine Säule pro Tag (in der Gesamtzeit pro 7-Tage-Fenster) mit einem Segment pro sichtbarer Reihe, sodass die Oberkante einer Säule genau die Summe der sichtbaren Reihen ist; ein Tag, an dem alle null sind, hat keine Säule. Ein Klick auf einen Legendeneintrag blendet eine Schicht aus (die letzte sichtbare bleibt an); der Rest wird ab null neu gezeichnet, und die Werteachse folgt der sichtbaren Summe. Beim Hovern über eine Säule oder beim Wechsel mit den Pfeiltasten zeigt die Anzeige jede sichtbare Schicht und eine Zeile Total. Die Gesamtzeit stapelt den gleitenden 7-Tage-Durchschnitt jeder Reihe, markiert mit ~. Jeder andere Wert von stack behält die überlagerten Linien bei.

Liste: kind: "breakdown" mit dashboard.options.stack als geordneter Liste von Teilen [{key, label}] und parts: {"key": number} an jedem Element, in items und in jedem ranges-Fenster. value muss der Summe aller Teile entsprechen. Das Panel zeigt pro Teil einen Chip, der ihn für die ganze Karte über alle Fenster hinweg umschaltet. Eine Zeile zeigt die Summe ihrer sichtbaren Teile, Zeilen mit null werden ausgeblendet, die Liste wird nach dieser Summe neu sortiert, und der Balken wird in ein Segment pro sichtbarem Teil geteilt. Mit map: "countries" folgen die Kreise den sichtbaren Summen. Ein Element ohne parts zählt vollständig, egal was ausgeschaltet ist.

{ "id": "site_sources", "kind": "breakdown", "label": "Sources",
  "items": [ { "label": "Search engines", "value": 812, "parts": { "makcards": 790, "journalingapp": 22 } } ],
  "ranges": { "today": [ { "label": "Search engines", "value": 30, "parts": { "makcards": 29, "journalingapp": 1 } } ],
              "month": [ { "label": "Search engines", "value": 812, "parts": { "makcards": 790, "journalingapp": 22 } } ] },
  "dashboard": { "show": true, "tab": "site", "section": "site_sources", "render": "breakdown",
                 "options": { "defaultRange": "month",
                              "stack": [ { "key": "makcards", "label": "makcards.online" },
                                         { "key": "journalingapp", "label": "journalingapp.app" } ] } } }

Kachel: eine kpi-Kachel vom Typ number oder delta nimmt dieselbe dashboard.options.stack-Liste und parts: {"key": number} an der Metrik selbst. Der große Wert bleibt value und muss der Summe aller Teile entsprechen. Darunter zeigt das Panel die Teile in einer Reihe in der Reihenfolge des Stapels (auf einer schmalen Kachel bricht die Reihe um), in der Farbe, die derselbe Name auf einem gestapelten Diagramm des Tabs hat; ein Teil mit null wird abgeschwächt dargestellt. Die Kachel hat keine Schalter. Die Kopfzeilen der Projektliste und Telegram lesen weiterhin value.

{ "id": "site_views_today", "kind": "number", "label": "Page views", "value": 42,
  "parts": { "portal": 30, "cabinet": 4, "backoffice": 8 },
  "dashboard": { "show": true, "tab": "site", "section": "site_today", "render": "kpi",
                 "options": { "stack": [ { "key": "portal", "label": "zakazindia.ru" },
                                         { "key": "cabinet", "label": "Client cabinet" },
                                         { "key": "backoffice", "label": "Backoffice" } ] } } }

5.3. Die Projektliste: Nutzer und Ziele aus dem Basis-Tab

Die Projektliste zeigt einige Zahlen eines Webdienstes, ohne ihn zu öffnen. Das Panel liest sie nur aus dem base Tab, und nur wenn die Metrik einen numerischen value hat. Der erste Treffer gewinnt.

MetrikWie das Panel sie findetWo sie angezeigt wird
DAU, WAU, MAUDie id, das label oder der Dashboard-Name ist genau dau, wau oder mau (Groß- und Kleinschreibung egal).WAU und MAU in der Spalte Nutzer, DAU in Heute.
Ziele 1 bis 3Die id ist genau goal_1, goal_2 oder goal_3.Heute, in derselben Zeile wie DAU: ein Symbol und eine Zahl.

Ein Ziel ist eine Zielaktion Ihrer Nutzer: Registrierungen, Käufe, gesendete Formulare. Sie wählen das Zeitfenster der Zahl, und das Panel zeigt sie unverändert. Wir empfehlen, heute zu zählen und das Zeitfenster im Label zu nennen (zum Beispiel Registrierungen heute). Das Label ist der Tooltip, bis zu 80 Zeichen. Das Feld icon nimmt einen Namen aus dem Katalog in Abschnitt 4; Emoji werden für Ziele nicht akzeptiert. Ohne Symbol oder mit einem unbekannten Namen zeichnet das Panel target. Eine Null wird als gedämpfter Strich angezeigt.

{ "id": "goal_1", "kind": "number", "label": "Sign-ups today", "value": 12, "icon": "user-plus",
  "dashboard": { "show": true, "tab": "base", "section": "goals", "render": "kpi" } }

Das Panel speichert nur die letzten Werte, wie bei DAU. Jeder erfolgreiche Abruf ersetzt sie, und ein Ziel, das nicht mehr in der Antwort ist, verschwindet aus der Liste.

Mehrere Oberflächen

Eine Custom-Metrics-Quelle gehört zu einer Oberfläche Ihres Dienstes, und das Panel speichert die Zahlen pro Oberfläche. Die Projektliste zeigt ihre Summe; die Projektseite zeigt jede Oberfläche einzeln.

Chrome-Erweiterungen

Eine Erweiterung nutzt dieselbe Konvention. Sendet ihr Feed dau und Ziele auf dem Tab base, zeigt die Projektliste sie in einer weiteren Zeile unter den Zählern für Installationen, Deinstallationen, Feedback und Neuinstallationen, im selben Format wie die Heute-Zeile eines Webdienstes.

5.4. Schwellenwerte (warn und crit)

Eine numerische Metrik kann thresholds enthalten. Dann berechnet das Panel die Severity der Metrik selbst, bei jedem Abruf und bei jeder Heartbeat-Annahme, und zeigt die Grenzen neben dem Wert: 41 (threshold 20/100), gelb zwischen warn und crit, rot ab crit. Die Severity, die Ihr Dienst für eine solche Metrik sendet, wird durch die berechnete ersetzt.

FeldBedeutung
directionabove: schlechter, wenn höher (Warteschlange, CPU). below: schlechter, wenn niedriger (freier Speicher, verbleibende Tage).
warn, critZahlen. Bei above ist ein Wert ab warn gelb und ab crit rot; below spiegelt das. Bei above darf warn nicht über crit liegen, bei below nicht darunter.
unitOptionale Beschriftung bis 16 Byte für die Angabe: threshold 80/95%.
recoverOptionale Hysterese: Eine Metrik, die warn oder crit war, kehrt erst zu ok zurück, wenn der Wert recover überschritten hat; dazwischen bleibt sie warn.
{
  "id": "queue",
  "kind": "number",
  "label": "Mail queue",
  "value": 41,
  "thresholds": { "direction": "above", "warn": 20, "crit": 100, "recover": 15 },
  "dashboard": { "show": true, "tab": "backend", "section": "mail", "order": 1, "render": "kpi" },
  "telegram": { "show": true, "line": "mail", "pos": 10, "format": "queue {value}", "when": "severity>=warn" }
}

Geplante Abfrage. Bei einem Webdienst können Sie in den Einstellungen einer Quelle die geplante Abfrage einschalten. Das Panel ruft den Endpunkt dann in einem Intervall ab, das von der Untergrenze Ihres Tarifs (5 Minuten bei Trial und Indie, 1 Minute bei Studio und Fleet) bis 24 Stunden reicht, mit derselben Anfrage wie jeder Abruf: ein ehrlicher User-Agent und höchstens eine Anfrage pro Minute. Sie belegt eine Monitoring-Unit und ist daher bei Free nicht verfügbar. Ein überschrittener Schwellenwert öffnet einen Vorfall für diese Metrik und benachrichtigt Sie; eine wiederholte Überschreitung benachrichtigt nicht erneut. Der Vorfall schließt nach einem Abruf ohne Überschreitung, wenn das Intervall 1 Stunde oder länger ist, und nach zwei Abrufen in Folge ohne Überschreitung, wenn es kürzer ist. Ein fehlgeschlagener Abruf ändert nichts und zeigt seinen Grund als letzten Fehler. Bis zu 20 Metriken mit Schwellenwerten pro Quelle erzeugen Vorfälle.

6. Die Palette gehört dem Panel

Diagramm- und Reihenfarben vergibt das Panel aus Marken-Tokens, nicht die Quelle. options.series[] trägt nur die Identität ({key,label,order}); ein Feld color in der Payload ist nur ein Hinweis und wird ignoriert. Semantische Schlüssel werden festen Tokens zugeordnet (paid der Akzentfarbe, free einem gedämpften Neutralton, failed/error der Gefahrenfarbe, ready/success der Erfolgsfarbe); andere Schlüssel erhalten die kategoriale Markenpalette der Reihe nach. Flächen und Linien der Reihen haben in beiden Themes mindestens 3:1 Kontrast (WCAG 1.4.11), Text und Beschriftungen mindestens 4,5:1. Das schützt die Marke vor beliebigen externen Hex-Farben.

7. Telegram-Vorlagen

telegram.header ist die Kopfzeile der Nachricht; telegram.lines[] sind logische Zeilen ({ id, order, prefix, when }). Der Composer sammelt jede Metrik mit einem bestimmten telegram.line, filtert nach when, sortiert nach pos, rendert jede über ihre Vorlage format und verbindet sie mit dem sep der jeweiligen Metrik. Das prefix der Zeile wird zuerst ausgegeben. Alles ist reiner Text.

PlatzhalterAusgabe
{value}Nach Art (Zahl 1,200; Prozent 99%)
{value:k}1.2k / 3.0M (kompakt)
{delta:+}+72 / -3
{value:pct}99%
{seconds:dur}28s / 5m 47s
{minutes:age}45m / 2h 30m / never
{bytes:size}~522KB / 1.4MB
{value}★ ({count})5.0★ (1)
{sev}Schweregrad-Emoji: 🟢 ok, 🟡 warn, 🔴 crit, ⚪ idle
{threshold}Der Schwellenwert der Metrik: threshold 20/100. Fehlt er im Format, wird bei einer Metrik mit Schwellenwerten (threshold 20/100) angehängt.
{trend}↗ / ↘ (±5 pp vs. 7 Tage)

8. Sichtbarkeitsbedingungen (when)

when steuert, ob ein Metrikfeld (oder eine ganze Telegram-Zeile) angezeigt wird. Werte:

whenZeigt das Feld an
alwaysImmer (Standard).
nonzeroNur wenn der Wert nicht 0 / leer ist.
severity>=warnNur wenn der Schweregrad warn oder crit ist.
changedNur wenn er sich seit dem vorherigen Snapshot geändert hat.

Unbekannte when-Werte verhalten sich wie always (vorwärtskompatibel).

9. Beispiel-Payload

{
  "schema_version": "2.0",
  "generated_at": "2026-07-02T23:17:30Z",
  "tabs": [
    { "id": "conv", "title": "Conversions", "order": 1, "icon": "trending-up" }
  ],
  "sections": [
    { "tab": "conv", "id": "by_hour", "title": "By hour", "order": 0 }
  ],
  "telegram": {
    "header": "{name} • {cws.users} • {cws.rating}★ ({cws.rating_count})",
    "lines": [
      { "id": "base", "order": 0 },
      { "id": "conv", "order": 1, "prefix": "{sev} Conv " }
    ]
  },
  "metrics": [
    {
      "id": "conv_today",
      "kind": "number",
      "label": "Conversions today",
      "value": 254,
      "severity": "ok",
      "shareable": true,
      "dashboard": {
        "show": true,
        "tab": "conv", "section": "by_hour", "order": 10,
        "name": "Today", "render": "kpi", "options": {}
      },
      "telegram": {
        "show": true,
        "line": "conv", "pos": 20,
        "format": "today {value}", "sep": " • ", "when": "always"
      }
    }
  ]
}
Es wird nur natives v2 unterstützt. Ihr Dienst liefert Metriken plus ein fertiges Layout gemäß diesem Vertrag; Konnektoren für Altformate gibt es nicht. Arten und Darstellungsarten stammen aus den oben deklarierten Mengen; unbekannte werden ignoriert, sodass eine neuere Quelle nie einen älteren Panel-Build bricht.

10. Der maschinenlesbare Vertrag

Die formale, importierbare Beschreibung dieses Endpunkts ist die OpenAPI-3.1-Datei. Sie trägt dieselbe Vertragsversion (2.1.0) und ist das einzige kanonische maschinenlesbare Artefakt, gemeinsam für alle Sprachen.

↓ OpenAPI 3.1 (YAML) herunterladen /custom-metrics-openapi.yaml