Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: metrics query range v3 #2265

Merged
merged 49 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
db23108
chore: add payload types for autocomplete requests
srikanthccv Feb 14, 2023
5a5960c
chore: update the query params file location and payload
srikanthccv Feb 15, 2023
6060d5f
chore: add query range v3 API request/response payload types
srikanthccv Feb 15, 2023
1c96b5c
feat: metric attribute autocomplete for the aggregation type
srikanthccv Feb 15, 2023
7cf2e86
feat: add attrs filters autocomplete endpoints
srikanthccv Feb 15, 2023
1bfcffb
feat: metrics query range v3
srikanthccv Feb 15, 2023
f299894
feat: ability to save and retrieve the explorer queries
srikanthccv Feb 16, 2023
22c388d
chore: add support for extra data
srikanthccv Feb 18, 2023
1f9f0ab
chore: update query_range
srikanthccv Feb 19, 2023
42ad8cc
chore: open access
srikanthccv Feb 20, 2023
3efd7bd
chore: fix conflicts
srikanthccv Mar 1, 2023
a36d37a
chore: fix conflicts
srikanthccv Mar 2, 2023
230d4de
chore: fix conflicts
srikanthccv Mar 2, 2023
080ad19
chore: fix conflicts
srikanthccv Mar 2, 2023
6ff50b8
chore: update the query for empty search text
srikanthccv Mar 2, 2023
d2f067a
chore: add constants for data type and key type
srikanthccv Mar 2, 2023
c769cb0
Merge branch 'issue-2239-api' into issue-2240
srikanthccv Mar 2, 2023
17e7341
chore: use constants
srikanthccv Mar 2, 2023
b45c8e1
chore: fix conflicts
srikanthccv Mar 2, 2023
0068e50
chore: add more validation and comments
srikanthccv Mar 3, 2023
960fe9c
chore: merge develop into issue-2240
srikanthccv Mar 3, 2023
c18f503
chore: update search query for values
srikanthccv Mar 5, 2023
9c990ca
chore: merge develop into issue-2236
srikanthccv Mar 5, 2023
688e200
chore: add validation
srikanthccv Mar 5, 2023
e6a0b73
chore: remove ID
srikanthccv Mar 5, 2023
a171ec0
chore: move the receiver methods
srikanthccv Mar 5, 2023
50377a4
chore: merge issue-2236 into issue-2240
srikanthccv Mar 5, 2023
42bf848
Merge branch 'issue-2240' into issue-2241
srikanthccv Mar 5, 2023
9f5d1fc
chore: update query range v3
srikanthccv Mar 6, 2023
64725fa
Merge branch 'develop' into issue-2240
srikanthccv Mar 7, 2023
e39753a
Merge branch 'develop' into issue-2240
srikanthccv Mar 7, 2023
0b836de
Merge branch 'develop' into issue-2240
srikanthccv Mar 9, 2023
9851f12
Merge branch 'issue-2240' into issue-2241
makeavish Mar 9, 2023
733304f
Merge branch 'develop' into issue-2241
srikanthccv Mar 10, 2023
c945791
Merge branch 'develop' of github.com:SigNoz/signoz into issue-2241
srikanthccv Mar 12, 2023
62be92b
chore: update v3
srikanthccv Mar 13, 2023
7e10f6b
Merge branch 'issue-2241' of github.com:SigNoz/signoz into issue-2241
srikanthccv Mar 13, 2023
6e8f013
chore: push tests
srikanthccv Mar 14, 2023
14c9836
Merge branch 'develop' into issue-2241
srikanthccv Mar 14, 2023
c2cf439
Merge branch 'issue-2241' of github.com:SigNoz/signoz into issue-2241
srikanthccv Mar 14, 2023
7c2cd99
Merge branch 'develop' into issue-2241
makeavish Mar 20, 2023
d5937aa
Merge branch 'develop' of github.com:SigNoz/signoz into issue-2241
srikanthccv Mar 21, 2023
431b5ae
chore: use attribute key structure
srikanthccv Mar 21, 2023
1deb2d2
Merge branch 'issue-2241' of github.com:SigNoz/signoz into issue-2241
srikanthccv Mar 21, 2023
0617c7c
Merge branch 'develop' of github.com:SigNoz/signoz into issue-2241
srikanthccv Mar 22, 2023
23a07b3
Merge branch 'develop' into issue-2241
srikanthccv Mar 23, 2023
6e6f2e2
fix: handle NaN
srikanthccv Mar 23, 2023
c6d8fcc
Merge branch 'issue-2241' of github.com:SigNoz/signoz into issue-2241
srikanthccv Mar 23, 2023
0cd332c
Merge branch 'develop' into issue-2241
srikanthccv Mar 23, 2023
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
Prev Previous commit
Next Next commit
feat: metric attribute autocomplete for the aggregation type
  • Loading branch information
