feat: added entry point operations api for the service overview page (#7957)

* feat: added entry point operations api for the service overview page

* feat: added entry point operations api for the service overview page

* feat: added entry point operations api for the service overview page

* feat: added entry point operations api for the service overview page

* feat: added entry point operations api for the service overview page

* feat: added entry point operations api for the service overview page

* feat: added entry point operations api for the service overview page

---------

Co-authored-by: Nityananda Gohain <nityanandagohain@gmail.com>
This commit is contained in:
Ekansh Gupta 2025-05-20 11:28:40 +05:30 committed by GitHub
parent 88239cec4d
commit 7290ab3602
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 73 additions and 0 deletions

View File

@ -23,6 +23,7 @@ import (
"github.com/SigNoz/signoz/pkg/valuer"
"github.com/uptrace/bun"
errorsV2 "github.com/SigNoz/signoz/pkg/errors"
"github.com/google/uuid"
"github.com/pkg/errors"
@ -679,6 +680,60 @@ func addExistsOperator(item model.TagQuery, tagMapType string, not bool) (string
return fmt.Sprintf(" AND %s (%s)", notStr, strings.Join(tagOperatorPair, " OR ")), args
}
func (r *ClickHouseReader) GetEntryPointOperations(ctx context.Context, queryParams *model.GetTopOperationsParams) (*[]model.TopOperationsItem, error) {
// Step 1: Get top operations for the given service
topOps, err := r.GetTopOperations(ctx, queryParams)
if err != nil {
return nil, errorsV2.Wrapf(err, errorsV2.TypeInternal, errorsV2.CodeInternal, "Error in getting Top Operations")
}
if topOps == nil {
return nil, errorsV2.Newf(errorsV2.TypeNotFound, errorsV2.CodeNotFound, "no top operations found")
}
// Step 2: Get entry point operation names for the given service using GetTopLevelOperations
// instead of running a separate query
serviceName := []string{queryParams.ServiceName}
var startTime, endTime time.Time
if queryParams.Start != nil {
startTime = *queryParams.Start
}
if queryParams.End != nil {
endTime = *queryParams.End
}
topLevelOpsResult, apiErr := r.GetTopLevelOperations(ctx, startTime, endTime, serviceName)
if apiErr != nil {
return nil, errorsV2.Wrapf(apiErr.Err, errorsV2.TypeInternal, errorsV2.CodeInternal, "failed to get top level operations")
}
// Create a set of entry point operations
entryPointSet := map[string]struct{}{}
// Extract operations for the requested service from topLevelOpsResult
if serviceOperations, ok := (*topLevelOpsResult)[queryParams.ServiceName]; ok {
// Skip the first "overflow_operation" if present
startIdx := 0
if len(serviceOperations) > 0 && serviceOperations[0] == "overflow_operation" {
startIdx = 1
}
// Add each operation name to the entry point set
for i := startIdx; i < len(serviceOperations); i++ {
entryPointSet[serviceOperations[i]] = struct{}{}
}
}
// Step 3: Filter topOps based on entryPointSet (same as original)
var filtered []model.TopOperationsItem
for _, op := range *topOps {
if _, ok := entryPointSet[op.Name]; ok {
filtered = append(filtered, op)
}
}
return &filtered, nil
}
func (r *ClickHouseReader) GetTopOperations(ctx context.Context, queryParams *model.GetTopOperationsParams) (*[]model.TopOperationsItem, *model.ApiError) {
namedArgs := []interface{}{

View File

@ -540,6 +540,7 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) {
router.HandleFunc("/api/v1/services/list", am.ViewAccess(aH.getServicesList)).Methods(http.MethodGet)
router.HandleFunc("/api/v1/service/top_operations", am.ViewAccess(aH.getTopOperations)).Methods(http.MethodPost)
router.HandleFunc("/api/v1/service/top_level_operations", am.ViewAccess(aH.getServicesTopLevelOps)).Methods(http.MethodPost)
router.HandleFunc("/api/v1/service/entry_point_operations", am.ViewAccess(aH.getEntryPointOps)).Methods(http.MethodPost)
router.HandleFunc("/api/v1/traces/{traceId}", am.ViewAccess(aH.SearchTraces)).Methods(http.MethodGet)
router.HandleFunc("/api/v1/usage", am.ViewAccess(aH.getUsage)).Methods(http.MethodGet)
router.HandleFunc("/api/v1/dependency_graph", am.ViewAccess(aH.dependencyGraph)).Methods(http.MethodPost)
@ -1618,6 +1619,22 @@ func (aH *APIHandler) getTopOperations(w http.ResponseWriter, r *http.Request) {
}
func (aH *APIHandler) getEntryPointOps(w http.ResponseWriter, r *http.Request) {
query, err := parseGetTopOperationsRequest(r)
if err != nil {
render.Error(w, err)
return
}
result, apiErr := aH.reader.GetEntryPointOperations(r.Context(), query)
if apiErr != nil {
render.Error(w, apiErr)
return
}
render.Success(w, http.StatusOK, result)
}
func (aH *APIHandler) getUsage(w http.ResponseWriter, r *http.Request) {
query, err := parseGetUsageRequest(r)

View File

@ -17,6 +17,7 @@ type Reader interface {
GetInstantQueryMetricsResult(ctx context.Context, query *model.InstantQueryMetricsParams) (*promql.Result, *stats.QueryStats, *model.ApiError)
GetQueryRangeResult(ctx context.Context, query *model.QueryRangeParams) (*promql.Result, *stats.QueryStats, *model.ApiError)
GetTopLevelOperations(ctx context.Context, start, end time.Time, services []string) (*map[string][]string, *model.ApiError)
GetEntryPointOperations(ctx context.Context, query *model.GetTopOperationsParams) (*[]model.TopOperationsItem, error)
GetServices(ctx context.Context, query *model.GetServicesParams) (*[]model.ServiceItem, *model.ApiError)
GetTopOperations(ctx context.Context, query *model.GetTopOperationsParams) (*[]model.TopOperationsItem, *model.ApiError)
GetUsage(ctx context.Context, query *model.GetUsageParams) (*[]model.UsageItem, error)