Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
cache: true
- name: Verify pinned engine, typed Parquet and SQL boundary
run: >-
bash scripts/with-duckdb.sh go test ./internal/query ./internal/telemetry ./internal/observability ./internal/ingest
bash scripts/with-duckdb.sh go test ./internal/engine ./internal/telemetry ./internal/observability ./internal/ingest
-run 'TestPinnedEngine|TestSQLBoundary|TestLogicalType|TestVariant|TestUnsupportedFormat|TestCommitBatchAllocation|TestDependencies|TestExportsBound|TestMaximumAttributeNesting|TestHTTPRejectsExcessiveAttributeNesting'
-count=1

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ jobs:
run: |
set -euo pipefail
version="${GITHUB_REF_NAME}"
bash scripts/with-duckdb.sh go test ./internal/query -run 'TestPinnedEngine|TestSQLBoundary' -count=1
bash scripts/with-duckdb.sh go test ./internal/engine -run 'TestPinnedEngine|TestSQLBoundary' -count=1
mkdir -p stage
bash scripts/with-duckdb.sh go build -trimpath -ldflags "-s -w -X main.version=${version}" -o stage/fanout ./cmd/fanout
for doc in LICENSE NOTICE README.md THIRD_PARTY_NOTICES TRADEMARK.md; do
Expand Down
4 changes: 2 additions & 2 deletions cmd/fanout-docgen/mcptools.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"strings"

"github.com/labstack/fanout/internal/mcp"
"github.com/labstack/fanout/internal/panel"
"github.com/labstack/fanout/internal/query"
)

// toolCount is set by renderMCPTools so the summary line can report it.
Expand Down Expand Up @@ -156,7 +156,7 @@ func renderMCPTools() ([]byte, error) {
}

