diff --git a/frontend/src/container/SpanDetailsDrawer/Events/Events.tsx b/frontend/src/container/SpanDetailsDrawer/Events/Events.tsx
index e339f3f9a2..4eccd8254c 100644
--- a/frontend/src/container/SpanDetailsDrawer/Events/Events.tsx
+++ b/frontend/src/container/SpanDetailsDrawer/Events/Events.tsx
@@ -45,7 +45,7 @@ function EventsTable(props: IEventsTableProps): JSX.Element {
)}
{events
.filter((eve) =>
- eve.name.toLowerCase().includes(fieldSearchInput.toLowerCase()),
+ eve.name?.toLowerCase().includes(fieldSearchInput.toLowerCase()),
)
.map((event) => (
{getYAxisFormattedValue(
- `${event.timeUnixNano / 1e6 - startTime}`,
+ `${(event.timeUnixNano || 0) / 1e6 - startTime}`,
'ms',
)}
diff --git a/frontend/src/container/TraceWaterfall/TraceWaterfallStates/Success/Success.styles.scss b/frontend/src/container/TraceWaterfall/TraceWaterfallStates/Success/Success.styles.scss
index 67091de747..95872a882c 100644
--- a/frontend/src/container/TraceWaterfall/TraceWaterfallStates/Success/Success.styles.scss
+++ b/frontend/src/container/TraceWaterfall/TraceWaterfallStates/Success/Success.styles.scss
@@ -241,18 +241,19 @@
height: 54px;
position: relative;
width: 100%;
+ padding-left: 15px;
cursor: pointer;
.span-line {
- position: absolute;
+ position: relative;
height: 12px;
top: 35%;
border-radius: 6px;
}
.span-line-text {
- position: absolute;
- top: 65%;
+ position: relative;
+ top: 40%;
font-variant-numeric: lining-nums tabular-nums stacked-fractions
slashed-zero;
font-feature-settings: 'case' on, 'cpsp' on, 'dlig' on, 'salt' on;
diff --git a/frontend/src/container/TraceWaterfall/TraceWaterfallStates/Success/Success.tsx b/frontend/src/container/TraceWaterfall/TraceWaterfallStates/Success/Success.tsx
index d87bdf877d..b3a113665f 100644
--- a/frontend/src/container/TraceWaterfall/TraceWaterfallStates/Success/Success.tsx
+++ b/frontend/src/container/TraceWaterfall/TraceWaterfallStates/Success/Success.tsx
@@ -188,14 +188,13 @@ function SpanDuration({
left: `${leftOffset}%`,
width: `${width}%`,
backgroundColor: color,
- marginLeft: '15px',
}}
/>
{`${toFixed(time, 2)} ${timeUnitName}`}
diff --git a/pkg/query-service/app/clickhouseReader/reader.go b/pkg/query-service/app/clickhouseReader/reader.go
index f3769061ef..e98dd0368c 100644
--- a/pkg/query-service/app/clickhouseReader/reader.go
+++ b/pkg/query-service/app/clickhouseReader/reader.go
@@ -1452,7 +1452,9 @@ func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadata(ctx context.Con
var traceRoots []*model.Span
var serviceNameToTotalDurationMap = map[string]uint64{}
var serviceNameIntervalMap = map[string][]tracedetail.Interval{}
+ var hasMissingSpans bool
+ userEmail , emailErr := auth.GetEmailFromJwt(ctx)
cachedTraceData, err := r.GetWaterfallSpansForTraceWithMetadataCache(ctx, traceID)
if err == nil {
startTime = cachedTraceData.StartTime
@@ -1463,6 +1465,11 @@ func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadata(ctx context.Con
traceRoots = cachedTraceData.TraceRoots
totalSpans = cachedTraceData.TotalSpans
totalErrorSpans = cachedTraceData.TotalErrorSpans
+ hasMissingSpans = cachedTraceData.HasMissingSpans
+
+ if emailErr == nil {
+ telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_TRACE_DETAIL_API, map[string]interface{}{"traceSize": totalSpans}, userEmail, true, false)
+ }
}
if err != nil {
@@ -1477,6 +1484,10 @@ func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadata(ctx context.Con
}
totalSpans = uint64(len(searchScanResponses))
+ if emailErr == nil {
+ telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_TRACE_DETAIL_API, map[string]interface{}{"traceSize": totalSpans}, userEmail, true, false)
+ }
+
processingBeforeCache := time.Now()
for _, item := range searchScanResponses {
ref := []model.OtelSpanRef{}
@@ -1514,7 +1525,23 @@ func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadata(ctx context.Con
Children: make([]*model.Span, 0),
}
- // convert start timestamp to millis
+ // metadata calculation
+ startTimeUnixNano := uint64(item.TimeUnixNano.UnixNano())
+ if startTime == 0 || startTimeUnixNano < startTime {
+ startTime = startTimeUnixNano
+ }
+ if endTime == 0 || (startTimeUnixNano + jsonItem.DurationNano ) > endTime {
+ endTime = (startTimeUnixNano + jsonItem.DurationNano )
+ }
+ if durationNano == 0 || jsonItem.DurationNano > durationNano {
+ durationNano = jsonItem.DurationNano
+ }
+
+ if jsonItem.HasError {
+ totalErrorSpans = totalErrorSpans + 1
+ }
+
+ // convert start timestamp to millis because right now frontend is expecting it in millis
jsonItem.TimeUnixNano = uint64(item.TimeUnixNano.UnixNano() / 1000000)
// collect the intervals for service for execution time calculation
@@ -1523,20 +1550,6 @@ func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadata(ctx context.Con
// append to the span node map
spanIdToSpanNodeMap[jsonItem.SpanID] = &jsonItem
-
- // metadata calculation
- if startTime == 0 || jsonItem.TimeUnixNano < startTime {
- startTime = jsonItem.TimeUnixNano
- }
- if endTime == 0 || (jsonItem.TimeUnixNano+(jsonItem.DurationNano/1000000)) > endTime {
- endTime = jsonItem.TimeUnixNano + (jsonItem.DurationNano / 1000000)
- }
- if durationNano == 0 || jsonItem.DurationNano > durationNano {
- durationNano = jsonItem.DurationNano
- }
- if jsonItem.HasError {
- totalErrorSpans = totalErrorSpans + 1
- }
}
// traverse through the map and append each node to the children array of the parent node
@@ -1568,6 +1581,7 @@ func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadata(ctx context.Con
missingSpan.Children = append(missingSpan.Children, spanNode)
spanIdToSpanNodeMap[missingSpan.SpanID] = &missingSpan
traceRoots = append(traceRoots, &missingSpan)
+ hasMissingSpans = true
}
}
}
@@ -1595,6 +1609,7 @@ func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadata(ctx context.Con
SpanIdToSpanNodeMap: spanIdToSpanNodeMap,
ServiceNameToTotalDurationMap: serviceNameToTotalDurationMap,
TraceRoots: traceRoots,
+ HasMissingSpans: hasMissingSpans,
}
zap.L().Info("getWaterfallSpansForTraceWithMetadata: processing pre cache", zap.Duration("duration", time.Since(processingBeforeCache)), zap.String("traceID", traceID))
@@ -1610,14 +1625,14 @@ func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadata(ctx context.Con
response.Spans = selectedSpans
response.UncollapsedSpans = uncollapsedSpans
- response.StartTimestampMillis = startTime
- response.EndTimestampMillis = endTime
+ response.StartTimestampMillis = startTime / 1000000
+ response.EndTimestampMillis = endTime / 1000000
response.TotalSpansCount = totalSpans
response.TotalErrorSpansCount = totalErrorSpans
response.RootServiceName = rootServiceName
response.RootServiceEntryPoint = rootServiceEntryPoint
response.ServiceNameToTotalDurationMap = serviceNameToTotalDurationMap
- response.HasMissingSpans = len(traceRoots) > 1
+ response.HasMissingSpans = hasMissingSpans
return response, nil
}
@@ -1692,19 +1707,20 @@ func (r *ClickHouseReader) GetFlamegraphSpansForTrace(ctx context.Context, trace
Children: make([]*model.FlamegraphSpan, 0),
}
- jsonItem.TimeUnixNano = uint64(item.TimeUnixNano.UnixNano() / 1000000)
- spanIdToSpanNodeMap[jsonItem.SpanID] = &jsonItem
-
// metadata calculation
- if startTime == 0 || jsonItem.TimeUnixNano < startTime {
- startTime = jsonItem.TimeUnixNano
+ startTimeUnixNano := uint64(item.TimeUnixNano.UnixNano())
+ if startTime == 0 || startTimeUnixNano < startTime {
+ startTime = startTimeUnixNano
}
- if endTime == 0 || (jsonItem.TimeUnixNano+(jsonItem.DurationNano/1000000)) > endTime {
- endTime = jsonItem.TimeUnixNano + (jsonItem.DurationNano / 1000000)
+ if endTime == 0 || ( startTimeUnixNano + jsonItem.DurationNano ) > endTime {
+ endTime = (startTimeUnixNano + jsonItem.DurationNano )
}
if durationNano == 0 || jsonItem.DurationNano > durationNano {
durationNano = jsonItem.DurationNano
}
+
+ jsonItem.TimeUnixNano = uint64(item.TimeUnixNano.UnixNano() / 1000000)
+ spanIdToSpanNodeMap[jsonItem.SpanID] = &jsonItem
}
// traverse through the map and append each node to the children array of the parent node
@@ -1760,8 +1776,8 @@ func (r *ClickHouseReader) GetFlamegraphSpansForTrace(ctx context.Context, trace
zap.L().Info("getFlamegraphSpansForTrace: processing post cache", zap.Duration("duration", time.Since(processingPostCache)), zap.String("traceID", traceID))
trace.Spans = selectedSpansForRequest
- trace.StartTimestampMillis = startTime
- trace.EndTimestampMillis = endTime
+ trace.StartTimestampMillis = startTime / 1000000
+ trace.EndTimestampMillis = endTime / 1000000
return trace, nil
}
diff --git a/pkg/query-service/app/traces/tracedetail/flamegraph.go b/pkg/query-service/app/traces/tracedetail/flamegraph.go
index b2c2c81b52..5cfd7c34e8 100644
--- a/pkg/query-service/app/traces/tracedetail/flamegraph.go
+++ b/pkg/query-service/app/traces/tracedetail/flamegraph.go
@@ -149,7 +149,7 @@ func getLatencyAndTimestampBucketedSpans(spans []*model.FlamegraphSpan, selected
}
func GetSelectedSpansForFlamegraphForRequest(selectedSpanID string, selectedSpans [][]*model.FlamegraphSpan, startTime uint64, endTime uint64) [][]*model.FlamegraphSpan {
- var selectedSpansForRequest [][]*model.FlamegraphSpan
+ var selectedSpansForRequest = make([][]*model.FlamegraphSpan, 0)
var selectedIndex = 0
if selectedSpanID != "" {
diff --git a/pkg/query-service/app/traces/tracedetail/waterfall.go b/pkg/query-service/app/traces/tracedetail/waterfall.go
index 36aa88ef4f..dace19ea7e 100644
--- a/pkg/query-service/app/traces/tracedetail/waterfall.go
+++ b/pkg/query-service/app/traces/tracedetail/waterfall.go
@@ -158,7 +158,7 @@ func CalculateServiceTime(serviceIntervals map[string][]Interval) map[string]uin
func GetSelectedSpans(uncollapsedSpans []string, selectedSpanID string, traceRoots []*model.Span, spanIdToSpanNodeMap map[string]*model.Span, isSelectedSpanIDUnCollapsed bool) ([]*model.Span, []string, string, string) {
- var preOrderTraversal = []*model.Span{}
+ var preOrderTraversal = make([]*model.Span, 0)
var rootServiceName, rootServiceEntryPoint string
updatedUncollapsedSpans := uncollapsedSpans
diff --git a/pkg/query-service/model/cacheable.go b/pkg/query-service/model/cacheable.go
index b691b2765a..d1de82ab37 100644
--- a/pkg/query-service/model/cacheable.go
+++ b/pkg/query-service/model/cacheable.go
@@ -11,6 +11,7 @@ type GetWaterfallSpansForTraceWithMetadataCache struct {
ServiceNameToTotalDurationMap map[string]uint64 `json:"serviceNameToTotalDurationMap"`
SpanIdToSpanNodeMap map[string]*Span `json:"spanIdToSpanNodeMap"`
TraceRoots []*Span `json:"traceRoots"`
+ HasMissingSpans bool `json:"hasMissingSpans"`
}
func (c *GetWaterfallSpansForTraceWithMetadataCache) MarshalBinary() (data []byte, err error) {