[ { "id": "metrics-demo-tab", "type": "tab", "label": "POD Gateway · Metrics output", "disabled": false, "info": "Central Gateway metrics flow. It calls the free Open-Meteo API without an API key, exports Prometheus metrics and shows the raw latency events. Install @yroshcha/node-red-contrib-nodered-metrics before importing this flow." }, { "id": "metrics-demo-server", "type": "pod-gateway-server-config", "name": "Central Gateway + Redis", "host": "0.0.0.0", "port": 8080, "path": "/ws", "redisUrl": "redis://127.0.0.1:6379", "redisRejectUnauthorized": true, "redisKeyPrefix": "pod-gateway-metrics-demo", "redisConsumer": "metrics-demo-gateway", "redisMaxQueueSize": 10000, "redisResultTtlSeconds": 3600, "redisDeleteOnAck": true, "redisRetryPollMs": 250, "rateLimits": "{\"weather\":{\"rate\":10,\"burst\":2}}", "concurrency": 8, "upstreamTimeoutMs": 60000, "maxAttempts": 0, "verboseLogging": true, "credentials": {} }, { "id": "metrics-demo-api", "type": "pod-gateway-api-config", "name": "Open-Meteo public API", "baseUrl": "https://api.open-meteo.com", "headers": "{\"Accept\":\"application/json\"}", "apiKeyHeader": "", "apiKeyPrefix": "", "credentials": {} }, { "id": "metrics-demo-adapter", "type": "pod-gateway-adapter", "name": "GET Kyiv weather", "server": "metrics-demo-server", "api": "metrics-demo-api", "operation": "weather/getKyivCurrent", "label": "Open-Meteo · Kyiv current weather", "path": "/v1/forecast?latitude=50.4501&longitude=30.5234¤t=temperature_2m,relative_humidity_2m,wind_speed_10m&timezone=Europe/Kyiv", "method": "GET", "headers": "{}", "idempotencyHeader": "", "description": "Fetch current Kyiv weather from the free Open-Meteo API without an API key." }, { "id": "metrics-demo-connector", "type": "pod-gateway-config", "name": "Local POD connector", "url": "ws://127.0.0.1:8080/ws", "podId": "pod-metrics-demo", "connectTimeout": 10000, "reconnectInterval": 3000, "verboseLogging": true, "credentials": {} }, { "id": "metrics-demo-inject", "type": "inject", "z": "metrics-demo-tab", "name": "Call free Kyiv weather API", "props": [{ "p": "payload" }], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "{}", "payloadType": "json", "x": 160, "y": 120, "wires": [["metrics-demo-call"]] }, { "id": "metrics-demo-call", "type": "pod-gateway-call", "z": "metrics-demo-tab", "name": "Gateway Call: Open-Meteo", "gateway": "metrics-demo-connector", "operation": "weather/getKyivCurrent", "timeout": 60000, "priority": "normal", "x": 410, "y": 120, "wires": [["metrics-demo-result"], ["metrics-demo-error"]] }, { "id": "metrics-demo-result", "type": "debug", "z": "metrics-demo-tab", "name": "API result", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 650, "y": 100, "wires": [] }, { "id": "metrics-demo-error", "type": "debug", "z": "metrics-demo-tab", "name": "Gateway error", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 650, "y": 140, "wires": [] }, { "id": "metrics-demo-output", "type": "pod-gateway-metrics", "z": "metrics-demo-tab", "name": "Gateway Metrics → connect palette here", "server": "metrics-demo-server", "events": "request.completed", "x": 220, "y": 300, "wires": [["metrics-demo-debug", "metrics-demo-latency", "metrics-prom-request-count", "metrics-prom-total-latency"]] }, { "id": "metrics-demo-debug", "type": "debug", "z": "metrics-demo-tab", "name": "Raw gateway metric", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 560, "y": 280, "wires": [] }, { "id": "metrics-demo-latency", "type": "function", "z": "metrics-demo-tab", "name": "Extract latency for metrics palette", "func": "const metric = (msg.metric && typeof msg.metric === 'object') ? msg.metric : ((msg.payload && typeof msg.payload === 'object') ? msg.payload : {})\nconst timings = (metric.timings && typeof metric.timings === 'object') ? metric.timings : {}\nconst asNumber = value => {\n const number = Number(value)\n return Number.isFinite(number) ? number : null\n}\nconst upstreamMs = asNumber(timings.upstreamMs ?? (metric.event === 'upstream.completed' ? metric.durationMs : null))\nconst totalMs = asNumber(timings.totalMs ?? (metric.event === 'request.completed' ? metric.durationMs : null))\nif (upstreamMs === null && totalMs === null) return null\nmsg.topic = `${msg.topic || 'pod-gateway'}/latency`\nmsg.payload = {\n service: metric.service || '',\n operation: metric.operation || '',\n outcome: metric.outcome || metric.status || '',\n ...(upstreamMs === null ? {} : { upstreamMs }),\n ...(totalMs === null ? {} : { totalMs })\n}\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 570, "y": 340, "wires": [["metrics-demo-latency-debug"]] }, { "id": "metrics-demo-latency-debug", "type": "debug", "z": "metrics-demo-tab", "name": "Latency fields", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 840, "y": 340, "wires": [] }, { "id": "metrics-demo-upstream-output", "type": "pod-gateway-metrics", "z": "metrics-demo-tab", "name": "Gateway Metrics: upstream latency", "server": "metrics-demo-server", "events": "upstream.completed", "x": 250, "y": 440, "wires": [["metrics-demo-upstream-debug", "metrics-prom-upstream-latency"]] }, { "id": "metrics-demo-upstream-debug", "type": "debug", "z": "metrics-demo-tab", "name": "Upstream metric event", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 590, "y": 420, "wires": [] }, { "id": "metrics-prom-request-count", "type": "nodered-metric", "z": "metrics-demo-tab", "name": "Prom: Gateway requests", "metric": "metrics-prom-request-config", "operation": "inc", "autoStep": false, "step": "", "stepType": "str", "status": "success", "statusType": "str", "value": "1", "valueType": "num", "duration": "", "durationType": "num", "durationUnit": "seconds", "labels": [ { "name": "service", "value": "payload.service", "valueType": "msg" }, { "name": "operation", "value": "payload.operation", "valueType": "msg" }, { "name": "outcome", "value": "payload.outcome", "valueType": "msg" } ], "x": 570, "y": 500, "wires": [] }, { "id": "metrics-prom-total-latency", "type": "nodered-metric", "z": "metrics-demo-tab", "name": "Prom: Gateway total latency", "metric": "metrics-prom-request-config", "operation": "observe", "autoStep": false, "step": "", "stepType": "str", "status": "success", "statusType": "str", "value": "1", "valueType": "num", "duration": "payload.timings.totalMs", "durationType": "msg", "durationUnit": "ms", "labels": [ { "name": "service", "value": "payload.service", "valueType": "msg" }, { "name": "operation", "value": "payload.operation", "valueType": "msg" }, { "name": "outcome", "value": "payload.outcome", "valueType": "msg" } ], "x": 600, "y": 540, "wires": [] }, { "id": "metrics-prom-upstream-latency", "type": "nodered-metric", "z": "metrics-demo-tab", "name": "Prom: Upstream API latency", "metric": "metrics-prom-upstream-config", "operation": "observe", "autoStep": false, "step": "", "stepType": "str", "status": "success", "statusType": "str", "value": "1", "valueType": "num", "duration": "payload.durationMs", "durationType": "msg", "durationUnit": "ms", "labels": [ { "name": "service", "value": "payload.service", "valueType": "msg" }, { "name": "operation", "value": "payload.operation", "valueType": "msg" }, { "name": "outcome", "value": "payload.outcome", "valueType": "msg" } ], "x": 600, "y": 580, "wires": [] }, { "id": "metrics-prom-exporter", "type": "nodered-metrics-exporter", "z": "metrics-demo-tab", "name": "Prometheus endpoint", "path": "/nodeRedMetrics", "x": 220, "y": 660, "wires": [] }, { "id": "metrics-prom-request-config", "type": "nodered-metric-config", "name": "Gateway completed requests", "metricType": "counter", "metricName": "nodered_gateway_requests_total", "help": "Completed requests handled by the central POD Gateway", "labelNames": "service,operation,outcome", "buckets": "", "withDuration": true, "prefix": "nodered_" }, { "id": "metrics-prom-upstream-config", "type": "nodered-metric-config", "name": "Gateway upstream API latency", "metricType": "histogram", "metricName": "nodered_gateway_upstream_duration_seconds", "help": "External API request duration measured by the central POD Gateway", "labelNames": "service,operation,outcome", "buckets": "0.1,0.25,0.5,1,2,5,10,30,60", "withDuration": false, "prefix": "nodered_" } ]