Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
867419f
feat: add endpoint & module for trace aggregations
krsoninikhil May 25, 2026
9c3aef3
chore: use v1 for aggregations api
krsoninikhil May 26, 2026
5d73fce
chore: update openapi specs
krsoninikhil May 26, 2026
f7532ee
feat: add implementation for aggregation store
krsoninikhil May 25, 2026
75f12af
chore: use query builder for count by field
krsoninikhil May 26, 2026
ae88f55
chore: remove support for aggregations on attributes
krsoninikhil May 27, 2026
1970514
chore: extract out inner query as cte
krsoninikhil May 27, 2026
dcaa923
chore: again extract out inner query
krsoninikhil May 27, 2026
2d3a403
chore: move end_ns computation to first cte for simplicity
krsoninikhil May 27, 2026
2dc7a50
chore: use notEmpty function instead of having
krsoninikhil May 27, 2026
3e7bc38
fix: type cast issue in sum function
krsoninikhil May 27, 2026
a604df8
chore: use query builder for duration query as well
krsoninikhil May 27, 2026
ebca04f
chore: add tests for trace store sql
krsoninikhil May 29, 2026
4da04cb
chore: remove unnecessary column checks
krsoninikhil May 29, 2026
df84116
chore: format the expected sql queries
krsoninikhil May 29, 2026
906220f
fix: formating was breaking test
krsoninikhil May 29, 2026
bd30292
fix: change import and remove formating from sql
krsoninikhil Jun 1, 2026
1f93993
chore: remove formating from store impl as well
krsoninikhil Jun 1, 2026
dfacb4e
fix: mark required fields as required
krsoninikhil Jun 1, 2026
0863f81
fix: explicitly mark nullable false for required field
krsoninikhil Jun 1, 2026
cd67e92
fix: mark required fields in response as well
krsoninikhil Jun 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions docs/api/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6525,6 +6525,15 @@ components:
required:
- items
type: object
SpantypesGettableTraceAggregations:
properties:
aggregations:
items:
$ref: '#/components/schemas/SpantypesSpanAggregationResult'
type: array
required:
- aggregations
type: object
SpantypesGettableWaterfallTrace:
properties:
aggregations:
Expand Down Expand Up @@ -6590,6 +6599,15 @@ components:
- name
- condition
type: object
SpantypesPostableTraceAggregations:
properties:
aggregations:
items:
$ref: '#/components/schemas/SpantypesSpanAggregation'
type: array
required:
- aggregations
type: object
SpantypesPostableWaterfall:
properties:
aggregations:
Expand All @@ -6614,6 +6632,9 @@ components:
$ref: '#/components/schemas/SpantypesSpanAggregationType'
field:
$ref: '#/components/schemas/TelemetrytypesTelemetryFieldKey'
required:
- field
- aggregation
type: object
SpantypesSpanAggregationResult:
properties:
Expand All @@ -6627,6 +6648,10 @@ components:
type: integer
nullable: true
type: object
required:
- field
- aggregation
- value
type: object
SpantypesSpanAggregationType:
enum:
Expand Down Expand Up @@ -12265,6 +12290,75 @@ paths:
summary: Test notification channel (deprecated)
tags:
- channels
/api/v1/traces/{traceID}/aggregations:
post:
deprecated: false
description: Computes span aggregations grouped by requested field.
operationId: GetTraceAggregations
parameters:
- in: path
name: traceID
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/SpantypesPostableTraceAggregations'
responses:
"200":
content:
application/json:
schema:
properties:
data:
$ref: '#/components/schemas/SpantypesGettableTraceAggregations'
status:
type: string
required:
- status
- data
type: object
description: OK
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Bad Request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Forbidden
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Not Found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Internal Server Error
security:
- api_key:
- VIEWER
- tokenizer:
- VIEWER
summary: Get aggregations for a trace
tags:
- tracedetail
/api/v1/user:
get:
deprecated: false
Expand Down
35 changes: 30 additions & 5 deletions frontend/src/api/generated/services/sigNoz.schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7753,12 +7753,19 @@ export type SpantypesSpanAggregationResultDTOValue =
SpantypesSpanAggregationResultDTOValueAnyOf | null;