srikanthccv committed Feb 15, 2023
commit 1c96b5cb5902a4232f21f7fd5bd4bea158ce1696
1 change: 1 addition & 0 deletions ee/query-service/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ func (s *Server) createPublicServer(apiHandler *api.APIHandler) (*http.Server, e
apiHandler.RegisterRoutes(r)
apiHandler.RegisterMetricsRoutes(r)
apiHandler.RegisterLogsRoutes(r)
apiHandler.RegisterQueryRangeV3Routes(r)

c := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
Expand Down
36 changes: 36 additions & 0 deletions pkg/query-service/app/clickhouseReader/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
am "go.signoz.io/signoz/pkg/query-service/integrations/alertManager"
"go.signoz.io/signoz/pkg/query-service/interfaces"
"go.signoz.io/signoz/pkg/query-service/model"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
"go.signoz.io/signoz/pkg/query-service/telemetry"
"go.signoz.io/signoz/pkg/query-service/utils"
"go.uber.org/zap"
Expand Down Expand Up @@ -3640,3 +3641,38 @@ func (r *ClickHouseReader) QueryDashboardVars(ctx context.Context, query string)
}
return &result, nil
}

func (r *ClickHouseReader) GetMetricAggregateAttributes(ctx context.Context, req *v3.AggregateAttributeRequest) (*v3.AggregateAttributeResponse, error) {

var query string
var err error
var rows driver.Rows
var response v3.AggregateAttributeResponse

query = fmt.Sprintf("SELECT DISTINCT(metric_name) from %s.%s WHERE metric_name ILIKE $1", signozMetricDBName, signozTSTableName)
if req.Limit != 0 {
query = query + fmt.Sprintf(" LIMIT %d;", req.Limit)
}
rows, err = r.db.Query(ctx, query, fmt.Sprintf("%%%s%%", req.SearchText))

if err != nil {
zap.S().Error(err)
return nil, fmt.Errorf("error while executing query: %s", err.Error())
}
defer rows.Close()

var metricName string
for rows.Next() {
if err := rows.Scan(&metricName); err != nil {
return nil, fmt.Errorf("error while scanning rows: %s", err.Error())
}
key := v3.AttributeKey{
Key: metricName,
DataType: "STRING",
Type: "ATTRIBUTE",
}
response.AttributeKeys = append(response.AttributeKeys, key)
}

return &response, nil
}
35 changes: 35 additions & 0 deletions pkg/query-service/app/http_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"go.signoz.io/signoz/pkg/query-service/app/parser"
"go.signoz.io/signoz/pkg/query-service/auth"
"go.signoz.io/signoz/pkg/query-service/constants"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
querytemplate "go.signoz.io/signoz/pkg/query-service/utils/queryTemplate"

"go.signoz.io/signoz/pkg/query-service/dao"
Expand Down Expand Up @@ -219,6 +220,11 @@ func (aH *APIHandler) RegisterMetricsRoutes(router *mux.Router) {
subRouter.HandleFunc("/autocomplete/tagValue", ViewAccess(aH.metricAutocompleteTagValue)).Methods(http.MethodGet)
}

func (aH *APIHandler) RegisterQueryRangeV3Routes(router *mux.Router) {
subRouter := router.PathPrefix("/api/v3").Subrouter()
subRouter.HandleFunc("/autocomplete/aggregate_attributes", OpenAccess(aH.autocompleteAggregateAttributes)).Methods(http.MethodGet)
}

