Previously a per-row scan error was logged and skipped with continue, so a
decode failure (e.g. the UInt64->int64 regression) produced a 200 response
with partial or empty data and no signal to the client. Fail the request
instead so the HTTP handlers return 500. Also check rows.Err() after iteration.
The PostgreSQL model migration regenerated LogScore.ID, MonitorID and
ServerID as signed/pgtype fields, but the ClickHouse log_scores columns
are unsigned (id UInt64, monitor_id/server_id UInt32). clickhouse-go
refuses to scan UInt64 into *int64, so every score row failed to parse
and the scores endpoints returned empty.
Scan each row into locals matching the ClickHouse column types, then
convert into the model, mirroring the existing leap handling. Factor the
shared scan into scanLogScore used by both Logscores and
LogscoresTimeRange.
Replace MySQL driver with pgx/v5 and pgxpool:
- Update sqlc to use postgresql engine
- Convert query.sql to PostgreSQL syntax ($1 params, CASE WHEN,
ANY() arrays)
- Replace sql.DB with pgxpool.Pool throughout
- Change nullable types from sql.Null* to pgtype.*
- Update ID types from uint32 to int64 for PostgreSQL compatibility
- Delete MySQL-specific dynamic_connect.go
- Add opentelemetry.gowrap template for tracing
The askdev origin pattern was missing a slash (https:/* instead of
https://*), so requests from *.askdev.grundclock.com never matched the
CORS allowlist and got no Access-Control-Allow-Origin header.
Requests from the web frontend use /api/data/... paths but the
data-api routes are registered under /api/.... Add a Pre middleware
rewrite rule to strip the /data segment before route matching.
Replace go.ntppool.org/api/config with go.ntppool.org/common/config,
removing the api module dependency entirely.
Also ignore vendor/ directory in .gitignore.
Add a vendor step that uses gitea_token to fetch private modules
from gitea.develooper.com, then subsequent steps use the vendored
dependencies without needing credentials.
GetZoneStatsData and GetZoneStatsV2's netspeed_active values can
exceed 2 billion, causing 32-bit integer overflow. Changed from
int32/uint32 to int (64-bit on modern systems) to handle large
network speed totals.
- Update sqlc column overrides to use int type
- Fix type compatibility in dnsanswers.go zoneTotals map
- Regenerate database code with new types
Fixes https://community.ntppool.org/t/error-message-displayed-on-the-monitoring-score-page/4063
Remove status filter from GetMonitorByNameAndIPVersion query to allow
historical score data for deleted monitors to be accessible when
querying by monitor name/TLS name, making behavior consistent with
ID-based queries.
Score monitors have type='score' and ip_version=NULL, but the
GetMonitorByNameAndIPVersion query required ip_version to match.
This broke monitor lookups by name for score monitors.
Modified query to match either:
- Regular monitors with specified ip_version
- Score monitors with NULL ip_version
Fixes issue reported by Ben Harris at:
https://community.ntppool.org/t/monitor-recentmedian-no-longer-works/4002
- Add parseRelativeTime function supporting "-3d", "-2h", "-30m" format
- Update parseTimeRangeParams to handle Unix timestamps and relative times
- Add unit tests with comprehensive coverage for all time formats
- Document v2 API in API.md with examples and migration guide
Enables intuitive time queries like from=-3d&to=-1h instead of
Unix timestamps, improving developer experience for the enhanced
v2 endpoint that supports 50k records vs legacy 10k limit.
Servers with monitor filtering returned incorrect results when monitors
have same names but different protocols (v4/v6). Monitor lookup now
considers both name and IP version to match the correct protocol.
- Add GetMonitorByNameAndIPVersion SQL query with protocol matching
- Update history parameter parsing to use server IP version context
- Fix both /scores/{ip}/log and Grafana endpoints
- Remove unused GetMonitorByName query
Fixesabh/ntppool#264
Reported-by: Anssi Johansson <https://github.com/avijc>
- Add /api/v2/server/scores/{server}/{mode} endpoint
- Support time range queries with from/to parameters
- Return data in Grafana table format for visualization
- Fix routing pattern to handle IP addresses correctly
- Add comprehensive parameter validation and error handling
Add `/api/v2/test/grafana-table` endpoint to validate Grafana
table format compatibility before implementing the full time
range API.
- Create server/grafana.go with table format structures
- Add structured logging and OpenTelemetry tracing
- Include realistic NTP Pool sample data with null handling
- Set proper CORS and cache headers for testing
- Update implementation plan with Phase 0 completion status
Ready for Grafana JSON API data source integration testing.
- Add RTT column to CSV output (before leap column)
- Add RTT field to JSON ScoresEntry
- Add avg_rtt field to JSON MonitorEntry
- Convert RTT from microseconds to milliseconds
- Calculate average RTT per monitor from history data