feat: add Prometheus metrics endpoint
Maintainer thường phản hồi trong vòng 1 ngày
@cameri đang làm issue này rồi.
Từ ngày 2/5/2026.
Đánh giá
Issue này chưa được đánh giá.
Mô tả
Description
Right now there's no way to know what's happening on a running nostream relay without connecting directly to the database. No connection counts, no event throughput, no latency data. You're flying blind.
Proposal
Two things:
A GET /metrics endpoint that returns standard Prometheus text format. Operators who already run Prometheus + Grafana can point a scrape config at it and get dashboards immediately with no extra work.
Example output:
# HELP nostream_connections_active Current number of active WebSocket connections
# TYPE nostream_connections_active gauge
nostream_connections_active 42
# HELP nostream_connections_total Total WebSocket connections since process start
# TYPE nostream_connections_total counter
nostream_connections_total 18340
# HELP nostream_events_received_total Events received from clients
# TYPE nostream_events_received_total counter
nostream_events_received_total{kind="1"} 52341
nostream_events_received_total{kind="7"} 12032
# HELP nostream_events_accepted_total Events written to the database
# TYPE nostream_events_accepted_total counter
nostream_events_accepted_total 48210
# HELP nostream_events_rejected_total Events rejected before storage
# TYPE nostream_events_rejected_total counter
nostream_events_rejected_total{reason="rate-limited"} 2891
nostream_events_rejected_total{reason="invalid"} 340
nostream_events_rejected_total{reason="blocked"} 900
# HELP nostream_subscriptions_active Current active REQ subscriptions
# TYPE nostream_subscriptions_active gauge
nostream_subscriptions_active 156
# HELP nostream_eose_duration_seconds Time from REQ received to EOSE sent
# TYPE nostream_eose_duration_seconds histogram
nostream_eose_duration_seconds_bucket{le="0.01"} 18200
nostream_eose_duration_seconds_bucket{le="0.05"} 31200
nostream_eose_duration_seconds_bucket{le="0.1"} 38900
nostream_eose_duration_seconds_bucket{le="0.5"} 42100
nostream_eose_duration_seconds_bucket{le="1"} 42800
nostream_eose_duration_seconds_bucket{le="5"} 42990
nostream_eose_duration_seconds_bucket{le="+Inf"} 43001
nostream_eose_duration_seconds_sum 4312.94
nostream_eose_duration_seconds_count 43001
# HELP nostream_db_query_duration_seconds Database query latency
# TYPE nostream_db_query_duration_seconds histogram
nostream_db_query_duration_seconds_bucket{le="0.005"} 39100
nostream_db_query_duration_seconds_bucket{le="0.01"} 45210
nostream_db_query_duration_seconds_bucket{le="0.025"} 47300
nostream_db_query_duration_seconds_bucket{le="0.05"} 48100
nostream_db_query_duration_seconds_bucket{le="0.1"} 48900
nostream_db_query_duration_seconds_bucket{le="0.5"} 49150
nostream_db_query_duration_seconds_bucket{le="+Inf"} 49200
nostream_db_query_duration_seconds_sum 621.33
nostream_db_query_duration_seconds_count 49200
Also a simple GET /stats page for operators who don't run Grafana , just a server-rendered HTML page using the same Bootstrap template pattern as the existing /, /invoices, and /terms pages.
Both endpoints are disabled by default and opt-in via settings.yaml
How it works
A MetricsStore singleton holds all counters and histograms in memory. Each component calls into it directly:
WebSocketServerAdapterincrements connection counters on open/closeWebSocketAdaptertracks active subscription countEventMessageHandlerincrements event counters per kind and per rejection reasonSubscribeMessageHandlerrecords EOSE latencyEventRepositoryrecords query latency
Plan
I'll split this into smaller PRs:
PR 1 : MetricsStore + settings flag + tests. No routes yet, just the data structure.
PR 2 : GET /metrics route + connection and subscription counters wired up. At this point you can actually curl the endpoint.
PR 3 : Event counters: received/accepted/rejected by kind and reason, wired into EventMessageHandler.
PR 4 : Latency histograms: EOSE duration in the subscribe handler, query duration in the event repository.
PR 5 : GET /stats HTML page for operators who prefer a browser over Prometheus.
PR 6 : Docs: metric reference + a docker-compose example with a Prometheus + Grafana sidecar for operators who want to set up the full stack.
- Ngôn ngữ chính
- TypeScript
- Star
- 829
- Fork
- 234
- Merge trung bình
- 4 ngày 5 giờ
- Pull request đã merge (30 ngày)
- 22
Chuẩn bị môi trường
- Có Dockerfile hoặc tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của cameri/nostream
-
validateSettings() doesn't validate rateLimits[].period — zero period silently degrades to a 1ms backoff hintCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
cameri/nostream#811 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
-
feat(nip77): negentropy reconciliation core for the PostgreSQL backendCó thể đã có người làm @Priyanshubhartistm đã nhận 2 ngày trước. Đang mởenhancement
cameri/nostream#801 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
feat(admin): bounded NIP-66 probe history and Network Health timelineCó thể đã có người làm @Ferryx349 đã nhận 3 ngày trước. Đang mởAdmin Console enhancement
cameri/nostream#800 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Store relay settings overrides in PostgreSQL (SETTINGS_BACKEND=db)Có thể đã có người làm @Ferryx349 đã nhận 36 ngày trước. Đang mởenhancement
cameri/nostream#757 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của cameri/nostream
Issue tương tự
-
bug cli service
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày
-
create-element: same editorAlias silent-fallback bug as #201, not covered by that fixCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mởgenerated-by-ai
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
umbraco/Umbraco-CMS-MCP-Editor#208 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Table: Space fires onActivate in single-selection mode — the reference doc and the JSDoc disagreeĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
sidorares/react-x11-components#764 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
backnotprop/plannotator#1840 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
JoviDeCroock/pracht#432 ·
Maintainer thường phản hồi trong vòng 1 ngày