diff --git a/deploy/docker/clickhouse-setup/docker-compose-core.yaml b/deploy/docker/clickhouse-setup/docker-compose-core.yaml
index f4c1d9f1ee..5bade6b2da 100644
--- a/deploy/docker/clickhouse-setup/docker-compose-core.yaml
+++ b/deploy/docker/clickhouse-setup/docker-compose-core.yaml
@@ -72,7 +72,9 @@ services:
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.111.14}
container_name: otel-migrator
command:
+ - "sync"
- "--dsn=tcp://clickhouse:9000"
+ - "--up="
depends_on:
clickhouse:
condition: service_healthy
diff --git a/frontend/src/container/MetricsApplication/Tabs/Overview.tsx b/frontend/src/container/MetricsApplication/Tabs/Overview.tsx
index 77bf86b80f..6decf72b39 100644
--- a/frontend/src/container/MetricsApplication/Tabs/Overview.tsx
+++ b/frontend/src/container/MetricsApplication/Tabs/Overview.tsx
@@ -145,41 +145,49 @@ function Application(): JSX.Element {
[servicename, topLevelOperations],
);
- const operationPerSecWidget = getWidgetQueryBuilder({
- query: {
- queryType: EQueryType.QUERY_BUILDER,
- promql: [],
- builder: operationPerSec({
- servicename,
- tagFilterItems,
- topLevelOperations: topLevelOperationsRoute,
+ const operationPerSecWidget = useMemo(
+ () =>
+ getWidgetQueryBuilder({
+ query: {
+ queryType: EQueryType.QUERY_BUILDER,
+ promql: [],
+ builder: operationPerSec({
+ servicename,
+ tagFilterItems,
+ topLevelOperations: topLevelOperationsRoute,
+ }),
+ clickhouse_sql: [],
+ id: uuid(),
+ },
+ title: GraphTitle.RATE_PER_OPS,
+ panelTypes: PANEL_TYPES.TIME_SERIES,
+ yAxisUnit: 'ops',
+ id: SERVICE_CHART_ID.rps,
}),
- clickhouse_sql: [],
- id: uuid(),
- },
- title: GraphTitle.RATE_PER_OPS,
- panelTypes: PANEL_TYPES.TIME_SERIES,
- yAxisUnit: 'ops',
- id: SERVICE_CHART_ID.rps,
- });
+ [servicename, tagFilterItems, topLevelOperationsRoute],
+ );
- const errorPercentageWidget = getWidgetQueryBuilder({
- query: {
- queryType: EQueryType.QUERY_BUILDER,
- promql: [],
- builder: errorPercentage({
- servicename,
- tagFilterItems,
- topLevelOperations: topLevelOperationsRoute,
+ const errorPercentageWidget = useMemo(
+ () =>
+ getWidgetQueryBuilder({
+ query: {
+ queryType: EQueryType.QUERY_BUILDER,
+ promql: [],
+ builder: errorPercentage({
+ servicename,
+ tagFilterItems,
+ topLevelOperations: topLevelOperationsRoute,
+ }),
+ clickhouse_sql: [],
+ id: uuid(),
+ },
+ title: GraphTitle.ERROR_PERCENTAGE,
+ panelTypes: PANEL_TYPES.TIME_SERIES,
+ yAxisUnit: '%',
+ id: SERVICE_CHART_ID.errorPercentage,
}),
- clickhouse_sql: [],
- id: uuid(),
- },
- title: GraphTitle.ERROR_PERCENTAGE,
- panelTypes: PANEL_TYPES.TIME_SERIES,
- yAxisUnit: '%',
- id: SERVICE_CHART_ID.errorPercentage,
- });
+ [servicename, tagFilterItems, topLevelOperationsRoute],
+ );
const stepInterval = useMemo(
() =>
diff --git a/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx b/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx
index 24e2233244..42f54c1448 100644
--- a/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx
+++ b/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx
@@ -53,24 +53,28 @@ function ServiceOverview({
[isSpanMetricEnable, queries],
);
- const latencyWidget = getWidgetQueryBuilder({
- query: {
- queryType: EQueryType.QUERY_BUILDER,
- promql: [],
- builder: latency({
- servicename,
- tagFilterItems,
- isSpanMetricEnable,
- topLevelOperationsRoute,
+ const latencyWidget = useMemo(
+ () =>
+ getWidgetQueryBuilder({
+ query: {
+ queryType: EQueryType.QUERY_BUILDER,
+ promql: [],
+ builder: latency({
+ servicename,
+ tagFilterItems,
+ isSpanMetricEnable,
+ topLevelOperationsRoute,
+ }),
+ clickhouse_sql: [],
+ id: uuid(),
+ },
+ title: GraphTitle.LATENCY,
+ panelTypes: PANEL_TYPES.TIME_SERIES,
+ yAxisUnit: 'ns',
+ id: SERVICE_CHART_ID.latency,
}),
- clickhouse_sql: [],
- id: uuid(),
- },
- title: GraphTitle.LATENCY,
- panelTypes: PANEL_TYPES.TIME_SERIES,
- yAxisUnit: 'ns',
- id: SERVICE_CHART_ID.latency,
- });
+ [isSpanMetricEnable, servicename, tagFilterItems, topLevelOperationsRoute],
+ );
const isQueryEnabled =
!topLevelOperationsIsLoading && topLevelOperationsRoute.length > 0;
diff --git a/frontend/src/container/SideNav/SideNav.tsx b/frontend/src/container/SideNav/SideNav.tsx
index f3bdbe0870..6116196bcc 100644
--- a/frontend/src/container/SideNav/SideNav.tsx
+++ b/frontend/src/container/SideNav/SideNav.tsx
@@ -16,7 +16,7 @@ import history from 'lib/history';
import {
AlertTriangle,
CheckSquare,
- RocketIcon,
+ PackagePlus,
UserCircle,
} from 'lucide-react';
import { MouseEvent, useCallback, useEffect, useMemo, useState } from 'react';
@@ -395,9 +395,9 @@ function SideNav({
onClickGetStarted(event);
}}
>
-
+
-
Get Started
+ New source
)}
diff --git a/pkg/query-service/app/clickhouseReader/reader.go b/pkg/query-service/app/clickhouseReader/reader.go
index 256ab98d68..4f1aa99dfc 100644
--- a/pkg/query-service/app/clickhouseReader/reader.go
+++ b/pkg/query-service/app/clickhouseReader/reader.go
@@ -1203,7 +1203,9 @@ func (r *ClickHouseReader) GetUsage(ctx context.Context, queryParams *model.GetU
return &usageItems, nil
}
-func (r *ClickHouseReader) SearchTracesV2(ctx context.Context, params *model.SearchTracesParams) (*[]model.SearchSpansResult, error) {
+func (r *ClickHouseReader) SearchTracesV2(ctx context.Context, params *model.SearchTracesParams,
+ smartTraceAlgorithm func(payload []model.SearchSpanResponseItem, targetSpanId string,
+ levelUp int, levelDown int, spanLimit int) ([]model.SearchSpansResult, error)) (*[]model.SearchSpansResult, error) {
searchSpansResult := []model.SearchSpansResult{
{
Columns: []string{"__time", "SpanId", "TraceId", "ServiceName", "Name", "Kind", "DurationNano", "TagsKeys", "TagsValues", "References", "Events", "HasError", "StatusMessage", "StatusCodeString", "SpanKind"},
@@ -1318,9 +1320,29 @@ func (r *ClickHouseReader) SearchTracesV2(ctx context.Context, params *model.Sea
end = time.Now()
zap.L().Debug("getTraceSQLQuery unmarshal took: ", zap.Duration("duration", end.Sub(start)))
- for i, item := range searchSpanResponses {
- spanEvents := item.GetValues()
- searchSpansResult[0].Events[i] = spanEvents
+ err = r.featureFlags.CheckFeature(model.SmartTraceDetail)
+ smartAlgoEnabled := err == nil
+ if len(searchScanResponses) > params.SpansRenderLimit && smartAlgoEnabled {
+ start = time.Now()
+ searchSpansResult, err = smartTraceAlgorithm(searchSpanResponses, params.SpanID, params.LevelUp, params.LevelDown, params.SpansRenderLimit)
+ if err != nil {
+ return nil, err
+ }
+ end = time.Now()
+ zap.L().Debug("smartTraceAlgo took: ", zap.Duration("duration", end.Sub(start)))
+ userEmail, err := auth.GetEmailFromJwt(ctx)
+ if err == nil {
+ data := map[string]interface{}{
+ "traceSize": len(searchScanResponses),
+ "spansRenderLimit": params.SpansRenderLimit,
+ }
+ telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_LARGE_TRACE_OPENED, data, userEmail, true, false)
+ }
+ } else {
+ for i, item := range searchSpanResponses {
+ spanEvents := item.GetValues()
+ searchSpansResult[0].Events[i] = spanEvents
+ }
}
searchSpansResult[0].StartTimestampMillis = startTime - (durationNano / 1000000)
@@ -1334,7 +1356,7 @@ func (r *ClickHouseReader) SearchTraces(ctx context.Context, params *model.Searc
levelUp int, levelDown int, spanLimit int) ([]model.SearchSpansResult, error)) (*[]model.SearchSpansResult, error) {
if r.useTraceNewSchema {
- return r.SearchTracesV2(ctx, params)
+ return r.SearchTracesV2(ctx, params, smartTraceAlgorithm)
}
var countSpans uint64
diff --git a/pkg/query-service/app/http_handler.go b/pkg/query-service/app/http_handler.go
index 5031cf7123..3e25ab23c8 100644
--- a/pkg/query-service/app/http_handler.go
+++ b/pkg/query-service/app/http_handler.go
@@ -3141,14 +3141,14 @@ func (aH *APIHandler) getProducerThroughputOverview(
Hash: make(map[string]struct{}),
}
- queryRangeParams, err := mq.BuildQRParamsWithCache(messagingQueue, "producer-throughput-overview", attributeCache)
+ producerQueryRangeParams, err := mq.BuildQRParamsWithCache(messagingQueue, "producer-throughput-overview", attributeCache)
if err != nil {
zap.L().Error(err.Error())
RespondError(w, apiErr, nil)
return
}
- if err := validateQueryRangeParamsV3(queryRangeParams); err != nil {
+ if err := validateQueryRangeParamsV3(producerQueryRangeParams); err != nil {
zap.L().Error(err.Error())
RespondError(w, apiErr, nil)
return
@@ -3157,7 +3157,7 @@ func (aH *APIHandler) getProducerThroughputOverview(
var result []*v3.Result
var errQuriesByName map[string]error
- result, errQuriesByName, err = aH.querierV2.QueryRange(r.Context(), queryRangeParams)
+ result, errQuriesByName, err = aH.querierV2.QueryRange(r.Context(), producerQueryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQuriesByName)
@@ -3165,21 +3165,21 @@ func (aH *APIHandler) getProducerThroughputOverview(
}
for _, res := range result {
- for _, list := range res.List {
- serviceName, serviceNameOk := list.Data["service_name"].(*string)
- topicName, topicNameOk := list.Data["topic"].(*string)
- params := []string{*serviceName, *topicName}
+ for _, series := range res.Series {
+ serviceName, serviceNameOk := series.Labels["service_name"]
+ topicName, topicNameOk := series.Labels["topic"]
+ params := []string{serviceName, topicName}
hashKey := uniqueIdentifier(params, "#")
_, ok := attributeCache.Hash[hashKey]
if topicNameOk && serviceNameOk && !ok {
attributeCache.Hash[hashKey] = struct{}{}
- attributeCache.TopicName = append(attributeCache.TopicName, *topicName)
- attributeCache.ServiceName = append(attributeCache.ServiceName, *serviceName)
+ attributeCache.TopicName = append(attributeCache.TopicName, topicName)
+ attributeCache.ServiceName = append(attributeCache.ServiceName, serviceName)
}
}
}
- queryRangeParams, err = mq.BuildQRParamsWithCache(messagingQueue, "producer-throughput-overview-latency", attributeCache)
+ queryRangeParams, err := mq.BuildQRParamsWithCache(messagingQueue, "producer-throughput-overview-byte-rate", attributeCache)
if err != nil {
zap.L().Error(err.Error())
RespondError(w, apiErr, nil)
@@ -3198,26 +3198,32 @@ func (aH *APIHandler) getProducerThroughputOverview(
return
}
- latencyColumn := &v3.Result{QueryName: "latency"}
- var latencySeries []*v3.Row
+ byteRateColumn := &v3.Result{QueryName: "byte_rate"}
+ var byteRateSeries []*v3.Series
for _, res := range resultFetchLatency {
- for _, list := range res.List {
- topic, topicOk := list.Data["topic"].(*string)
- serviceName, serviceNameOk := list.Data["service_name"].(*string)
- params := []string{*serviceName, *topic}
+ for _, series := range res.Series {
+ topic, topicOk := series.Labels["topic"]
+ serviceName, serviceNameOk := series.Labels["service_name"]
+ params := []string{serviceName, topic}
hashKey := uniqueIdentifier(params, "#")
_, ok := attributeCache.Hash[hashKey]
if topicOk && serviceNameOk && ok {
- latencySeries = append(latencySeries, list)
+ byteRateSeries = append(byteRateSeries, series)
}
}
}
- latencyColumn.List = latencySeries
- result = append(result, latencyColumn)
+ byteRateColumn.Series = byteRateSeries
+ var latencyColumnResult []*v3.Result
+ latencyColumnResult = append(latencyColumnResult, byteRateColumn)
+ resultFetchLatency = postprocess.TransformToTableForBuilderQueries(latencyColumnResult, queryRangeParams)
+
+ result = postprocess.TransformToTableForClickHouseQueries(result)
+
+ result = append(result, resultFetchLatency[0])
resp := v3.QueryRangeResponse{
- Result: resultFetchLatency,
+ Result: result,
}
aH.Respond(w, resp)
}
diff --git a/pkg/query-service/app/integrations/messagingQueues/kafka/translator.go b/pkg/query-service/app/integrations/messagingQueues/kafka/translator.go
index d7dc96d470..1a60b90e56 100644
--- a/pkg/query-service/app/integrations/messagingQueues/kafka/translator.go
+++ b/pkg/query-service/app/integrations/messagingQueues/kafka/translator.go
@@ -61,14 +61,17 @@ func buildClickHouseQueryNetwork(messagingQueue *MessagingQueue, queueType strin
func buildBuilderQueriesProducerBytes(unixMilliStart, unixMilliEnd int64, attributeCache *Clients) (map[string]*v3.BuilderQuery, error) {
bq := make(map[string]*v3.BuilderQuery)
- queryName := fmt.Sprintf("latency")
+ queryName := fmt.Sprintf("byte_rate")
chq := &v3.BuilderQuery{
QueryName: queryName,
StepInterval: common.MinAllowedStepInterval(unixMilliStart, unixMilliEnd),
DataSource: v3.DataSourceMetrics,
AggregateAttribute: v3.AttributeKey{
- Key: "kafka_producer_byte_rate",
+ Key: "kafka_producer_byte_rate",
+ DataType: v3.AttributeKeyDataTypeFloat64,
+ Type: v3.AttributeKeyType("Gauge"),
+ IsColumn: true,
},
AggregateOperator: v3.AggregateOperatorAvg,
Temporality: v3.Unspecified,
@@ -276,7 +279,7 @@ func BuildQRParamsWithCache(messagingQueue *MessagingQueue, queryContext string,
cq, err = buildCompositeQuery(&v3.ClickHouseQuery{
Query: query,
}, queryContext)
- } else if queryContext == "producer-throughput-overview-latency" {
+ } else if queryContext == "producer-throughput-overview-byte-rate" {
bhq, err := buildBuilderQueriesProducerBytes(unixMilliStart, unixMilliEnd, attributeCache)
if err != nil {
return nil, err
@@ -284,7 +287,8 @@ func BuildQRParamsWithCache(messagingQueue *MessagingQueue, queryContext string,
cq = &v3.CompositeQuery{
QueryType: v3.QueryTypeBuilder,
BuilderQueries: bhq,
- PanelType: v3.PanelTypeList,
+ PanelType: v3.PanelTypeTable,
+ FillGaps: false,
}
}
@@ -315,7 +319,7 @@ func BuildClickHouseQuery(messagingQueue *MessagingQueue, queueType string, quer
if !ok {
return nil, fmt.Errorf("invalid type for Topic")
}
- if queryContext != "consumer-throughput-details" {
+ if !(queryContext == "consumer-throughput-details" || queryContext == "producer-throughput-details") {
partition, ok = messagingQueue.Variables["partition"]
if !ok {
return nil, fmt.Errorf("invalid type for Partition")
@@ -364,7 +368,7 @@ func BuildClickHouseQuery(messagingQueue *MessagingQueue, queueType string, quer
func buildCompositeQuery(chq *v3.ClickHouseQuery, queryContext string) (*v3.CompositeQuery, error) {
- if queryContext == "producer-consumer-eval" || queryContext == "producer-throughput-overview" {
+ if queryContext == "producer-consumer-eval" {
return &v3.CompositeQuery{
QueryType: v3.QueryTypeClickHouseSQL,
ClickHouseQueries: map[string]*v3.ClickHouseQuery{queryContext: chq},