func (aH *APIHandler) Respond(w http.ResponseWriter, data interface{}) {
writeHttpResponse(w, data)
}
Expand Down Expand Up @@ -2291,3 +2297,32 @@ func (aH *APIHandler) logAggregate(w http.ResponseWriter, r *http.Request) {
}
aH.WriteJSON(w, r, res)
}

func (aH *APIHandler) autocompleteAggregateAttributes(w http.ResponseWriter, r *http.Request) {
var response *v3.AggregateAttributeResponse
req, err := parseAggregateAttributeRequest(r)

if err != nil {
RespondError(w, &model.ApiError{Typ: model.ErrorBadData, Err: err}, nil)
return
}

switch req.DataSource {
case v3.DataSourceMetrics:
response, err = aH.reader.GetMetricAggregateAttributes(r.Context(), req)
case v3.DataSourceLogs:
// TODO: implement
case v3.DataSourceTraces:
// TODO: implement
default:
RespondError(w, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("invalid data source")}, nil)
return
}

if err != nil {
RespondError(w, &model.ApiError{Typ: model.ErrorBadData, Err: err}, nil)
return
}

aH.Respond(w, response)
}
36 changes: 33 additions & 3 deletions pkg/query-service/app/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"go.signoz.io/signoz/pkg/query-service/auth"
"go.signoz.io/signoz/pkg/query-service/constants"
"go.signoz.io/signoz/pkg/query-service/model"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
)