export interface SpantypesSpanAggregationResultDTO {
aggregation?: SpantypesSpanAggregationTypeDTO;
field?: TelemetrytypesTelemetryFieldKeyDTO;
aggregation: SpantypesSpanAggregationTypeDTO;
field: TelemetrytypesTelemetryFieldKeyDTO;
/**
* @type object,null
*/
value?: SpantypesSpanAggregationResultDTOValue;
value: SpantypesSpanAggregationResultDTOValue;
}

export interface SpantypesGettableTraceAggregationsDTO {
/**
* @type array
*/
aggregations: SpantypesSpanAggregationResultDTO[];
}

export type SpantypesWaterfallSpanDTOAttributesAnyOf = {
Expand Down Expand Up @@ -8000,8 +8007,15 @@ export interface SpantypesPostableSpanMapperGroupDTO {
}

export interface SpantypesSpanAggregationDTO {
aggregation?: SpantypesSpanAggregationTypeDTO;
field?: TelemetrytypesTelemetryFieldKeyDTO;
aggregation: SpantypesSpanAggregationTypeDTO;
field: TelemetrytypesTelemetryFieldKeyDTO;
}

export interface SpantypesPostableTraceAggregationsDTO {
/**
* @type array
*/
aggregations: SpantypesSpanAggregationDTO[];
}

export interface SpantypesPostableWaterfallDTO {
Expand Down Expand Up @@ -9344,6 +9358,17 @@ export type UpdateSpanMapperPathParameters = {
groupId: string;
mapperId: string;
};
export type GetTraceAggregationsPathParameters = {
traceID: string;
};
export type GetTraceAggregations200 = {
data: SpantypesGettableTraceAggregationsDTO;
/**
* @type string
*/
status: string;
};

export type ListUsersDeprecated200 = {
/**
* @type array
Expand Down
103 changes: 103 additions & 0 deletions frontend/src/api/generated/services/tracedetail/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,120 @@ import type {
} from 'react-query';

import type {
GetTraceAggregations200,
GetTraceAggregationsPathParameters,
GetWaterfall200,
GetWaterfallPathParameters,
GetWaterfallV4200,
GetWaterfallV4PathParameters,
RenderErrorResponseDTO,
SpantypesPostableTraceAggregationsDTO,
SpantypesPostableWaterfallDTO,
} from '../sigNoz.schemas';

import { GeneratedAPIInstance } from '../../../generatedAPIInstance';
import type { ErrorType, BodyType } from '../../../generatedAPIInstance';

/**
* Computes span aggregations grouped by requested field.
* @summary Get aggregations for a trace
*/
export const getTraceAggregations = (
{ traceID }: GetTraceAggregationsPathParameters,
spantypesPostableTraceAggregationsDTO?: BodyType<SpantypesPostableTraceAggregationsDTO>,
signal?: AbortSignal,
) => {
return GeneratedAPIInstance<GetTraceAggregations200>({
url: `/api/v1/traces/${traceID}/aggregations`,
method: 'POST',
headers: { 'Content-Type': 'application/json' },
data: spantypesPostableTraceAggregationsDTO,
signal,
});
};

export const getGetTraceAggregationsMutationOptions = <
TError = ErrorType<RenderErrorResponseDTO>,
TContext = unknown,
>(options?: {
mutation?: UseMutationOptions<
Awaited<ReturnType<typeof getTraceAggregations>>,
TError,
{
pathParams: GetTraceAggregationsPathParameters;
data?: BodyType<SpantypesPostableTraceAggregationsDTO>;
},
TContext
>;
}): UseMutationOptions<
Awaited<ReturnType<typeof getTraceAggregations>>,
TError,
{
pathParams: GetTraceAggregationsPathParameters;
data?: BodyType<SpantypesPostableTraceAggregationsDTO>;
},
TContext
> => {
const mutationKey = ['getTraceAggregations'];
const { mutation: mutationOptions } = options
? options.mutation &&
'mutationKey' in options.mutation &&
options.mutation.mutationKey
? options
: { ...options, mutation: { ...options.mutation, mutationKey } }
: { mutation: { mutationKey } };

const mutationFn: MutationFunction<
Awaited<ReturnType<typeof getTraceAggregations>>,
{
pathParams: GetTraceAggregationsPathParameters;
data?: BodyType<SpantypesPostableTraceAggregationsDTO>;
}
> = (props) => {
const { pathParams, data } = props ?? {};

return getTraceAggregations(pathParams, data);
};

return { mutationFn, ...mutationOptions };
};

export type GetTraceAggregationsMutationResult = NonNullable<
Awaited<ReturnType<typeof getTraceAggregations>>
>;
export type GetTraceAggregationsMutationBody =
| BodyType<SpantypesPostableTraceAggregationsDTO>
| undefined;
export type GetTraceAggregationsMutationError =
ErrorType<RenderErrorResponseDTO>;

/**
* @summary Get aggregations for a trace
*/
export const useGetTraceAggregations = <
TError = ErrorType<RenderErrorResponseDTO>,
TContext = unknown,
>(options?: {
mutation?: UseMutationOptions<
Awaited<ReturnType<typeof getTraceAggregations>>,
TError,
{
pathParams: GetTraceAggregationsPathParameters;
data?: BodyType<SpantypesPostableTraceAggregationsDTO>;
},
TContext
>;
}): UseMutationResult<
Awaited<ReturnType<typeof getTraceAggregations>>,
TError,
{
pathParams: GetTraceAggregationsPathParameters;
data?: BodyType<SpantypesPostableTraceAggregationsDTO>;
},
TContext
> => {
return useMutation(getGetTraceAggregationsMutationOptions(options));
};
/**
* Returns the waterfall view of spans for a given trace ID with tree structure, metadata, and windowed pagination
* @summary Get waterfall view for a trace
Expand Down
19 changes: 19 additions & 0 deletions pkg/apiserver/signozapiserver/tracedetail.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,24 @@ func (provider *provider) addTraceDetailRoutes(router *mux.Router) error {
return err
}

if err := router.Handle("/api/v1/traces/{traceID}/aggregations", handler.New(
provider.authzMiddleware.ViewAccess(provider.traceDetailHandler.GetTraceAggregations),
handler.OpenAPIDef{
ID: "GetTraceAggregations",
Tags: []string{"tracedetail"},
Summary: "Get aggregations for a trace",
Description: "Computes span aggregations grouped by requested field.",
Request: new(spantypes.PostableTraceAggregations),
RequestContentType: "application/json",
Response: new(spantypes.GettableTraceAggregations),
ResponseContentType: "application/json",
SuccessStatusCode: http.StatusOK,
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
},
)).Methods(http.MethodPost).GetError(); err != nil {
return err
}

return nil
}
21 changes: 21 additions & 0 deletions pkg/modules/tracedetail/impltracedetail/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,24 @@ func (h *handler) GetWaterfallV4(rw http.ResponseWriter, r *http.Request) {

render.Success(rw, http.StatusOK, result)
}

func (h *handler) GetTraceAggregations(rw http.ResponseWriter, r *http.Request) {
req := new(spantypes.PostableTraceAggregations)
if err := binding.JSON.BindBody(r.Body, req); err != nil {
render.Error(rw, err)
return
}

if err := req.Validate(); err != nil {
render.Error(rw, err)
return
}

result, err := h.module.GetTraceAggregations(r.Context(), mux.Vars(r)["traceID"], req)
if err != nil {
render.Error(rw, err)
return
}

render.Success(rw, http.StatusOK, result)
}
Loading
Loading