Private
Public Access
1
0

fix(api): protocol-aware monitor filtering for multi-protocol monitors
All checks were successful
continuous-integration/drone/push Build is passing

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

Fixes abh/ntppool#264
Reported-by: Anssi Johansson <https://github.com/avijc>
This commit is contained in:
2025-07-27 00:37:49 -07:00
parent 8262b1442f
commit eb5459abf3
6 changed files with 135 additions and 103 deletions

View File

@@ -8,7 +8,6 @@ package ntpdb
import (
"context"
"database/sql"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
@@ -82,14 +81,14 @@ func (_d QuerierTxWithTracing) Commit(ctx context.Context) (err error) {
return _d.QuerierTx.Commit(ctx)
}
// GetMonitorByName implements QuerierTx
func (_d QuerierTxWithTracing) GetMonitorByName(ctx context.Context, tlsName sql.NullString) (m1 Monitor, err error) {
ctx, _span := otel.Tracer(_d._instance).Start(ctx, "QuerierTx.GetMonitorByName")
// GetMonitorByNameAndIPVersion implements QuerierTx
func (_d QuerierTxWithTracing) GetMonitorByNameAndIPVersion(ctx context.Context, arg GetMonitorByNameAndIPVersionParams) (m1 Monitor, err error) {
ctx, _span := otel.Tracer(_d._instance).Start(ctx, "QuerierTx.GetMonitorByNameAndIPVersion")
defer func() {
if _d._spanDecorator != nil {
_d._spanDecorator(_span, map[string]interface{}{
"ctx": ctx,
"tlsName": tlsName}, map[string]interface{}{
"ctx": ctx,
"arg": arg}, map[string]interface{}{
"m1": m1,
"err": err})
} else if err != nil {
@@ -103,7 +102,7 @@ func (_d QuerierTxWithTracing) GetMonitorByName(ctx context.Context, tlsName sql
_span.End()
}()
return _d.QuerierTx.GetMonitorByName(ctx, tlsName)
return _d.QuerierTx.GetMonitorByNameAndIPVersion(ctx, arg)
}
// GetMonitorsByID implements QuerierTx

View File

@@ -6,11 +6,10 @@ package ntpdb
import (
"context"
"database/sql"
)
type Querier interface {
GetMonitorByName(ctx context.Context, tlsName sql.NullString) (Monitor, error)
GetMonitorByNameAndIPVersion(ctx context.Context, arg GetMonitorByNameAndIPVersionParams) (Monitor, error)
GetMonitorsByID(ctx context.Context, monitorids []uint32) ([]Monitor, error)
GetServerByID(ctx context.Context, id uint32) (Server, error)
GetServerByIP(ctx context.Context, ip string) (Server, error)

View File

@@ -12,16 +12,24 @@ import (
"time"
)
const getMonitorByName = `-- name: GetMonitorByName :one
const getMonitorByNameAndIPVersion = `-- name: GetMonitorByNameAndIPVersion :one
select id, id_token, type, user_id, account_id, hostname, location, ip, ip_version, tls_name, api_key, status, config, client_version, last_seen, last_submit, created_on, deleted_on, is_current from monitors
where
tls_name like ?
tls_name like ? AND
ip_version = ? AND
is_current = 1 AND
status != 'deleted'
order by id
limit 1
`
func (q *Queries) GetMonitorByName(ctx context.Context, tlsName sql.NullString) (Monitor, error) {
row := q.db.QueryRowContext(ctx, getMonitorByName, tlsName)
type GetMonitorByNameAndIPVersionParams struct {
TlsName sql.NullString `db:"tls_name" json:"tls_name"`
IpVersion NullMonitorsIpVersion `db:"ip_version" json:"ip_version"`
}
func (q *Queries) GetMonitorByNameAndIPVersion(ctx context.Context, arg GetMonitorByNameAndIPVersionParams) (Monitor, error) {
row := q.db.QueryRowContext(ctx, getMonitorByNameAndIPVersion, arg.TlsName, arg.IpVersion)
var i Monitor
err := row.Scan(
&i.ID,