Documentation
¶
Index ¶
- func GzipMiddleware(next http.Handler) http.Handler
- type Broker
- func (b *Broker) ClientCount() int
- func (b *Broker) LastNotifyUnix() int64
- func (b *Broker) LastSource() string
- func (b *Broker) Notify()
- func (b *Broker) NotifyCount() int64
- func (b *Broker) NotifySource(source string)
- func (b *Broker) Subscribe() chan string
- func (b *Broker) Unsubscribe(ch chan string)
- type CalendarResponse
- type Handler
- func (h *Handler) Calendar(w http.ResponseWriter, r *http.Request)
- func (h *Handler) Close()
- func (h *Handler) CodexCalendar(w http.ResponseWriter, r *http.Request)
- func (h *Handler) CodexDaily(w http.ResponseWriter, r *http.Request)
- func (h *Handler) CodexDashboard(w http.ResponseWriter, r *http.Request)
- func (h *Handler) CodexDurations(w http.ResponseWriter, r *http.Request)
- func (h *Handler) CodexIntraday(w http.ResponseWriter, r *http.Request)
- func (h *Handler) CodexModels(w http.ResponseWriter, r *http.Request)
- func (h *Handler) CodexRequests(w http.ResponseWriter, r *http.Request)
- func (h *Handler) CodexSessions(w http.ResponseWriter, r *http.Request)
- func (h *Handler) DailyModel(w http.ResponseWriter, r *http.Request)
- func (h *Handler) Dashboard(w http.ResponseWriter, r *http.Request)
- func (h *Handler) Durations(w http.ResponseWriter, r *http.Request)
- func (h *Handler) Events(w http.ResponseWriter, r *http.Request)
- func (h *Handler) Health(w http.ResponseWriter, r *http.Request)
- func (h *Handler) HourlyModel(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ImportDelete(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ImportInspect(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ImportStart(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ImportStatus(w http.ResponseWriter, r *http.Request)
- func (h *Handler) InitImports() error
- func (h *Handler) Intraday(w http.ResponseWriter, r *http.Request)
- func (h *Handler) Models(w http.ResponseWriter, r *http.Request)
- func (h *Handler) PricingCollection(w http.ResponseWriter, r *http.Request)
- func (h *Handler) PricingLookup(w http.ResponseWriter, r *http.Request)
- func (h *Handler) PricingRecompute(w http.ResponseWriter, r *http.Request)
- func (h *Handler) PricingSuggest(w http.ResponseWriter, r *http.Request)
- func (h *Handler) Rate(w http.ResponseWriter, r *http.Request)
- func (h *Handler) Register(mux *http.ServeMux)
- func (h *Handler) Requests(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SessionRate(w http.ResponseWriter, r *http.Request)
- func (h *Handler) Sessions(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SetOTLPHTTPBound(f func() bool)
- func (h *Handler) SetPricer(p pricing.Registry)
- func (h *Handler) SetPricingWriter(w pricing.Writer)
- func (h *Handler) SetShutdownContext(ctx context.Context)
- func (h *Handler) Status(w http.ResponseWriter, r *http.Request)
- type HourlyResponse
- type ImportFileStatus
- type ImportJobError
- type ImportJobStatus
- type IntradayResponse
- type PagedResponse
- type PricingLookupResponse
- type PricingStatus
- type RateResponse
- type StatusResponse
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Broker ¶
type Broker struct {
// contains filtered or unexported fields
}
Broker manages SSE client channels.
Each Notify call broadcasts a "source" tag (`claude`, `codex`, or `all`) so the web UI can selectively refresh the active tab. Notify() (no args) is kept for backward compatibility and tags the event as "claude".
func (*Broker) ClientCount ¶
func (*Broker) LastNotifyUnix ¶
func (*Broker) LastSource ¶
LastSource returns the source tag of the most recent broadcast, or "" if no broadcast has happened yet.
func (*Broker) Notify ¶
func (b *Broker) Notify()
Notify broadcasts a Claude-tagged update. Equivalent to NotifySource("claude").
func (*Broker) NotifyCount ¶
func (*Broker) NotifySource ¶
NotifySource broadcasts an update tagged with the given source.
func (*Broker) Unsubscribe ¶
type CalendarResponse ¶
type CalendarResponse struct {
Data []db.CalendarDay `json:"data"`
}
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler serves the REST API and SSE endpoints for the cc-otel web dashboard.
func NewHandler ¶
func NewHandler(repo *db.Repository, broker *Broker, cfg *config.Config, configPath string) *Handler
NewHandler creates a Handler with the given database repository, SSE broker, config, and the absolute path of the config file the daemon actually loaded.
func (*Handler) Calendar ¶
func (h *Handler) Calendar(w http.ResponseWriter, r *http.Request)
Calendar returns compact per-day aggregates for the dashboard usage calendar.
func (*Handler) Close ¶
func (h *Handler) Close()
Close cancels active inspection/import work and waits for file users to exit.
func (*Handler) CodexCalendar ¶
func (h *Handler) CodexCalendar(w http.ResponseWriter, r *http.Request)
CodexCalendar returns compact per-day aggregates for the Codex usage calendar.
func (*Handler) CodexDaily ¶
func (h *Handler) CodexDaily(w http.ResponseWriter, r *http.Request)
CodexDaily returns paged per-(date, model) rollup rows for the Codex tab.
func (*Handler) CodexDashboard ¶
func (h *Handler) CodexDashboard(w http.ResponseWriter, r *http.Request)
CodexDashboard returns aggregated KPI cards for the Codex tab.
func (*Handler) CodexDurations ¶
func (h *Handler) CodexDurations(w http.ResponseWriter, r *http.Request)
CodexDurations returns per-model latency stats. Token-throughput columns are always zero since Codex does not emit per-request token rates.
func (*Handler) CodexIntraday ¶
func (h *Handler) CodexIntraday(w http.ResponseWriter, r *http.Request)
CodexIntraday returns per-(time-bucket, model) Codex stats.
func (*Handler) CodexModels ¶
func (h *Handler) CodexModels(w http.ResponseWriter, r *http.Request)
CodexModels returns the distinct list of Codex models seen so far.
func (*Handler) CodexRequests ¶
func (h *Handler) CodexRequests(w http.ResponseWriter, r *http.Request)
CodexRequests returns paged Codex API request rows.
func (*Handler) CodexSessions ¶
func (h *Handler) CodexSessions(w http.ResponseWriter, r *http.Request)
CodexSessions returns paged session aggregates.
func (*Handler) DailyModel ¶
func (h *Handler) DailyModel(w http.ResponseWriter, r *http.Request)
DailyModel returns per-day, per-model token usage and cost with pagination.
func (*Handler) Dashboard ¶
func (h *Handler) Dashboard(w http.ResponseWriter, r *http.Request)
Dashboard returns aggregated token usage and cost KPIs for a date range.
func (*Handler) Durations ¶
func (h *Handler) Durations(w http.ResponseWriter, r *http.Request)
Durations returns per-model average duration stats for the selected date range. Query:
- from=YYYY-MM-DD&to=YYYY-MM-DD (preferred)
- or range=today|week|month|all
- optional: model=<name> to filter down to a single model
- optional: limit=<n> (default 2000, max 2000)
func (*Handler) Events ¶
func (h *Handler) Events(w http.ResponseWriter, r *http.Request)
Events streams Server-Sent Events to the client, pushing "update" on each new OTEL record.
func (*Handler) Health ¶
func (h *Handler) Health(w http.ResponseWriter, r *http.Request)
Health reports database connectivity (200 ok, 503 error).
func (*Handler) HourlyModel ¶
func (h *Handler) HourlyModel(w http.ResponseWriter, r *http.Request)
HourlyModel returns per-hour, per-model token usage and cost for a single local day. Query params: - date=YYYY-MM-DD (optional; defaults to today) - model=<name> (optional filter)
func (*Handler) ImportDelete ¶
func (h *Handler) ImportDelete(w http.ResponseWriter, r *http.Request)
func (*Handler) ImportInspect ¶
func (h *Handler) ImportInspect(w http.ResponseWriter, r *http.Request)
func (*Handler) ImportStart ¶
func (h *Handler) ImportStart(w http.ResponseWriter, r *http.Request)
func (*Handler) ImportStatus ¶
func (h *Handler) ImportStatus(w http.ResponseWriter, r *http.Request)
func (*Handler) InitImports ¶
InitImports initializes the singleton database-import manager. Initialization failure does not prevent the dashboard from starting; import endpoints report the stored error as unavailable.
func (*Handler) Intraday ¶
func (h *Handler) Intraday(w http.ResponseWriter, r *http.Request)
Intraday returns per-(time-bucket, model) stats across a [from, to] window of at most 7 local days, bucketed at 5/10/15/30/60 minutes. Designed for the Intraday bar-chart view; defaults to today + 30-min buckets.
Query params:
- from=YYYY-MM-DD, to=YYYY-MM-DD (optional; default = today)
- range=<today|week|month|all> (used only if from/to omitted)
- bucket=5|10|15|30|60 (default 30)
- model=<name> (optional filter)
func (*Handler) Models ¶
func (h *Handler) Models(w http.ResponseWriter, r *http.Request)
Models returns the distinct model names seen in the database.
func (*Handler) PricingCollection ¶
func (h *Handler) PricingCollection(w http.ResponseWriter, r *http.Request)
PricingCollection handles GET (list), POST (upsert), DELETE over model_pricing. Prices are USD/Mtok on the wire and USD/token in storage, so POST divides by perMtokFactor and GET multiplies back.
func (*Handler) PricingLookup ¶
func (h *Handler) PricingLookup(w http.ResponseWriter, r *http.Request)
PricingLookup answers "why does cc-otel think model X costs Y?". Useful when a row's cost_usd looks wrong: hit /api/pricing/lookup?model=glm-4.6 to confirm whether the registry resolved at all and which entry won.
func (*Handler) PricingRecompute ¶
func (h *Handler) PricingRecompute(w http.ResponseWriter, r *http.Request)
PricingRecompute handles GET (status) / POST (start) for the background full-table recompute. State is server-side and singleton: GET never starts a job; POST while a job is already running is a no-op that returns the current status. One job at a time.
func (*Handler) PricingSuggest ¶
func (h *Handler) PricingSuggest(w http.ResponseWriter, r *http.Request)
PricingSuggest handles GET /api/pricing/suggest — a user-initiated OpenRouter price lookup used to prefill the manual-entry form. It never writes. The response carries the default one-click price (first-party "Official" provider when OpenRouter lists one, else the blended minimum) plus a "providers" list + "providers_total" for the picker. A non-match returns a zero-valued SuggestResult (Matched=false).
func (*Handler) Rate ¶
func (h *Handler) Rate(w http.ResponseWriter, r *http.Request)
Rate returns per-(bucket, model) token throughput over time for the rate chart.
func (*Handler) Requests ¶
func (h *Handler) Requests(w http.ResponseWriter, r *http.Request)
Requests returns individual API request records with optional model and date filters.
func (*Handler) SessionRate ¶
func (h *Handler) SessionRate(w http.ResponseWriter, r *http.Request)
SessionRate returns token throughput for the most recent 1-minute window in which the given session had API activity (duration_ms > 0).
func (*Handler) Sessions ¶
func (h *Handler) Sessions(w http.ResponseWriter, r *http.Request)
Sessions returns per-session aggregated stats with pagination.
func (*Handler) SetOTLPHTTPBound ¶
SetOTLPHTTPBound supplies the predicate /api/status uses to report OTLP/HTTP receiver health. Pass the daemon's own bind state, not a port probe.
func (*Handler) SetPricer ¶
SetPricer injects the pricing registry used by /api/status and /api/pricing/lookup. Done via setter (rather than another constructor argument) to avoid churning every existing call site.
func (*Handler) SetPricingWriter ¶
SetPricingWriter injects the pricing Writer used by /api/pricing CRUD. nil (the default) makes the collection endpoint return 503.
func (*Handler) SetShutdownContext ¶
SetShutdownContext supplies the context used to cancel a background recompute goroutine when the daemon shuts down. If unset, the recompute runs against context.Background.
type HourlyResponse ¶
type HourlyResponse struct {
Date string `json:"date"`
Data []db.HourlyModelSummary `json:"data"`
}
type ImportFileStatus ¶
type ImportJobError ¶
type ImportJobStatus ¶
type ImportJobStatus struct {
JobID string `json:"job_id"`
State importState `json:"state"`
Phase dbmerge.Phase `json:"phase"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
ExpiresAt int64 `json:"expires_at,omitempty"`
Retryable bool `json:"retryable"`
File ImportFileStatus `json:"file"`
Progress dbmerge.Progress `json:"progress"`
Preview *dbmerge.Inspection `json:"preview"`
Result *dbmerge.Result `json:"result"`
Error *ImportJobError `json:"error"`
}
type IntradayResponse ¶
type IntradayResponse struct {
From string `json:"from"`
To string `json:"to"`
BucketMinutes int `json:"bucket_minutes"`
Data []db.IntradayModelSummary `json:"data"`
}
IntradayResponse wraps Intraday for the JSON envelope; From/To are inclusive local YYYY-MM-DD; BucketMinutes echoes back the granularity actually used so the client can label its axis without re-deriving it.
type PagedResponse ¶
type PricingLookupResponse ¶
type PricingLookupResponse struct {
Query string `json:"query"`
Found bool `json:"found"`
Kind string `json:"kind"` // "exact" | "alias" | "prefix" | "miss"
MatchedKey string `json:"matched_key,omitempty"`
Source string `json:"source,omitempty"`
Input float64 `json:"input,omitempty"`
Output float64 `json:"output,omitempty"`
CacheRead float64 `json:"cache_read,omitempty"`
CacheWrite float64 `json:"cache_creation,omitempty"`
IsClaude bool `json:"is_claude"` // Claude is intentionally absent — surfaced so callers know why
}
PricingLookupResponse describes one model lookup against the registry. Returned by /api/pricing/lookup.
type PricingStatus ¶
type PricingStatus struct {
TableSize int `json:"table_size"`
UserOverrides int `json:"user_overrides"`
LastEditAt int64 `json:"last_edit_at"`
MissCount24h int `json:"miss_count_24h"`
MissModelsTop []string `json:"miss_models_top"`
}
PricingStatus mirrors pricing.Snapshot with JSON-friendly names. Kept separate so the api package doesn't expose the internal struct directly.
type RateResponse ¶
type RateResponse struct {
From string `json:"from"`
To string `json:"to"`
BucketMinutes int `json:"bucket_minutes"`
Data []db.RateBucket `json:"data"`
}
RateResponse wraps the rate-over-time buckets in a JSON envelope. From/To are inclusive local YYYY-MM-DD; BucketMinutes echoes the granularity actually used.
type StatusResponse ¶
type StatusResponse struct {
ServerTimeUnix int64 `json:"server_time_unix"`
DBOK bool `json:"db_ok"`
SSEClients int `json:"sse_clients"`
LastUpdate int64 `json:"last_update_unix"`
NotifyCount int64 `json:"notify_count"`
WebPort int `json:"web_port"`
OTELPort int `json:"otel_port"`
OTLPHTTPPort int `json:"otlp_http_port"`
OTELReceiverListening bool `json:"otel_receiver_listening"`
OTLPHTTPReceiverListening bool `json:"otlp_http_receiver_listening"`
// ConfigPath is the absolute path of the config file this daemon loaded at startup.
// DBPath is the resolved SQLite path after yaml + CC_OTEL_DB_PATH env override.
ConfigPath string `json:"config_path"`
DBPath string `json:"db_path"`
// Pricing is omitted when no pricing registry is wired (legacy callers /
// tests). The frontend Server Status popup keys off the presence of this
// block to decide whether to render the Pricing row.
Pricing *PricingStatus `json:"pricing,omitempty"`
}