b.WriteString("## Panel SQL relations\n\n")
relations := panel.SQLRelations()
relations := query.SQLRelations()
names := make([]string, 0, len(relations))
for name := range relations {
names = append(names, name)
Expand Down
8 changes: 4 additions & 4 deletions cmd/fanout/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ import (
"github.com/labstack/fanout/internal/auth"
"github.com/labstack/fanout/internal/config"
"github.com/labstack/fanout/internal/dashboard"
"github.com/labstack/fanout/internal/engine"
"github.com/labstack/fanout/internal/ingest"
"github.com/labstack/fanout/internal/intelligence"
"github.com/labstack/fanout/internal/mcp"
appmetrics "github.com/labstack/fanout/internal/metrics"
"github.com/labstack/fanout/internal/observability"
"github.com/labstack/fanout/internal/panel"
"github.com/labstack/fanout/internal/query"
"github.com/labstack/fanout/internal/server"
"github.com/labstack/fanout/internal/settings"
Expand Down Expand Up @@ -134,7 +134,7 @@ func main() {
defer repository.Close()

// DuckDB is the query facade over open Parquet and its indexed trace sidecars.
q, err := query.NewDuck(ctx, cfg, repository)
q, err := engine.NewDuck(ctx, cfg, repository)
if err != nil {
slog.Error("duckdb init failed", "err", err)
os.Exit(1)
Expand Down Expand Up @@ -275,9 +275,9 @@ func main() {
// Route both HTTP and MCP reads through Duck's retrying adapter. Passing the
// raw *sql.DB here bypassed the Telemetry maintenance-race protection.
queries := observability.New(q, q, cfg.RetentionDays)
panels := panel.NewExecutor(q, cfg.RetentionDays)
panels := query.NewExecutor(q, cfg.RetentionDays)
panels.SetRollupReader(queries)
api.RegisterPanelRoutes(e, panels)
api.RegisterQueryRoutes(e, panels)
api.RegisterFanQLRoutes(e, q, panels)
api.RegisterAnnotationRoutes(e, annotations.New(q))
api.RegisterTraceRoutes(e, queries, cfg.RetentionDays)
Expand Down
6 changes: 3 additions & 3 deletions docs/diagrams/architecture.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,17 +279,17 @@
],
"sources": [
{
"path": "internal/query/duck.go",
"path": "internal/engine/duck.go",
"line": 240,
"end_line": 244
},
{
"path": "internal/query/duck.go",
"path": "internal/engine/duck.go",
"line": 505,
"end_line": 522
},
{
"path": "internal/query/duck.go",
"path": "internal/engine/duck.go",
"line": 627,
"end_line": 653
}
Expand Down
12 changes: 6 additions & 6 deletions docs/diagrams/persistence.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
"row": 1,
"sources": [
{
"path": "internal/query/duck.go",
"path": "internal/engine/duck.go",
"line": 240,
"end_line": 244
}
Expand All @@ -162,12 +162,12 @@
"row": 2,
"sources": [
{
"path": "internal/query/duck.go",
"path": "internal/engine/duck.go",
"line": 627,
"end_line": 653
},
{
"path": "internal/query/duck.go",
"path": "internal/engine/duck.go",
"line": 692,
"end_line": 693
},
Expand All @@ -187,17 +187,17 @@
"row": 1,
"sources": [
{
"path": "internal/query/duck.go",
"path": "internal/engine/duck.go",
"line": 505,
"end_line": 522
},
{
"path": "internal/query/duck.go",
"path": "internal/engine/duck.go",
"line": 1437,
"end_line": 1437
},
{
"path": "internal/query/duck.go",
"path": "internal/engine/duck.go",
"line": 1622,
"end_line": 1622
}
Expand Down
2 changes: 1 addition & 1 deletion docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ The native tests exercise whole-window totals, bounded newest buckets
and width-aware 24-hour bucket selection:

```sh
just test ./internal/panel -run 'TestGaugeTotalsMatchStat|TestBudgetKeepsCompleteNewestBuckets|TestWidthAwareCellBuckets'
just test ./internal/query -run 'TestGaugeTotalsMatchStat|TestBudgetKeepsCompleteNewestBuckets|TestWidthAwareCellBuckets'
```

Use the pinned engine wrapper through `just test`, with the workspace's offline
Expand Down
8 changes: 4 additions & 4 deletions internal/agent/committed_panic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
agtypes "github.com/ag-ui-protocol/ag-ui/sdks/community/go/pkg/core/types"
"github.com/labstack/fanout/internal/dashboard"
fanoutmcp "github.com/labstack/fanout/internal/mcp"
"github.com/labstack/fanout/internal/panel"
"github.com/labstack/fanout/internal/query"
controlstore "github.com/labstack/fanout/internal/store"
)

Expand All @@ -27,14 +27,14 @@ func TestRuntimePanicDistinguishesCommittedSave(t *testing.T) {
if _, err := db.DB.Exec(`INSERT INTO users(id,email) VALUES ('owner','owner@example.test')`); err != nil {
t.Fatal(err)
}
service := dashboard.New(db.DB, panel.NewExecutor(nil, 30))
server := fanoutmcp.NewWithIntelligence(registryQueries{}, service, panel.NewExecutor(nil, 30), nil, "test")
service := dashboard.New(db.DB, query.NewExecutor(nil, 30))
server := fanoutmcp.NewWithIntelligence(registryQueries{}, service, query.NewExecutor(nil, 30), nil, "test")
registry, err := NewToolRegistry(t.Context(), server.MCP())
if err != nil {
t.Fatal(err)
}
defer registry.Close()
spec := panel.Dashboard{Name: "Committed", Panels: []panel.Panel{{ID: "note", Title: "Note", Viz: "text", Content: "hello"}}}
spec := query.Dashboard{Name: "Committed", Panels: []query.Panel{{ID: "note", Title: "Note", Viz: "text", Content: "hello"}}}
input, err := json.Marshal(map[string]any{"dashboard": spec})
if err != nil {
t.Fatal(err)
Expand Down
18 changes: 9 additions & 9 deletions internal/agent/dashboard_eval_golden_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (
agtypes "github.com/ag-ui-protocol/ag-ui/sdks/community/go/pkg/core/types"
"github.com/labstack/fanout/internal/config"
"github.com/labstack/fanout/internal/dashboard"
"github.com/labstack/fanout/internal/engine"
fanoutmcp "github.com/labstack/fanout/internal/mcp"
"github.com/labstack/fanout/internal/panel"
"github.com/labstack/fanout/internal/query"
controlstore "github.com/labstack/fanout/internal/store"
"github.com/labstack/fanout/internal/telemetry"
Expand All @@ -31,7 +31,7 @@ func TestDashboardEvalGoldensCurrent(t *testing.T) {
t.Fatal(err)
}
defer repo.Close()
engine, err := query.NewDuck(t.Context(), cfg, repo)
engine, err := engine.NewDuck(t.Context(), cfg, repo)
if err != nil {
t.Fatal(err)
}
Expand All @@ -41,7 +41,7 @@ func TestDashboardEvalGoldensCurrent(t *testing.T) {
if err = repo.Commit(t.Context(), telemetrystore.Batch{ID: "eval_fixture", Spans: []telemetry.Span{{Namespace: "shop", ServiceName: "checkout", TraceID: "trace", SpanID: "span", Name: "request", Kind: "SPAN_KIND_SERVER", StartUnixNanos: from.UnixNano(), EndUnixNanos: from.Add(time.Millisecond).UnixNano(), DurationMS: 1, StatusCode: "STATUS_CODE_OK", IngestedAt: from.UnixNano()}}}); err != nil {
t.Fatal(err)
}
executor := panel.NewExecutor(engine, 30)
executor := query.NewExecutor(engine, 30)
db, err := controlstore.NewSQLite(":memory:")
if err != nil {
t.Fatal(err)
Expand All @@ -67,8 +67,8 @@ func TestDashboardEvalGoldensCurrent(t *testing.T) {
t.Fatal("embedded AI tools lost the shared MCP inventory guidance")
}
ctx := dashboard.WithOwner(t.Context(), "owner")
authored := panel.Dashboard{Name: "Eval fixture", Time: panel.Time{From: &from, To: &to}, Panels: []panel.Panel{
{ID: "actual_latency", Title: "Latency", Viz: "stat", Query: &panel.Query{From: "spans", Measures: []string{"p95(duration_ms)"}, Where: []string{"service = 'checkout'", "namespace = 'shop'"}}, Unit: "ms", Thresholds: []panel.Threshold{{Value: 100, Status: "warn"}}},
authored := query.Dashboard{Name: "Eval fixture", Time: query.Time{From: &from, To: &to}, Panels: []query.Panel{
{ID: "actual_latency", Title: "Latency", Viz: "stat", Query: &query.Spec{From: "spans", Measures: []string{"p95(duration_ms)"}, Where: []string{"service = 'checkout'", "namespace = 'shop'"}}, Unit: "ms", Thresholds: []query.Threshold{{Value: 100, Status: "warn"}}},
{ID: "actual_text", Title: "Explanation", Viz: "text", Content: "Seeded checkout request.", Description: "Fixture context."},
}}
authoredJSON := evalObject(t, authored)
Expand All @@ -91,13 +91,13 @@ func TestDashboardEvalGoldensCurrent(t *testing.T) {
if created.ID == "" || created.Version != 1 {
t.Fatalf("missing tool save: %+v", saved)
}
added := panel.Panel{ID: "added_panel", Title: "Added fixture panel", Viz: "timeseries", Query: &panel.Query{From: "spans", Measures: []string{"count()"}}}
added := query.Panel{ID: "added_panel", Title: "Added fixture panel", Viz: "timeseries", Query: &query.Spec{From: "spans", Measures: []string{"count()"}}}
addedJSON := evalObject(t, added)
edited, err := service.Edit(t.Context(), "owner", created.ID, []dashboard.Operation{{Op: "add_panel", Panel: &added, After: "actual_latency"}}, created.Version, dashboard.Author{Kind: "agent", ID: "owner"}, "Add fixture")
if err != nil {
t.Fatal(err)
}
statAdded := panel.Panel{ID: "added_stat", Title: "Added stat", Viz: "stat", Query: &panel.Query{From: "spans", Measures: []string{"count()"}}}
statAdded := query.Panel{ID: "added_stat", Title: "Added stat", Viz: "stat", Query: &query.Spec{From: "spans", Measures: []string{"count()"}}}
statJSON := evalObject(t, statAdded)
statEdited, err := service.Edit(t.Context(), "owner", created.ID, []dashboard.Operation{{Op: "add_panel", Panel: &statAdded}}, edited.Version, dashboard.Author{Kind: "agent", ID: "owner"}, "Add stat fixture")
if err != nil {
Expand All @@ -123,11 +123,11 @@ func TestDashboardEvalGoldensCurrent(t *testing.T) {
t.Fatal(err)
}
evalStableSave(editedOutput)
results, err := executor.Run(t.Context(), panel.RunRequest{Dashboard: created.Spec})
results, err := executor.Run(t.Context(), query.RunRequest{Dashboard: created.Spec})
if err != nil {
t.Fatal(err)
}
addedResults, err := executor.Run(t.Context(), panel.RunRequest{Dashboard: edited.Spec})
addedResults, err := executor.Run(t.Context(), query.RunRequest{Dashboard: edited.Spec})
if err != nil {
t.Fatal(err)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/agent/fragment_content_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"
"encoding/json"
fanoutmcp "github.com/labstack/fanout/internal/mcp"
"github.com/labstack/fanout/internal/panel"
"github.com/labstack/fanout/internal/query"
"github.com/labstack/fanout/internal/toolerror"
"reflect"
"strings"
Expand Down Expand Up @@ -66,7 +66,7 @@ func TestFragmentActivityPersistsExactContent(t *testing.T) {
if err != nil {
t.Fatal(err)
}
server := fanoutmcp.NewWithIntelligence(registryQueries{}, nil, panel.NewExecutor(nil, 30), nil, "test")
server := fanoutmcp.NewWithIntelligence(registryQueries{}, nil, query.NewExecutor(nil, 30), nil, "test")
tools, err := NewToolRegistry(t.Context(), server.MCP())
if err != nil {
t.Fatal(err)
Expand Down
8 changes: 4 additions & 4 deletions internal/agent/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/labstack/echo/v5"
"github.com/labstack/fanout/internal/auth"
fanoutmcp "github.com/labstack/fanout/internal/mcp"
"github.com/labstack/fanout/internal/panel"
"github.com/labstack/fanout/internal/query"

"github.com/labstack/fanout/internal/dashboard"
controlstore "github.com/labstack/fanout/internal/store"
Expand Down Expand Up @@ -346,9 +346,9 @@ func TestBuildOriginSkipsMissingMessageIdentity(t *testing.T) {

type originValidator struct{}

func (originValidator) Validate(_ context.Context, d *panel.Dashboard) error {
panel.Normalize(d)
if problems := panel.Validate(d); len(problems) > 0 {
func (originValidator) Validate(_ context.Context, d *query.Dashboard) error {
query.Normalize(d)
if problems := query.Validate(d); len(problems) > 0 {
return problems
}
return nil
Expand Down
12 changes: 6 additions & 6 deletions internal/agent/service_input_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import (

"github.com/labstack/fanout/internal/config"
"github.com/labstack/fanout/internal/dashboard"
"github.com/labstack/fanout/internal/engine"
fanoutmcp "github.com/labstack/fanout/internal/mcp"
"github.com/labstack/fanout/internal/observability"
"github.com/labstack/fanout/internal/panel"
"github.com/labstack/fanout/internal/query"
controlstore "github.com/labstack/fanout/internal/store"
"github.com/labstack/fanout/internal/telemetry"
Expand All @@ -27,7 +27,7 @@ func TestToolRegistryUnknownServiceBoundsOversizedAliases(t *testing.T) {
t.Fatal(err)
}
defer repo.Close()
duck, err := query.NewDuck(t.Context(), cfg, repo)
duck, err := engine.NewDuck(t.Context(), cfg, repo)
if err != nil {
t.Fatal(err)
}
Expand All @@ -46,7 +46,7 @@ func TestToolRegistryUnknownServiceBoundsOversizedAliases(t *testing.T) {
if err := repo.Commit(t.Context(), batch); err != nil {
t.Fatal(err)
}
executor := panel.NewExecutor(duck, 7)
executor := query.NewExecutor(duck, 7)
server := fanoutmcp.NewWithIntelligence(observability.New(duck, duck, 7), nil, executor, nil, "test")
registry, err := NewToolRegistry(t.Context(), server.MCP())
if err != nil {
Expand Down Expand Up @@ -81,7 +81,7 @@ func TestToolRegistryNoDataAndDashboardPanelErrors(t *testing.T) {
t.Fatal(err)
}
defer repo.Close()
duck, err := query.NewDuck(t.Context(), cfg, repo)
duck, err := engine.NewDuck(t.Context(), cfg, repo)
if err != nil {
t.Fatal(err)
}
Expand All @@ -99,14 +99,14 @@ func TestToolRegistryNoDataAndDashboardPanelErrors(t *testing.T) {
if _, err := db.DB.Exec(`INSERT INTO users(id,email) VALUES ('owner','owner@example.test')`); err != nil {
t.Fatal(err)
}
executor := panel.NewExecutor(duck, 7)
executor := query.NewExecutor(duck, 7)
server := fanoutmcp.NewWithIntelligence(observability.New(duck, duck, 7), dashboard.New(db.DB, executor), executor, nil, "test")
registry, err := NewToolRegistry(t.Context(), server.MCP())
if err != nil {
t.Fatal(err)
}
defer registry.Close()
spec := panel.Dashboard{Name: "Empty", Time: panel.Time{From: &from, To: &to}, Panels: []panel.Panel{{ID: "p", Title: "Collector requests", Viz: "stat", Query: &panel.Query{From: "spans", Where: []string{"service = 'collector'"}, Measures: []string{"count()"}}}}}
spec := query.Dashboard{Name: "Empty", Time: query.Time{From: &from, To: &to}, Panels: []query.Panel{{ID: "p", Title: "Collector requests", Viz: "stat", Query: &query.Spec{From: "spans", Where: []string{"service = 'collector'"}, Measures: []string{"count()"}}}}}
for _, tc := range []struct {
name, code, want string
args any
Expand Down
6 changes: 3 additions & 3 deletions internal/agent/tools_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/labstack/fanout/internal/intelligence"
fanoutmcp "github.com/labstack/fanout/internal/mcp"
"github.com/labstack/fanout/internal/observability"
"github.com/labstack/fanout/internal/panel"
"github.com/labstack/fanout/internal/query"
controlstore "github.com/labstack/fanout/internal/store"
)

Expand Down Expand Up @@ -113,9 +113,9 @@ func TestRuntimeDashboardHistoryUsesAuthenticatedOwner(t *testing.T) {
if _, err := db.DB.Exec(`INSERT INTO users(id,email) VALUES ('owner','owner@example.test'),('other','other@example.test')`); err != nil {
t.Fatal(err)
}
executor := panel.NewExecutor(nil, 30)
executor := query.NewExecutor(nil, 30)
service := dashboard.New(db.DB, executor)
created, err := service.Create(t.Context(), "owner", panel.Dashboard{Name: "History", Panels: []panel.Panel{{ID: "note", Title: "Note", Viz: "text", Content: "first"}}}, dashboard.Author{Kind: "user", ID: "owner"})
created, err := service.Create(t.Context(), "owner", query.Dashboard{Name: "History", Panels: []query.Panel{{ID: "note", Title: "Note", Viz: "text", Content: "first"}}}, dashboard.Author{Kind: "user", ID: "owner"})
if err != nil {
t.Fatal(err)
}
Expand Down
Loading
Loading