Compare commits

...

2 Commits

Author SHA1 Message Date
Nikhil Soni
e7a8231ff8 chore: update openapi specs 2026-05-18 15:29:30 +05:30
Nikhil Soni
4fdee20976 chore: remove unused field from waterfall v3 2026-05-18 15:29:19 +05:30
6 changed files with 46 additions and 95 deletions

View File

@@ -5937,12 +5937,6 @@ components:
type: string
rootServiceName:
type: string
serviceNameToTotalDurationMap:
additionalProperties:
minimum: 0
type: integer
nullable: true
type: object
spans:
items:
$ref: '#/components/schemas/TracedetailtypesWaterfallSpan'

View File

@@ -6895,15 +6895,6 @@ export interface TracedetailtypesEventDTO {
timeUnixNano?: number;
}
export type TracedetailtypesGettableWaterfallTraceDTOServiceNameToTotalDurationMapAnyOf =
{ [key: string]: number };
/**
* @nullable
*/
export type TracedetailtypesGettableWaterfallTraceDTOServiceNameToTotalDurationMap =
TracedetailtypesGettableWaterfallTraceDTOServiceNameToTotalDurationMapAnyOf | null;
export enum TracedetailtypesSpanAggregationTypeDTO {
span_count = 'span_count',
execution_time_percentage = 'execution_time_percentage',
@@ -7094,10 +7085,6 @@ export interface TracedetailtypesGettableWaterfallTraceDTO {
* @type string
*/
rootServiceName?: string;
/**
* @type object,null
*/
serviceNameToTotalDurationMap?: TracedetailtypesGettableWaterfallTraceDTOServiceNameToTotalDurationMap;
/**
* @type array,null
*/

View File

@@ -97,7 +97,7 @@ func makeChain(n int) (*tracedetailtypes.WaterfallSpan, map[string]*tracedetailt
}
func getWaterfallTrace(roots []*tracedetailtypes.WaterfallSpan, spanMap map[string]*tracedetailtypes.WaterfallSpan) *tracedetailtypes.WaterfallTrace {
return tracedetailtypes.NewWaterfallTrace(0, 0, uint64(len(spanMap)), 0, spanMap, nil, roots, false)
return tracedetailtypes.NewWaterfallTrace(0, 0, uint64(len(spanMap)), 0, spanMap, roots, false)
}
// ─────────────────────────────────────────────────────────────────────────────

View File

@@ -1160,6 +1160,7 @@ func (r *ClickHouseReader) GetFlamegraphSpansForTrace(ctx context.Context, orgID
selectCols += ", attributes_string, attributes_number, attributes_bool, resources_string"
}
flamegraphQuery := fmt.Sprintf("SELECT %s FROM %s.%s WHERE trace_id=$1 and ts_bucket_start>=$2 and ts_bucket_start<=$3 ORDER BY timestamp ASC, name ASC", selectCols, r.TraceDB, r.traceTableName)
fmt.Printf("============== selectCols: %s, flamegraphQuery: %s", selectCols, flamegraphQuery)
searchScanResponses, err := r.GetSpansForTrace(ctx, traceID, flamegraphQuery)
if err != nil {

View File

@@ -33,7 +33,7 @@ func buildTraceFromSpans(spans ...*WaterfallSpan) *WaterfallTrace {
endTime = end
}
}
return NewWaterfallTrace(startTime, endTime, uint64(len(spanMap)), 0, spanMap, nil, nil, false)
return NewWaterfallTrace(startTime, endTime, uint64(len(spanMap)), 0, spanMap, nil, false)
}
var (

View File

@@ -20,50 +20,45 @@ type TraceSummary struct {
// WaterfallTrace holds processed trace data with childern populated in spans.
type WaterfallTrace struct {
StartTime uint64 `json:"startTime"`
EndTime uint64 `json:"endTime"`
TotalSpans uint64 `json:"totalSpans"`
TotalErrorSpans uint64 `json:"totalErrorSpans"`
ServiceNameToTotalDurationMap map[string]uint64 `json:"serviceNameToTotalDurationMap"`
SpanIDToSpanNodeMap map[string]*WaterfallSpan `json:"spanIdToSpanNodeMap"`
TraceRoots []*WaterfallSpan `json:"traceRoots"`
HasMissingSpans bool `json:"hasMissingSpans"`
StartTime uint64 `json:"startTime"`
EndTime uint64 `json:"endTime"`
TotalSpans uint64 `json:"totalSpans"`
TotalErrorSpans uint64 `json:"totalErrorSpans"`
SpanIDToSpanNodeMap map[string]*WaterfallSpan `json:"spanIdToSpanNodeMap"`
TraceRoots []*WaterfallSpan `json:"traceRoots"`
HasMissingSpans bool `json:"hasMissingSpans"`
}
// GettableWaterfallTrace is the response for the v3 waterfall API.
type GettableWaterfallTrace struct {
StartTimestampMillis uint64 `json:"startTimestampMillis"`
EndTimestampMillis uint64 `json:"endTimestampMillis"`
RootServiceName string `json:"rootServiceName"`
RootServiceEntryPoint string `json:"rootServiceEntryPoint"`
TotalSpansCount uint64 `json:"totalSpansCount"`
TotalErrorSpansCount uint64 `json:"totalErrorSpansCount"`
// Deprecated: use Aggregations with SpanAggregationExecutionTimePercentage on the service.name field instead.
ServiceNameToTotalDurationMap map[string]uint64 `json:"serviceNameToTotalDurationMap"`
Spans []*WaterfallSpan `json:"spans"`
HasMissingSpans bool `json:"hasMissingSpans"`
UncollapsedSpans []string `json:"uncollapsedSpans"`
HasMore bool `json:"hasMore"`
Aggregations []SpanAggregationResult `json:"aggregations"`
StartTimestampMillis uint64 `json:"startTimestampMillis"`
EndTimestampMillis uint64 `json:"endTimestampMillis"`
RootServiceName string `json:"rootServiceName"`
RootServiceEntryPoint string `json:"rootServiceEntryPoint"`
TotalSpansCount uint64 `json:"totalSpansCount"`
TotalErrorSpansCount uint64 `json:"totalErrorSpansCount"`
Spans []*WaterfallSpan `json:"spans"`
HasMissingSpans bool `json:"hasMissingSpans"`
UncollapsedSpans []string `json:"uncollapsedSpans"`
HasMore bool `json:"hasMore"`
Aggregations []SpanAggregationResult `json:"aggregations"`
}
// NewWaterfallTrace constructs a WaterfallTrace from processed span data.
func NewWaterfallTrace(
startTime, endTime, totalSpans, totalErrorSpans uint64,
spanIDToSpanNodeMap map[string]*WaterfallSpan,
serviceNameToTotalDurationMap map[string]uint64,
traceRoots []*WaterfallSpan,
hasMissingSpans bool,
) *WaterfallTrace {
return &WaterfallTrace{
StartTime: startTime,
EndTime: endTime,
TotalSpans: totalSpans,
TotalErrorSpans: totalErrorSpans,
SpanIDToSpanNodeMap: spanIDToSpanNodeMap,
ServiceNameToTotalDurationMap: serviceNameToTotalDurationMap,
TraceRoots: traceRoots,
HasMissingSpans: hasMissingSpans,
StartTime: startTime,
EndTime: endTime,
TotalSpans: totalSpans,
TotalErrorSpans: totalErrorSpans,
SpanIDToSpanNodeMap: spanIDToSpanNodeMap,
TraceRoots: traceRoots,
HasMissingSpans: hasMissingSpans,
}
}
@@ -124,7 +119,6 @@ func NewWaterfallTraceFromSpans(spans []StorableSpan) *WaterfallTrace {
uint64(len(spans)),
totalErrorSpans,
spanIDToSpanNodeMap,
calculateServiceTime(spanIDToSpanNodeMap),
traceRoots,
hasMissingSpans,
)
@@ -206,23 +200,19 @@ func (wt *WaterfallTrace) CalculateUncollapsedSpanIDs(uncollapsedSpanIDs []strin
}
func (wt *WaterfallTrace) Clone() cachetypes.Cacheable {
copyOfServiceNameToTotalDurationMap := make(map[string]uint64)
maps.Copy(copyOfServiceNameToTotalDurationMap, wt.ServiceNameToTotalDurationMap)
copyOfSpanIDToSpanNodeMap := make(map[string]*WaterfallSpan)
maps.Copy(copyOfSpanIDToSpanNodeMap, wt.SpanIDToSpanNodeMap)
copyOfTraceRoots := make([]*WaterfallSpan, len(wt.TraceRoots))
copy(copyOfTraceRoots, wt.TraceRoots)
return &WaterfallTrace{
StartTime: wt.StartTime,
EndTime: wt.EndTime,
TotalSpans: wt.TotalSpans,
TotalErrorSpans: wt.TotalErrorSpans,
ServiceNameToTotalDurationMap: copyOfServiceNameToTotalDurationMap,
SpanIDToSpanNodeMap: copyOfSpanIDToSpanNodeMap,
TraceRoots: copyOfTraceRoots,
HasMissingSpans: wt.HasMissingSpans,
StartTime: wt.StartTime,
EndTime: wt.EndTime,
TotalSpans: wt.TotalSpans,
TotalErrorSpans: wt.TotalErrorSpans,
SpanIDToSpanNodeMap: copyOfSpanIDToSpanNodeMap,
TraceRoots: copyOfTraceRoots,
HasMissingSpans: wt.HasMissingSpans,
}
}
@@ -257,11 +247,6 @@ func NewGettableWaterfallTrace(
rootServiceEntryPoint = traceData.TraceRoots[0].Name
}
serviceDurationsMillis := make(map[string]uint64, len(traceData.ServiceNameToTotalDurationMap))
for svc, dur := range traceData.ServiceNameToTotalDurationMap {
serviceDurationsMillis[svc] = dur / 1_000_000
}
// convert start timestamp to millis because client is expecting it in millis
for _, span := range selectedSpans {
span.TimeUnix = span.TimeUnix / 1_000_000
@@ -277,18 +262,17 @@ func NewGettableWaterfallTrace(
}
return &GettableWaterfallTrace{
Spans: selectedSpans,
UncollapsedSpans: uncollapsedSpans,
StartTimestampMillis: traceData.StartTime / 1_000_000,
EndTimestampMillis: traceData.EndTime / 1_000_000,
TotalSpansCount: traceData.TotalSpans,
TotalErrorSpansCount: traceData.TotalErrorSpans,
RootServiceName: rootServiceName,
RootServiceEntryPoint: rootServiceEntryPoint,
ServiceNameToTotalDurationMap: serviceDurationsMillis,
HasMissingSpans: traceData.HasMissingSpans,
HasMore: !selectAllSpans,
Aggregations: aggregations,
Spans: selectedSpans,
UncollapsedSpans: uncollapsedSpans,
StartTimestampMillis: traceData.StartTime / 1_000_000,
EndTimestampMillis: traceData.EndTime / 1_000_000,
TotalSpansCount: traceData.TotalSpans,
TotalErrorSpansCount: traceData.TotalErrorSpans,
RootServiceName: rootServiceName,
RootServiceEntryPoint: rootServiceEntryPoint,
HasMissingSpans: traceData.HasMissingSpans,
HasMore: !selectAllSpans,
Aggregations: aggregations,
}
}
@@ -311,21 +295,6 @@ func windowAroundIndex(selectedIndex, total int, spanLimitPerRequest float64) (s
return
}
func calculateServiceTime(spanIDToSpanNodeMap map[string]*WaterfallSpan) map[string]uint64 {
serviceSpans := make(map[string][]*WaterfallSpan)
for _, span := range spanIDToSpanNodeMap {
if span.ServiceName != "" {
serviceSpans[span.ServiceName] = append(serviceSpans[span.ServiceName], span)
}
}
totalTimes := make(map[string]uint64)
for service, spans := range serviceSpans {
totalTimes[service] = mergeSpanIntervals(spans)
}
return totalTimes
}
// mergeSpanIntervals computes non-overlapping execution time for a set of spans.
func mergeSpanIntervals(spans []*WaterfallSpan) uint64 {
if len(spans) == 0 {