mirror of
https://github.com/SigNoz/signoz.git
synced 2026-11-13 11:50:42 +00:00
Compare commits
1 Commits
tvats-offs
...
fix/safe-n
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98a0d906ed |
@@ -31,12 +31,3 @@ packages:
|
||||
filename: "tokenizer.go"
|
||||
structname: 'Mock{{.InterfaceName}}'
|
||||
pkgname: '{{.SrcPackageName}}test'
|
||||
github.com/ClickHouse/clickhouse-go/v2/lib/driver:
|
||||
interfaces:
|
||||
Rows:
|
||||
ColumnType:
|
||||
config:
|
||||
dir: 'pkg/telemetrystore/drivertest'
|
||||
filename: "driver.go"
|
||||
structname: 'Mock{{.InterfaceName}}'
|
||||
pkgname: '{{.SrcPackageName}}test'
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { QueryParams } from 'constants/query';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { back, getCurrentLocation } from 'lib/router/navigation';
|
||||
import { act, AllTheProviders, renderHook, waitFor } from 'tests/test-utils';
|
||||
|
||||
// jest.config.ts maps `hooks/useSafeNavigate` to a mock; the `.ts` path loads the real hook.
|
||||
const { useSafeNavigate } = jest.requireActual<
|
||||
typeof import('hooks/useSafeNavigate')
|
||||
>('hooks/useSafeNavigate.ts');
|
||||
|
||||
describe('useSafeNavigate', () => {
|
||||
it('adds a history entry for replace: false even when the target adds params', async () => {
|
||||
const initialSearch = `?${QueryParams.relativeTime}=15m`;
|
||||
const { result } = renderHook(() => useSafeNavigate(), {
|
||||
wrapper: ({ children }): JSX.Element => (
|
||||
<AllTheProviders initialRoute={`${ROUTES.LOGS_EXPLORER}${initialSearch}`}>
|
||||
{children}
|
||||
</AllTheProviders>
|
||||
),
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.safeNavigate(
|
||||
`${ROUTES.LOGS_EXPLORER}?${QueryParams.startTime}=1000`,
|
||||
{ replace: false },
|
||||
);
|
||||
});
|
||||
act(() => back());
|
||||
|
||||
await waitFor(() => expect(getCurrentLocation().search).toBe(initialSearch));
|
||||
});
|
||||
});
|
||||
@@ -140,7 +140,7 @@ export const useSafeNavigate = (
|
||||
|
||||
const navigationOptions = {
|
||||
...options,
|
||||
replace: isDefaultParamsNavigation || options?.replace,
|
||||
replace: options?.replace ?? isDefaultParamsNavigation,
|
||||
};
|
||||
|
||||
if (typeof to === 'string') {
|
||||
|
||||
@@ -457,13 +457,6 @@ func emptyResultFor(kind qbtypes.RequestType, queryName string) *qbtypes.Result
|
||||
|
||||
// executeWithContext executes the query with query window and step context for partial value detection.
|
||||
func (q *builderQuery[T]) executeWithContext(ctx context.Context, query string, args []any) (*qbtypes.Result, error) {
|
||||
result, _, err := q.executeSkippingRaw(ctx, query, args, 0)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// executeSkippingRaw is executeWithContext for a raw query that drops its first
|
||||
// skip rows undecoded. It returns how many rows were skipped.
|
||||
func (q *builderQuery[T]) executeSkippingRaw(ctx context.Context, query string, args []any, skip int) (*qbtypes.Result, int, error) {
|
||||
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
|
||||
instrumentationtypes.TelemetrySignal: q.spec.Signal.StringValue(),
|
||||
instrumentationtypes.QueryDuration: instrumentationtypes.DurationBucket(q.fromMS, q.toMS),
|
||||
@@ -482,19 +475,19 @@ func (q *builderQuery[T]) executeSkippingRaw(ctx context.Context, query string,
|
||||
rows, err := q.telemetryStore.ClickhouseDB().Query(ctx, query, args...)
|
||||
if err != nil {
|
||||
if errors.Is(err, context.DeadlineExceeded) {
|
||||
return nil, 0, errors.Newf(errors.TypeTimeout, errors.CodeTimeout, "Query timed out").
|
||||
return nil, errors.Newf(errors.TypeTimeout, errors.CodeTimeout, "Query timed out").
|
||||
WithAdditional("Try refining your search by adding relevant resource attributes filtering")
|
||||
}
|
||||
|
||||
if !errors.Is(err, context.Canceled) {
|
||||
return nil, 0, errors.Newf(
|
||||
return nil, errors.Newf(
|
||||
errors.TypeInternal,
|
||||
errors.CodeInternal,
|
||||
"Something went wrong on our end. It's not you, it's us. Our team is notified about it. Reach out to support if issue persists.",
|
||||
)
|
||||
}
|
||||
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
@@ -508,15 +501,9 @@ func (q *builderQuery[T]) executeSkippingRaw(ctx context.Context, query string,
|
||||
kind = qbtypes.RequestTypeTimeSeries
|
||||
}
|
||||
|
||||
var payload any
|
||||
skipped := 0
|
||||
if skip > 0 {
|
||||
payload, skipped, err = readAsRawSkipping(rows, q.spec.Name, skip)
|
||||
} else {
|
||||
payload, err = consume(rows, kind, queryWindow, q.spec.StepInterval, q.spec.Name)
|
||||
}
|
||||
payload, err := consume(rows, kind, queryWindow, q.spec.StepInterval, q.spec.Name)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: This should move to readAsRaw function in consume.go but for now we are keeping it here since it's only relevant for traces
|
||||
@@ -536,7 +523,7 @@ func (q *builderQuery[T]) executeSkippingRaw(ctx context.Context, query string,
|
||||
BytesScanned: totalBytes,
|
||||
DurationMS: uint64(elapsed.Milliseconds()),
|
||||
},
|
||||
}, skipped, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (q *builderQuery[T]) executeWindowList(ctx context.Context) (*qbtypes.Result, error) {
|
||||
@@ -636,7 +623,7 @@ func (q *builderQuery[T]) executeWindowList(ctx context.Context) (*qbtypes.Resul
|
||||
}
|
||||
}
|
||||
// Execute with proper context for partial value detection
|
||||
res, skipped, err := q.executeSkippingRaw(ctx, stmt.Query, stmt.Args, offsetLeft)
|
||||
res, err := q.executeWithContext(ctx, stmt.Query, stmt.Args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -644,10 +631,13 @@ func (q *builderQuery[T]) executeWindowList(ctx context.Context) (*qbtypes.Resul
|
||||
totalBytes += res.Stats.BytesScanned
|
||||
|
||||
rawRows := res.Value.(*qbtypes.RawData).Rows
|
||||
need -= skipped + len(rawRows)
|
||||
offsetLeft -= skipped
|
||||
need -= len(rawRows)
|
||||
|
||||
for _, rr := range rawRows {
|
||||
if offsetLeft > 0 { // client-requested initial offset
|
||||
offsetLeft--
|
||||
continue
|
||||
}
|
||||
rows = append(rows, rr)
|
||||
if len(rows) >= reqLimit { // page filled
|
||||
break
|
||||
|
||||
@@ -521,26 +521,13 @@ func derefValue(v any) any {
|
||||
}
|
||||
|
||||
func readAsRaw(rows driver.Rows, queryName string) (*qbtypes.RawData, error) {
|
||||
data, _, err := readAsRawSkipping(rows, queryName, 0)
|
||||
return data, err
|
||||
}
|
||||
|
||||
// readAsRawSkipping advances past the first skip rows without scanning them, so
|
||||
// rows dropped for an offset are never decoded. It returns how many were skipped.
|
||||
func readAsRawSkipping(rows driver.Rows, queryName string, skip int) (*qbtypes.RawData, int, error) {
|
||||
colNames := rows.Columns()
|
||||
colTypes := rows.ColumnTypes()
|
||||
colCnt := len(colNames)
|
||||
|
||||
var outRows []*qbtypes.RawRow
|
||||
skipped := 0
|
||||
|
||||
for rows.Next() {
|
||||
if skipped < skip {
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
|
||||
// fresh copy of the scan slice (otherwise the driver reuses pointers)
|
||||
scan := make([]any, colCnt)
|
||||
for i := range colTypes {
|
||||
@@ -548,7 +535,7 @@ func readAsRawSkipping(rows driver.Rows, queryName string, skip int) (*qbtypes.R
|
||||
}
|
||||
|
||||
if err := rows.Scan(scan...); err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rr := qbtypes.RawRow{
|
||||
@@ -580,13 +567,13 @@ func readAsRawSkipping(rows driver.Rows, queryName string, skip int) (*qbtypes.R
|
||||
outRows = append(outRows, &rr)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &qbtypes.RawData{
|
||||
QueryName: queryName,
|
||||
Rows: outRows,
|
||||
}, skipped, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
// mergeSpanAttributeColumns merges (attributes_string, attributes_number, attributes_bool, resources_string) into
|
||||
|
||||
@@ -5,12 +5,9 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ClickHouse/clickhouse-go/v2/lib/chcol"
|
||||
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/telemetrystore/drivertest"
|
||||
"github.com/SigNoz/signoz/pkg/types/spantypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrystoretypes"
|
||||
)
|
||||
@@ -257,52 +254,3 @@ func TestMergeSpanAttributeColumns_JSONColumn(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadAsRawSkipping(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
values []string
|
||||
skip int
|
||||
wantSkipped int
|
||||
wantIDs []string
|
||||
}{
|
||||
{name: "NoSkip", values: []string{"a", "b", "c"}, skip: 0, wantSkipped: 0, wantIDs: []string{"a", "b", "c"}},
|
||||
{name: "SkipInsideResult", values: []string{"d", "e", "f", "g"}, skip: 2, wantSkipped: 2, wantIDs: []string{"f", "g"}},
|
||||
{name: "SkipWholeResult", values: []string{"h", "i"}, skip: 2, wantSkipped: 2, wantIDs: nil},
|
||||
{name: "SkipPastResult", values: []string{"j"}, skip: 5, wantSkipped: 1, wantIDs: nil},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
columnType := drivertest.NewMockColumnType(t)
|
||||
columnType.EXPECT().ScanType().Return(reflect.TypeOf("")).Maybe()
|
||||
|
||||
// Like clickhouse-go, Next advances on its own; Scan is expected only for returned rows.
|
||||
rows := drivertest.NewMockRows(t)
|
||||
pos := 0
|
||||
rows.EXPECT().Columns().Return([]string{"id"})
|
||||
rows.EXPECT().ColumnTypes().Return([]driver.ColumnType{columnType})
|
||||
rows.EXPECT().Next().RunAndReturn(func() bool {
|
||||
pos++
|
||||
return pos <= len(testCase.values)
|
||||
})
|
||||
if len(testCase.wantIDs) > 0 {
|
||||
rows.EXPECT().Scan(mock.Anything).RunAndReturn(func(dest ...any) error {
|
||||
*dest[0].(*string) = testCase.values[pos-1]
|
||||
return nil
|
||||
}).Times(len(testCase.wantIDs))
|
||||
}
|
||||
rows.EXPECT().Err().Return(nil)
|
||||
|
||||
data, skipped, err := readAsRawSkipping(rows, "A", testCase.skip)
|
||||
require.NoError(t, err)
|
||||
|
||||
var ids []string
|
||||
for _, row := range data.Rows {
|
||||
ids = append(ids, row.Data["id"].(string))
|
||||
}
|
||||
assert.Equal(t, testCase.wantSkipped, skipped)
|
||||
assert.Equal(t, testCase.wantIDs, ids)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,701 +0,0 @@
|
||||
// Code generated by mockery; DO NOT EDIT.
|
||||
// github.com/vektra/mockery
|
||||
// template: testify
|
||||
|
||||
package drivertest
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// NewMockRows creates a new instance of MockRows. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewMockRows(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *MockRows {
|
||||
if helper, ok := t.(interface{ Helper() }); ok {
|
||||
helper.Helper()
|
||||
}
|
||||
|
||||
mock := &MockRows{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() {
|
||||
if helper, ok := t.(interface{ Helper() }); ok {
|
||||
helper.Helper()
|
||||
}
|
||||
mock.AssertExpectations(t)
|
||||
})
|
||||
|
||||
return mock
|
||||
}
|
||||
|
||||
// MockRows is an autogenerated mock type for the Rows type
|
||||
type MockRows struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type MockRows_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *MockRows) EXPECT() *MockRows_Expecter {
|
||||
return &MockRows_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Close provides a mock function for the type MockRows
|
||||
func (_mock *MockRows) Close() error {
|
||||
ret := _mock.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Close")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = returnFunc()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockRows_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
|
||||
type MockRows_Close_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Close is a helper method to define mock.On call
|
||||
func (_e *MockRows_Expecter) Close() *MockRows_Close_Call {
|
||||
return &MockRows_Close_Call{Call: _e.mock.On("Close")}
|
||||
}
|
||||
|
||||
func (_c *MockRows_Close_Call) Run(run func()) *MockRows_Close_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Close_Call) Return(err error) *MockRows_Close_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Close_Call) RunAndReturn(run func() error) *MockRows_Close_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ColumnTypes provides a mock function for the type MockRows
|
||||
func (_mock *MockRows) ColumnTypes() []driver.ColumnType {
|
||||
ret := _mock.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ColumnTypes")
|
||||
}
|
||||
|
||||
var r0 []driver.ColumnType
|
||||
if returnFunc, ok := ret.Get(0).(func() []driver.ColumnType); ok {
|
||||
r0 = returnFunc()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]driver.ColumnType)
|
||||
}
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockRows_ColumnTypes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ColumnTypes'
|
||||
type MockRows_ColumnTypes_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ColumnTypes is a helper method to define mock.On call
|
||||
func (_e *MockRows_Expecter) ColumnTypes() *MockRows_ColumnTypes_Call {
|
||||
return &MockRows_ColumnTypes_Call{Call: _e.mock.On("ColumnTypes")}
|
||||
}
|
||||
|
||||
func (_c *MockRows_ColumnTypes_Call) Run(run func()) *MockRows_ColumnTypes_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_ColumnTypes_Call) Return(columnTypes []driver.ColumnType) *MockRows_ColumnTypes_Call {
|
||||
_c.Call.Return(columnTypes)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_ColumnTypes_Call) RunAndReturn(run func() []driver.ColumnType) *MockRows_ColumnTypes_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Columns provides a mock function for the type MockRows
|
||||
func (_mock *MockRows) Columns() []string {
|
||||
ret := _mock.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Columns")
|
||||
}
|
||||
|
||||
var r0 []string
|
||||
if returnFunc, ok := ret.Get(0).(func() []string); ok {
|
||||
r0 = returnFunc()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]string)
|
||||
}
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockRows_Columns_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Columns'
|
||||
type MockRows_Columns_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Columns is a helper method to define mock.On call
|
||||
func (_e *MockRows_Expecter) Columns() *MockRows_Columns_Call {
|
||||
return &MockRows_Columns_Call{Call: _e.mock.On("Columns")}
|
||||
}
|
||||
|
||||
func (_c *MockRows_Columns_Call) Run(run func()) *MockRows_Columns_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Columns_Call) Return(strings []string) *MockRows_Columns_Call {
|
||||
_c.Call.Return(strings)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Columns_Call) RunAndReturn(run func() []string) *MockRows_Columns_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Err provides a mock function for the type MockRows
|
||||
func (_mock *MockRows) Err() error {
|
||||
ret := _mock.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Err")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = returnFunc()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockRows_Err_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Err'
|
||||
type MockRows_Err_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Err is a helper method to define mock.On call
|
||||
func (_e *MockRows_Expecter) Err() *MockRows_Err_Call {
|
||||
return &MockRows_Err_Call{Call: _e.mock.On("Err")}
|
||||
}
|
||||
|
||||
func (_c *MockRows_Err_Call) Run(run func()) *MockRows_Err_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Err_Call) Return(err error) *MockRows_Err_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Err_Call) RunAndReturn(run func() error) *MockRows_Err_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// HasData provides a mock function for the type MockRows
|
||||
func (_mock *MockRows) HasData() bool {
|
||||
ret := _mock.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for HasData")
|
||||
}
|
||||
|
||||
var r0 bool
|
||||
if returnFunc, ok := ret.Get(0).(func() bool); ok {
|
||||
r0 = returnFunc()
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockRows_HasData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HasData'
|
||||
type MockRows_HasData_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// HasData is a helper method to define mock.On call
|
||||
func (_e *MockRows_Expecter) HasData() *MockRows_HasData_Call {
|
||||
return &MockRows_HasData_Call{Call: _e.mock.On("HasData")}
|
||||
}
|
||||
|
||||
func (_c *MockRows_HasData_Call) Run(run func()) *MockRows_HasData_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_HasData_Call) Return(b bool) *MockRows_HasData_Call {
|
||||
_c.Call.Return(b)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_HasData_Call) RunAndReturn(run func() bool) *MockRows_HasData_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Next provides a mock function for the type MockRows
|
||||
func (_mock *MockRows) Next() bool {
|
||||
ret := _mock.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Next")
|
||||
}
|
||||
|
||||
var r0 bool
|
||||
if returnFunc, ok := ret.Get(0).(func() bool); ok {
|
||||
r0 = returnFunc()
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockRows_Next_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Next'
|
||||
type MockRows_Next_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Next is a helper method to define mock.On call
|
||||
func (_e *MockRows_Expecter) Next() *MockRows_Next_Call {
|
||||
return &MockRows_Next_Call{Call: _e.mock.On("Next")}
|
||||
}
|
||||
|
||||
func (_c *MockRows_Next_Call) Run(run func()) *MockRows_Next_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Next_Call) Return(b bool) *MockRows_Next_Call {
|
||||
_c.Call.Return(b)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Next_Call) RunAndReturn(run func() bool) *MockRows_Next_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Scan provides a mock function for the type MockRows
|
||||
func (_mock *MockRows) Scan(dest ...any) error {
|
||||
var tmpRet mock.Arguments
|
||||
if len(dest) > 0 {
|
||||
tmpRet = _mock.Called(dest)
|
||||
} else {
|
||||
tmpRet = _mock.Called()
|
||||
}
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Scan")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func(...any) error); ok {
|
||||
r0 = returnFunc(dest...)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockRows_Scan_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Scan'
|
||||
type MockRows_Scan_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Scan is a helper method to define mock.On call
|
||||
// - dest ...any
|
||||
func (_e *MockRows_Expecter) Scan(dest ...any) *MockRows_Scan_Call {
|
||||
return &MockRows_Scan_Call{Call: _e.mock.On("Scan",
|
||||
append([]any{}, dest...)...)}
|
||||
}
|
||||
|
||||
func (_c *MockRows_Scan_Call) Run(run func(dest ...any)) *MockRows_Scan_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 []any
|
||||
var variadicArgs []any
|
||||
if len(args) > 0 {
|
||||
variadicArgs = args[0].([]any)
|
||||
}
|
||||
arg0 = variadicArgs
|
||||
run(
|
||||
arg0...,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Scan_Call) Return(err error) *MockRows_Scan_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Scan_Call) RunAndReturn(run func(dest ...any) error) *MockRows_Scan_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ScanStruct provides a mock function for the type MockRows
|
||||
func (_mock *MockRows) ScanStruct(dest any) error {
|
||||
ret := _mock.Called(dest)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ScanStruct")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func(any) error); ok {
|
||||
r0 = returnFunc(dest)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockRows_ScanStruct_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ScanStruct'
|
||||
type MockRows_ScanStruct_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ScanStruct is a helper method to define mock.On call
|
||||
// - dest any
|
||||
func (_e *MockRows_Expecter) ScanStruct(dest any) *MockRows_ScanStruct_Call {
|
||||
return &MockRows_ScanStruct_Call{Call: _e.mock.On("ScanStruct", dest)}
|
||||
}
|
||||
|
||||
func (_c *MockRows_ScanStruct_Call) Run(run func(dest any)) *MockRows_ScanStruct_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 any
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(any)
|
||||
}
|
||||
run(
|
||||
arg0,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_ScanStruct_Call) Return(err error) *MockRows_ScanStruct_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_ScanStruct_Call) RunAndReturn(run func(dest any) error) *MockRows_ScanStruct_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Totals provides a mock function for the type MockRows
|
||||
func (_mock *MockRows) Totals(dest ...any) error {
|
||||
var tmpRet mock.Arguments
|
||||
if len(dest) > 0 {
|
||||
tmpRet = _mock.Called(dest)
|
||||
} else {
|
||||
tmpRet = _mock.Called()
|
||||
}
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Totals")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func(...any) error); ok {
|
||||
r0 = returnFunc(dest...)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockRows_Totals_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Totals'
|
||||
type MockRows_Totals_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Totals is a helper method to define mock.On call
|
||||
// - dest ...any
|
||||
func (_e *MockRows_Expecter) Totals(dest ...any) *MockRows_Totals_Call {
|
||||
return &MockRows_Totals_Call{Call: _e.mock.On("Totals",
|
||||
append([]any{}, dest...)...)}
|
||||
}
|
||||
|
||||
func (_c *MockRows_Totals_Call) Run(run func(dest ...any)) *MockRows_Totals_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 []any
|
||||
var variadicArgs []any
|
||||
if len(args) > 0 {
|
||||
variadicArgs = args[0].([]any)
|
||||
}
|
||||
arg0 = variadicArgs
|
||||
run(
|
||||
arg0...,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Totals_Call) Return(err error) *MockRows_Totals_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRows_Totals_Call) RunAndReturn(run func(dest ...any) error) *MockRows_Totals_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewMockColumnType creates a new instance of MockColumnType. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewMockColumnType(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *MockColumnType {
|
||||
if helper, ok := t.(interface{ Helper() }); ok {
|
||||
helper.Helper()
|
||||
}
|
||||
|
||||
mock := &MockColumnType{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() {
|
||||
if helper, ok := t.(interface{ Helper() }); ok {
|
||||
helper.Helper()
|
||||
}
|
||||
mock.AssertExpectations(t)
|
||||
})
|
||||
|
||||
return mock
|
||||
}
|
||||
|
||||
// MockColumnType is an autogenerated mock type for the ColumnType type
|
||||
type MockColumnType struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type MockColumnType_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *MockColumnType) EXPECT() *MockColumnType_Expecter {
|
||||
return &MockColumnType_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// DatabaseTypeName provides a mock function for the type MockColumnType
|
||||
func (_mock *MockColumnType) DatabaseTypeName() string {
|
||||
ret := _mock.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DatabaseTypeName")
|
||||
}
|
||||
|
||||
var r0 string
|
||||
if returnFunc, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = returnFunc()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockColumnType_DatabaseTypeName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DatabaseTypeName'
|
||||
type MockColumnType_DatabaseTypeName_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DatabaseTypeName is a helper method to define mock.On call
|
||||
func (_e *MockColumnType_Expecter) DatabaseTypeName() *MockColumnType_DatabaseTypeName_Call {
|
||||
return &MockColumnType_DatabaseTypeName_Call{Call: _e.mock.On("DatabaseTypeName")}
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_DatabaseTypeName_Call) Run(run func()) *MockColumnType_DatabaseTypeName_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_DatabaseTypeName_Call) Return(s string) *MockColumnType_DatabaseTypeName_Call {
|
||||
_c.Call.Return(s)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_DatabaseTypeName_Call) RunAndReturn(run func() string) *MockColumnType_DatabaseTypeName_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Name provides a mock function for the type MockColumnType
|
||||
func (_mock *MockColumnType) Name() string {
|
||||
ret := _mock.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Name")
|
||||
}
|
||||
|
||||
var r0 string
|
||||
if returnFunc, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = returnFunc()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockColumnType_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name'
|
||||
type MockColumnType_Name_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Name is a helper method to define mock.On call
|
||||
func (_e *MockColumnType_Expecter) Name() *MockColumnType_Name_Call {
|
||||
return &MockColumnType_Name_Call{Call: _e.mock.On("Name")}
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_Name_Call) Run(run func()) *MockColumnType_Name_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_Name_Call) Return(s string) *MockColumnType_Name_Call {
|
||||
_c.Call.Return(s)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_Name_Call) RunAndReturn(run func() string) *MockColumnType_Name_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Nullable provides a mock function for the type MockColumnType
|
||||
func (_mock *MockColumnType) Nullable() bool {
|
||||
ret := _mock.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Nullable")
|
||||
}
|
||||
|
||||
var r0 bool
|
||||
if returnFunc, ok := ret.Get(0).(func() bool); ok {
|
||||
r0 = returnFunc()
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockColumnType_Nullable_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Nullable'
|
||||
type MockColumnType_Nullable_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Nullable is a helper method to define mock.On call
|
||||
func (_e *MockColumnType_Expecter) Nullable() *MockColumnType_Nullable_Call {
|
||||
return &MockColumnType_Nullable_Call{Call: _e.mock.On("Nullable")}
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_Nullable_Call) Run(run func()) *MockColumnType_Nullable_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_Nullable_Call) Return(b bool) *MockColumnType_Nullable_Call {
|
||||
_c.Call.Return(b)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_Nullable_Call) RunAndReturn(run func() bool) *MockColumnType_Nullable_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ScanType provides a mock function for the type MockColumnType
|
||||
func (_mock *MockColumnType) ScanType() reflect.Type {
|
||||
ret := _mock.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ScanType")
|
||||
}
|
||||
|
||||
var r0 reflect.Type
|
||||
if returnFunc, ok := ret.Get(0).(func() reflect.Type); ok {
|
||||
r0 = returnFunc()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(reflect.Type)
|
||||
}
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockColumnType_ScanType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ScanType'
|
||||
type MockColumnType_ScanType_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ScanType is a helper method to define mock.On call
|
||||
func (_e *MockColumnType_Expecter) ScanType() *MockColumnType_ScanType_Call {
|
||||
return &MockColumnType_ScanType_Call{Call: _e.mock.On("ScanType")}
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_ScanType_Call) Run(run func()) *MockColumnType_ScanType_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_ScanType_Call) Return(typeParam reflect.Type) *MockColumnType_ScanType_Call {
|
||||
_c.Call.Return(typeParam)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockColumnType_ScanType_Call) RunAndReturn(run func() reflect.Type) *MockColumnType_ScanType_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
@@ -9,12 +9,7 @@ from fixtures import types
|
||||
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
|
||||
from fixtures.logs import Logs
|
||||
from fixtures.querier import (
|
||||
BuilderQuery,
|
||||
OrderBy,
|
||||
RequestType,
|
||||
TelemetryFieldKey,
|
||||
assert_identical_query_response,
|
||||
get_rows,
|
||||
make_query_request,
|
||||
)
|
||||
|
||||
@@ -503,64 +498,3 @@ def test_logs_list_with_order_by(
|
||||
ids = [row["data"]["attributes_string"].get("id", "") for row in rows]
|
||||
|
||||
assert ids == expected_order
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"limit,offset",
|
||||
[
|
||||
pytest.param(2, 0, id="first_chunk"),
|
||||
pytest.param(2, 1, id="first_into_second_chunk"),
|
||||
pytest.param(2, 2, id="second_chunk"),
|
||||
pytest.param(2, 3, id="second_into_third_chunk"),
|
||||
pytest.param(2, 4, id="third_chunk"),
|
||||
pytest.param(4, 5, id="last_partial_page"),
|
||||
pytest.param(2, 6, id="offset_past_end"),
|
||||
],
|
||||
)
|
||||
def test_logs_list_offset_across_chunks(
|
||||
signoz: types.SigNoz,
|
||||
create_user_admin: None, # pylint: disable=unused-argument
|
||||
get_token: Callable[[str, str], str],
|
||||
insert_logs: Callable[[list[Logs]], None],
|
||||
limit: int,
|
||||
offset: int,
|
||||
) -> None:
|
||||
"""
|
||||
A 4h list runs as 1h, 2h and 1h chunks, newest first. Two logs sit in each
|
||||
chunk, so the offset lands in, or crosses into, every chunk.
|
||||
"""
|
||||
now = datetime.now(tz=UTC).replace(microsecond=0)
|
||||
minutes_ago = [10, 20, 90, 150, 200, 220]
|
||||
insert_logs(
|
||||
[
|
||||
Logs(
|
||||
timestamp=now - timedelta(minutes=minutes),
|
||||
resources={"service.name": "chunked-offset-service"},
|
||||
body=f"chunked-log-{minutes}",
|
||||
)
|
||||
for minutes in minutes_ago
|
||||
]
|
||||
)
|
||||
|
||||
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
|
||||
response = make_query_request(
|
||||
signoz,
|
||||
token,
|
||||
start_ms=int((now - timedelta(hours=4)).timestamp() * 1000),
|
||||
end_ms=int((now + timedelta(seconds=1)).timestamp() * 1000),
|
||||
request_type=RequestType.RAW,
|
||||
queries=[
|
||||
BuilderQuery(
|
||||
signal="logs",
|
||||
name="A",
|
||||
limit=limit,
|
||||
offset=offset,
|
||||
filter_expression="service.name = 'chunked-offset-service'",
|
||||
order=[OrderBy(TelemetryFieldKey("timestamp"), "desc"), OrderBy(TelemetryFieldKey("id"), "desc")],
|
||||
).to_dict()
|
||||
],
|
||||
)
|
||||
|
||||
assert response.status_code == HTTPStatus.OK, response.text
|
||||
expected_bodies = [f"chunked-log-{minutes}" for minutes in minutes_ago][offset : offset + limit]
|
||||
assert [row["data"]["body"] for row in get_rows(response)] == expected_bodies
|
||||
|
||||
@@ -917,69 +917,6 @@ def test_traces_list_pagination(
|
||||
assert [row["data"]["span_id"] for row in rows] == expected_ids
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"limit,offset",
|
||||
[
|
||||
pytest.param(2, 0, id="first_chunk"),
|
||||
pytest.param(2, 1, id="first_into_second_chunk"),
|
||||
pytest.param(2, 2, id="second_chunk"),
|
||||
pytest.param(2, 3, id="second_into_third_chunk"),
|
||||
pytest.param(2, 4, id="third_chunk"),
|
||||
pytest.param(4, 5, id="last_partial_page"),
|
||||
pytest.param(2, 6, id="offset_past_end"),
|
||||
],
|
||||
)
|
||||
def test_traces_list_offset_across_chunks(
|
||||
signoz: types.SigNoz,
|
||||
create_user_admin: None, # pylint: disable=unused-argument
|
||||
get_token: Callable[[str, str], str],
|
||||
insert_traces: Callable[[list[Traces]], None],
|
||||
limit: int,
|
||||
offset: int,
|
||||
) -> None:
|
||||
"""
|
||||
A 4h list runs as 1h, 2h and 1h chunks, newest first. Two spans sit in each
|
||||
chunk, so the offset lands in, or crosses into, every chunk.
|
||||
"""
|
||||
now = datetime.now(tz=UTC).replace(microsecond=0)
|
||||
minutes_ago = [10, 20, 90, 150, 200, 220]
|
||||
insert_traces(
|
||||
[
|
||||
Traces(
|
||||
timestamp=now - timedelta(minutes=minutes),
|
||||
trace_id=TraceIdGenerator.trace_id(),
|
||||
span_id=TraceIdGenerator.span_id(),
|
||||
name=f"chunked-span-{minutes}",
|
||||
resources={"service.name": "chunked-offset-service"},
|
||||
)
|
||||
for minutes in minutes_ago
|
||||
]
|
||||
)
|
||||
|
||||
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
|
||||
response = make_query_request(
|
||||
signoz,
|
||||
token,
|
||||
start_ms=int((now - timedelta(hours=4)).timestamp() * 1000),
|
||||
end_ms=int((now + timedelta(seconds=1)).timestamp() * 1000),
|
||||
request_type=RequestType.RAW,
|
||||
queries=[
|
||||
BuilderQuery(
|
||||
signal="traces",
|
||||
name="A",
|
||||
limit=limit,
|
||||
offset=offset,
|
||||
filter_expression="service.name = 'chunked-offset-service'",
|
||||
order=[OrderBy(TelemetryFieldKey("timestamp"), "desc")],
|
||||
).to_dict()
|
||||
],
|
||||
)
|
||||
|
||||
assert response.status_code == HTTPStatus.OK, response.text
|
||||
expected_names = [f"chunked-span-{minutes}" for minutes in minutes_ago][offset : offset + limit]
|
||||
assert [row["data"]["name"] for row in get_rows(response)] == expected_names
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Time window
|
||||
# ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user