var allowedFunctions = []string{"count", "ratePerSec", "sum", "avg", "min", "max", "p50", "p90", "p95", "p99"}
Expand Down Expand Up @@ -412,11 +413,11 @@ func extractTagKeys(tags []model.TagQueryParam) ([]model.TagQueryParam, error) {
tag.Key = customStr[0]
}
if tag.Operator == model.ExistsOperator || tag.Operator == model.NotExistsOperator {
if customStr[1] == string(model.TagTypeString) + ")" {
if customStr[1] == string(model.TagTypeString)+")" {
tag.StringValues = []string{" "}
} else if customStr[1] ==string(model.TagTypeBool) + ")" {
} else if customStr[1] == string(model.TagTypeBool)+")" {
tag.BoolValues = []bool{true}
} else if customStr[1] == string(model.TagTypeNumber) + ")" {
} else if customStr[1] == string(model.TagTypeNumber)+")" {
tag.NumberValues = []float64{0}
} else {
return nil, fmt.Errorf("TagKey param is not valid in query")
Expand Down Expand Up @@ -811,3 +812,32 @@ func parseFilterSet(r *http.Request) (*model.FilterSet, error) {
}
return &filterSet, nil
}

func parseAggregateAttributeRequest(r *http.Request) (*v3.AggregateAttributeRequest, error) {
var req v3.AggregateAttributeRequest

aggregateOperator := v3.AggregateOperator(r.URL.Query().Get("aggregateOperator"))
dataSource := v3.DataSource(r.URL.Query().Get("dataSource"))
aggregateAttribute := r.URL.Query().Get("searchText")

limit, err := strconv.Atoi(r.URL.Query().Get("limit"))
if err != nil {
limit = 50
}

if err := aggregateOperator.Validate(); err != nil {
return nil, err
}

if err := dataSource.Validate(); err != nil {
return nil, err
}

req = v3.AggregateAttributeRequest{
Operator: aggregateOperator,
SearchText: aggregateAttribute,
Limit: limit,
DataSource: dataSource,
}
return &req, nil
}
91 changes: 90 additions & 1 deletion pkg/query-service/app/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ package app
import (
"bytes"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/smartystreets/assertions/should"

. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
"go.signoz.io/signoz/pkg/query-service/app/metrics"
"go.signoz.io/signoz/pkg/query-service/model"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
)

func TestParseFilterSingleFilter(t *testing.T) {
Expand Down Expand Up @@ -58,3 +61,89 @@ func TestParseFilterNotSupportedOp(t *testing.T) {
So(err, should.BeError, "unsupported operation")
})
}

func TestParseAggregateAttrReques(t *testing.T) {
reqCases := []struct {
desc string
queryString string
expectedOperator v3.AggregateOperator
expectedDataSource v3.DataSource
expectedLimit int
expectedSearchText string
expectErr bool
errMsg string
}{
{
desc: "valid operator and data source",
queryString: "aggregateOperator=sum&dataSource=metrics&searchText=abc",
expectedOperator: v3.AggregateOperatorSum,
expectedDataSource: v3.DataSourceMetrics,
expectedLimit: 50,
expectedSearchText: "abc",
},
{
desc: "different valid operator and data source as logs",
queryString: "aggregateOperator=avg&dataSource=logs&searchText=abc",
expectedOperator: v3.AggregateOperatorAvg,
expectedDataSource: v3.DataSourceLogs,
expectedLimit: 50,
expectedSearchText: "abc",
},
{
desc: "different valid operator and with default search text and limit",
queryString: "aggregateOperator=avg&dataSource=metrics",
expectedOperator: v3.AggregateOperatorAvg,
expectedDataSource: v3.DataSourceMetrics,
expectedLimit: 50,
expectedSearchText: "",
},
{
desc: "valid operator and data source with limit",
queryString: "aggregateOperator=avg&dataSource=traces&limit=10",
expectedOperator: v3.AggregateOperatorAvg,
expectedDataSource: v3.DataSourceTraces,
expectedLimit: 10,
expectedSearchText: "",
},
{
desc: "invalid operator",
queryString: "aggregateOperator=avg1&dataSource=traces&limit=10",
expectErr: true,
errMsg: "invalid operator",
},
{
desc: "invalid data source",
queryString: "aggregateOperator=avg&dataSource=traces1&limit=10",
expectErr: true,
errMsg: "invalid data source",
},
{
desc: "invalid limit",
queryString: "aggregateOperator=avg&dataSource=traces&limit=abc",
expectedOperator: v3.AggregateOperatorAvg,
expectedDataSource: v3.DataSourceTraces,
expectedLimit: 50,
},
}

for _, reqCase := range reqCases {
r := httptest.NewRequest("GET", "/api/v3/autocomplete/aggregate_attributes?"+reqCase.queryString, nil)
aggregateAttrRequest, err := parseAggregateAttributeRequest(r)
if reqCase.expectErr {
if err == nil {
t.Errorf("expected error: %s", reqCase.errMsg)
}
if !strings.Contains(err.Error(), reqCase.errMsg) {
t.Errorf("expected error to contain: %s, got: %s", reqCase.errMsg, err.Error())
}
continue
}
if err != nil {
t.Errorf("unexpected error: %v", err)
}
assert.Equal(t, reqCase.expectedOperator, aggregateAttrRequest.Operator)
assert.Equal(t, reqCase.expectedDataSource, aggregateAttrRequest.DataSource)
assert.Equal(t, reqCase.expectedLimit, aggregateAttrRequest.Limit)
assert.Equal(t, reqCase.expectedSearchText, aggregateAttrRequest.SearchText)
}
}
1 change: 1 addition & 0 deletions pkg/query-service/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ func (s *Server) createPublicServer(api *APIHandler) (*http.Server, error) {
api.RegisterRoutes(r)
api.RegisterMetricsRoutes(r)
api.RegisterLogsRoutes(r)
api.RegisterQueryRangeV3Routes(r)

c := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
Expand Down
2 changes: 2 additions & 0 deletions pkg/query-service/interfaces/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/prometheus/prometheus/util/stats"
am "go.signoz.io/signoz/pkg/query-service/integrations/alertManager"
"go.signoz.io/signoz/pkg/query-service/model"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
)

type Reader interface {
Expand Down Expand Up @@ -56,6 +57,7 @@ type Reader interface {
GetMetricAutocompleteTagValue(ctx context.Context, params *model.MetricAutocompleteTagParams) (*[]string, *model.ApiError)
GetMetricResult(ctx context.Context, query string) ([]*model.Series, error)
GetMetricResultEE(ctx context.Context, query string) ([]*model.Series, string, error)
GetMetricAggregateAttributes(ctx context.Context, req *v3.AggregateAttributeRequest) (*v3.AggregateAttributeResponse, error)

GetTotalSpans(ctx context.Context) (uint64, error)
GetSpansInLastHeartBeatInterval(ctx context.Context) (uint64, error)
Expand Down
Loading