feat: scaffold agentmon services and k8s deploy

Adds Go microservices (ingest-gateway, event-processor, query-api, web-ui), NATS+Postgres wiring, initial schema/init job, ingress manifests for LAN+tailnet, and a multi-arch image build script.
This commit is contained in:
William Valentin
2026-01-17 01:06:57 -08:00
parent a584d7e274
commit 256b841cbf
28 changed files with 1554 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
package postgres
import (
"context"
"database/sql"
"encoding/json"
"errors"
"time"
)
type InsertEvent struct {
EventID string
TS time.Time
Type string
SessionID sql.NullString
RunID sql.NullString
TraceID sql.NullString
SpanID sql.NullString
ParentSpanID sql.NullString
SourceFramework sql.NullString
ClientID sql.NullString
Payload any
}
func (d *DB) InsertEvent(ctx context.Context, e InsertEvent) error {
payload, err := json.Marshal(e.Payload)
if err != nil {
return err
}
_, err = d.sql.ExecContext(ctx, `
insert into events (
event_id, ts, type, session_id, run_id, trace_id, span_id, parent_span_id,
source_framework, client_id, payload
) values (
$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11
)
on conflict (event_id) do nothing
`,
e.EventID,
e.TS,
e.Type,
e.SessionID,
e.RunID,
e.TraceID,
e.SpanID,
e.ParentSpanID,
e.SourceFramework,
e.ClientID,
payload,
)
return err
}
var ErrMissingField = errors.New("missing required field")
+27
View File
@@ -0,0 +1,27 @@
package postgres
import (
"context"
"database/sql"
_ "github.com/jackc/pgx/v5/stdlib"
)
type DB struct {
sql *sql.DB
}
func Open(url string) (*DB, error) {
db, err := sql.Open("pgx", url)
if err != nil {
return nil, err
}
return &DB{sql: db}, nil
}
func (d *DB) Close() error {
return d.sql.Close()
}
func (d *DB) Ping(ctx context.Context) error {
return d.sql.PingContext(ctx)
}
+47
View File
@@ -0,0 +1,47 @@
package postgres
import (
"context"
"encoding/json"
"time"
)
type EventRow struct {
EventID string `json:"event_id"`
TS time.Time `json:"ts"`
Type string `json:"type"`
Payload json.RawMessage `json:"payload"`
}
func (d *DB) ListRecentEvents(ctx context.Context, limit int) ([]EventRow, error) {
if limit <= 0 {
limit = 100
}
if limit > 1000 {
limit = 1000
}
rows, err := d.sql.QueryContext(ctx, `
select event_id, ts, type, payload
from events
order by ts desc
limit $1
`, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var out []EventRow
for rows.Next() {
var r EventRow
if err := rows.Scan(&r.EventID, &r.TS, &r.Type, &r.Payload); err != nil {
return nil, err
}
out = append(out, r)
}
if err := rows.Err(); err != nil {
return nil, err
}
return out, nil
}