mirror of
https://github.com/hanzoai/o11y.git
synced 2026-10-15 12:58:33 +00:00
HIP-0132 unified o11y_logs, o11y_traces and o11y_metrics into one `event`
database and dropped them. The commit that restored the reads repointed
three files and said so; it was thirty. The rest went on naming databases
that no longer exist, so trace funnels, the Kafka and queue panels, the
v3/v4 logs and traces builders and the PromQL adapter each answered
Code: 81 UNKNOWN_DATABASE, and the golden tests agreed with them because
they pinned the same dead SQL.
pkg/telemetryplane is the one address for the name, imports nothing, and
is reachable from every depth that needs it. Its test walks the tree and
fails the build on a literal that names a dropped database, tests
included — a golden encoding broken SQL is a second vote for the bug, not
coverage.
Two service views turned a failed read into an offer to instrument an
already-instrumented application. A failure now shows the failure, and
onboarding is offered on a successful empty read.
Cherry-picked from salvage/blue-wt-o11y-readers 83ecbec03c.
158 lines
5.3 KiB
Go
158 lines
5.3 KiB
Go
package querier
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
dsmock "github.com/hanzo-ds/mock"
|
|
|
|
"github.com/hanzoai/o11y/pkg/flagger/flaggertest"
|
|
"github.com/hanzoai/o11y/pkg/instrumentation/instrumentationtest"
|
|
"github.com/hanzoai/o11y/pkg/telemetrystore"
|
|
"github.com/hanzoai/o11y/pkg/telemetrystore/telemetrystoretest"
|
|
"github.com/hanzoai/o11y/pkg/types/metrictypes"
|
|
qbtypes "github.com/hanzoai/o11y/pkg/types/querybuildertypes/querybuildertypesv5"
|
|
"github.com/hanzoai/o11y/pkg/types/telemetrytypes"
|
|
"github.com/hanzoai/o11y/pkg/types/telemetrytypes/telemetrytypestest"
|
|
"github.com/hanzoai/o11y/pkg/valuer"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type queryMatcherAny struct{}
|
|
|
|
func (m *queryMatcherAny) Match(string, string) error { return nil }
|
|
|
|
// mockMetricStmtBuilder implements qbtypes.StatementBuilder[qbtypes.MetricAggregation]
|
|
// and returns a fixed query string so the mock Datastore can match it.
|
|
type mockMetricStmtBuilder struct{}
|
|
|
|
func (m *mockMetricStmtBuilder) Build(_ context.Context, _, _ uint64, _ qbtypes.RequestType, _ qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation], _ map[string]qbtypes.VariableItem) (*qbtypes.Statement, error) {
|
|
return &qbtypes.Statement{
|
|
Query: "SELECT ts, value FROM event.metric",
|
|
Args: nil,
|
|
}, nil
|
|
}
|
|
|
|
func TestQueryRange_MetricTypeMissing(t *testing.T) {
|
|
// When a metric has UnspecifiedType and is not found in the metadata store,
|
|
// the querier should return an empty result with a warning instead of an error.
|
|
providerSettings := instrumentationtest.New().ToProviderSettings()
|
|
metadataStore := telemetrytypestest.NewMockMetadataStore()
|
|
|
|
q := New(
|
|
providerSettings,
|
|
nil, // telemetryStore
|
|
metadataStore,
|
|
nil, // prometheus
|
|
nil, // traceStmtBuilder
|
|
nil, // logStmtBuilder
|
|
nil, // auditStmtBuilder
|
|
nil, // metricStmtBuilder
|
|
nil, // meterStmtBuilder
|
|
nil, // traceOperatorStmtBuilder
|
|
nil, // bucketCache
|
|
flaggertest.New(t), // flagger
|
|
0,
|
|
)
|
|
|
|
req := &qbtypes.QueryRangeRequest{
|
|
Start: uint64(time.Now().Add(-5 * time.Minute).UnixMilli()),
|
|
End: uint64(time.Now().UnixMilli()),
|
|
RequestType: qbtypes.RequestTypeTimeSeries,
|
|
CompositeQuery: qbtypes.CompositeQuery{
|
|
Queries: []qbtypes.QueryEnvelope{{
|
|
Type: qbtypes.QueryTypeBuilder,
|
|
Spec: qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation]{
|
|
Name: "A",
|
|
StepInterval: qbtypes.Step{Duration: time.Minute},
|
|
Aggregations: []qbtypes.MetricAggregation{
|
|
{
|
|
MetricName: "unknown_metric",
|
|
Temporality: metrictypes.Cumulative,
|
|
TimeAggregation: metrictypes.TimeAggregationRate,
|
|
SpaceAggregation: metrictypes.SpaceAggregationSum,
|
|
},
|
|
},
|
|
Signal: telemetrytypes.SignalMetrics,
|
|
},
|
|
}},
|
|
},
|
|
}
|
|
|
|
resp, err := q.QueryRange(context.Background(), valuer.GenerateUUID(), req)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
require.NotNil(t, resp.Warning)
|
|
|
|
require.Len(t, resp.Warning.Warnings, 1)
|
|
assert.Contains(t, resp.Warning.Warnings[0].Message, "unknown_metric")
|
|
assert.Contains(t, resp.Warning.Warnings[0].Message, "has never been received")
|
|
}
|
|
|
|
func TestQueryRange_MetricTypeFromStore(t *testing.T) {
|
|
// When a metric has UnspecifiedType but the metadata store returns a valid type,
|
|
// the metric should not be treated as missing.
|
|
providerSettings := instrumentationtest.New().ToProviderSettings()
|
|
metadataStore := telemetrytypestest.NewMockMetadataStore()
|
|
metadataStore.TypeMap["my_metric"] = metrictypes.SumType
|
|
metadataStore.TemporalityMap["my_metric"] = metrictypes.Cumulative
|
|
|
|
telemetryStore := telemetrystoretest.New(telemetrystore.Config{}, &queryMatcherAny{})
|
|
|
|
cols := []dsmock.ColumnType{
|
|
{Name: "ts", Type: "DateTime"},
|
|
{Name: "value", Type: "Float64"},
|
|
}
|
|
rows := dsmock.NewRows(cols, [][]any{
|
|
{time.Now(), float64(42)},
|
|
})
|
|
telemetryStore.Mock().
|
|
ExpectQuery("SELECT any").
|
|
WillReturnRows(rows)
|
|
|
|
q := New(
|
|
providerSettings,
|
|
telemetryStore,
|
|
metadataStore,
|
|
nil, // prometheus
|
|
nil, // traceStmtBuilder
|
|
nil, // logStmtBuilder
|
|
nil, // auditStmtBuilder
|
|
&mockMetricStmtBuilder{}, // metricStmtBuilder
|
|
nil, // meterStmtBuilder
|
|
nil, // traceOperatorStmtBuilder
|
|
nil, // bucketCache
|
|
flaggertest.New(t), // flagger
|
|
0,
|
|
)
|
|
|
|
req := &qbtypes.QueryRangeRequest{
|
|
Start: uint64(time.Now().Add(-5 * time.Minute).UnixMilli()),
|
|
End: uint64(time.Now().UnixMilli()),
|
|
RequestType: qbtypes.RequestTypeTimeSeries,
|
|
CompositeQuery: qbtypes.CompositeQuery{
|
|
Queries: []qbtypes.QueryEnvelope{{
|
|
Type: qbtypes.QueryTypeBuilder,
|
|
Spec: qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation]{
|
|
Name: "A",
|
|
StepInterval: qbtypes.Step{Duration: time.Minute},
|
|
Aggregations: []qbtypes.MetricAggregation{
|
|
{
|
|
MetricName: "my_metric",
|
|
TimeAggregation: metrictypes.TimeAggregationRate,
|
|
SpaceAggregation: metrictypes.SpaceAggregationSum,
|
|
},
|
|
},
|
|
Signal: telemetrytypes.SignalMetrics,
|
|
},
|
|
}},
|
|
},
|
|
}
|
|
|
|
resp, err := q.QueryRange(context.Background(), valuer.GenerateUUID(), req)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
}
|