New Trace Filter Page API changes (Backend) (#646)

* build: integrate sql migrations for clickhouse

* feat: support error/exception attributes for trace

* chore: fixing dependencies for docker go client libs

* feat: get trace filter api checkpoint

* chore: fixing dependencies for go-migrate

* feat: add new columns

* feat: move mirgate run from docker to code

* fix: migration file 404 issue

* feat: getSpanFilter API

* fix: migrate version naming bug

* chore: change url param format to array

* feat: add getTagFilter API

* feat: add getFilteredSpans API

* fix: using OFFSET in sqlx driver

* feat: aggregates API on getFilteredSpan, use IN and NOT IN for tag filtering

* feat: add more function support to span aggregate API

* fix: null component edge case

* feat: groupBy support for filteredSpanAggregate

* feat: add function param to span aggregate API

* feat: add support to return totalSpans in getFilteredSpans API

* fix: don't return null string as keys in span filters

* chore: remove SQL migrations(moved to otel collector)

* fix: null string issue in aggregate API

* Merge main

* fix: trace API db query param

* fix: signoz sql db path

* fix: case when both error and ok status are selected

Co-authored-by: Ankit Nayan <ankit@signoz.io>
This commit is contained in:
Vishal Sharma 2022-01-26 20:41:59 +05:30 committed by GitHub
parent dcb17fb33a
commit 0ab91707e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1689 additions and 34 deletions

View File

@ -11,7 +11,6 @@ services:
- 8123:8123 - 8123:8123
volumes: volumes:
- ./clickhouse-config.xml:/etc/clickhouse-server/config.xml - ./clickhouse-config.xml:/etc/clickhouse-server/config.xml
- ./docker-entrypoint-initdb.d/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql
- ./data/clickhouse/:/var/lib/clickhouse/ - ./data/clickhouse/:/var/lib/clickhouse/
healthcheck: healthcheck:

View File

@ -1,31 +0,0 @@
CREATE TABLE IF NOT EXISTS signoz_index (
timestamp DateTime64(9) CODEC(Delta, ZSTD(1)),
traceID String CODEC(ZSTD(1)),
spanID String CODEC(ZSTD(1)),
parentSpanID String CODEC(ZSTD(1)),
serviceName LowCardinality(String) CODEC(ZSTD(1)),
name LowCardinality(String) CODEC(ZSTD(1)),
kind Int32 CODEC(ZSTD(1)),
durationNano UInt64 CODEC(ZSTD(1)),
tags Array(String) CODEC(ZSTD(1)),
tagsKeys Array(String) CODEC(ZSTD(1)),
tagsValues Array(String) CODEC(ZSTD(1)),
statusCode Int64 CODEC(ZSTD(1)),
references String CODEC(ZSTD(1)),
externalHttpMethod Nullable(String) CODEC(ZSTD(1)),
externalHttpUrl Nullable(String) CODEC(ZSTD(1)),
component Nullable(String) CODEC(ZSTD(1)),
dbSystem Nullable(String) CODEC(ZSTD(1)),
dbName Nullable(String) CODEC(ZSTD(1)),
dbOperation Nullable(String) CODEC(ZSTD(1)),
peerService Nullable(String) CODEC(ZSTD(1)),
INDEX idx_traceID traceID TYPE bloom_filter GRANULARITY 4,
INDEX idx_service serviceName TYPE bloom_filter GRANULARITY 4,
INDEX idx_name name TYPE bloom_filter GRANULARITY 4,
INDEX idx_kind kind TYPE minmax GRANULARITY 4,
INDEX idx_tagsKeys tagsKeys TYPE bloom_filter(0.01) GRANULARITY 64,
INDEX idx_tagsValues tagsValues TYPE bloom_filter(0.01) GRANULARITY 64,
INDEX idx_duration durationNano TYPE minmax GRANULARITY 1
) ENGINE MergeTree()
PARTITION BY toDate(timestamp)
ORDER BY (serviceName, -toUnixTimestamp(timestamp))

File diff suppressed because it is too large Load Diff

View File

@ -165,6 +165,22 @@ func (druid *DruidReader) GetTTL(_ context.Context, _ *model.GetTTLParams) (*mod
return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support setting ttl configuration")} return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support setting ttl configuration")}
} }
func (druid *DruidReader) GetSpanFilters(_ context.Context, _ *model.SpanFilterParams) (*model.SpanFiltersResponse, *model.ApiError) {
return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support getting spanfilters")}
}
func (druid *DruidReader) GetTagFilters(_ context.Context, _ *model.TagFilterParams) (*[]model.TagFilters, *model.ApiError) {
return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support getting tagFilters")}
}
func (druid *DruidReader) GetFilteredSpans(_ context.Context, _ *model.GetFilteredSpansParams) (*model.GetFilterSpansResponse, *model.ApiError) {
return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support getting FilteredSpans")}
}
func (druid *DruidReader) GetFilteredSpansAggregates(_ context.Context, _ *model.GetFilteredSpanAggregatesParams) (*model.GetFilteredSpansAggregatesResponse, *model.ApiError) {
return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support getting FilteredSpans")}
}
func (druid *DruidReader) GetErrors(_ context.Context, _ *model.GetErrorsParams) (*[]model.Error, *model.ApiError) { func (druid *DruidReader) GetErrors(_ context.Context, _ *model.GetErrorsParams) (*[]model.Error, *model.ApiError) {
return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support get error API")} return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support get error API")}
} }

View File

@ -203,6 +203,10 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router) {
router.HandleFunc("/api/v1/serviceMapDependencies", aH.serviceMapDependencies).Methods(http.MethodGet) router.HandleFunc("/api/v1/serviceMapDependencies", aH.serviceMapDependencies).Methods(http.MethodGet)
router.HandleFunc("/api/v1/settings/ttl", aH.setTTL).Methods(http.MethodPost) router.HandleFunc("/api/v1/settings/ttl", aH.setTTL).Methods(http.MethodPost)
router.HandleFunc("/api/v1/settings/ttl", aH.getTTL).Methods(http.MethodGet) router.HandleFunc("/api/v1/settings/ttl", aH.getTTL).Methods(http.MethodGet)
router.HandleFunc("/api/v1/getSpanFilters", aH.getSpanFilters).Methods(http.MethodGet)
router.HandleFunc("/api/v1/getTagFilters", aH.getTagFilters).Methods(http.MethodGet)
router.HandleFunc("/api/v1/getFilteredSpans", aH.getFilteredSpans).Methods(http.MethodGet)
router.HandleFunc("/api/v1/getFilteredSpans/aggregates", aH.getFilteredSpanAggregates).Methods(http.MethodGet)
router.HandleFunc("/api/v1/errors", aH.getErrors).Methods(http.MethodGet) router.HandleFunc("/api/v1/errors", aH.getErrors).Methods(http.MethodGet)
router.HandleFunc("/api/v1/errorWithId", aH.getErrorForId).Methods(http.MethodGet) router.HandleFunc("/api/v1/errorWithId", aH.getErrorForId).Methods(http.MethodGet)
router.HandleFunc("/api/v1/errorWithType", aH.getErrorForType).Methods(http.MethodGet) router.HandleFunc("/api/v1/errorWithType", aH.getErrorForType).Methods(http.MethodGet)
@ -965,6 +969,70 @@ func (aH *APIHandler) searchSpans(w http.ResponseWriter, r *http.Request) {
aH.writeJSON(w, r, result) aH.writeJSON(w, r, result)
} }
func (aH *APIHandler) getSpanFilters(w http.ResponseWriter, r *http.Request) {
query, err := parseSpanFilterRequest(r)
if aH.handleError(w, err, http.StatusBadRequest) {
return
}
result, apiErr := (*aH.reader).GetSpanFilters(context.Background(), query)
if apiErr != nil && aH.handleError(w, apiErr.Err, http.StatusInternalServerError) {
return
}
aH.writeJSON(w, r, result)
}
func (aH *APIHandler) getFilteredSpans(w http.ResponseWriter, r *http.Request) {
query, err := parseFilteredSpansRequest(r)
if aH.handleError(w, err, http.StatusBadRequest) {
return
}
result, apiErr := (*aH.reader).GetFilteredSpans(context.Background(), query)
if apiErr != nil && aH.handleError(w, apiErr.Err, http.StatusInternalServerError) {
return
}
aH.writeJSON(w, r, result)
}
func (aH *APIHandler) getFilteredSpanAggregates(w http.ResponseWriter, r *http.Request) {
query, err := parseFilteredSpanAggregatesRequest(r)
if aH.handleError(w, err, http.StatusBadRequest) {
return
}
result, apiErr := (*aH.reader).GetFilteredSpansAggregates(context.Background(), query)
if apiErr != nil && aH.handleError(w, apiErr.Err, http.StatusInternalServerError) {
return
}
aH.writeJSON(w, r, result)
}
func (aH *APIHandler) getTagFilters(w http.ResponseWriter, r *http.Request) {
query, err := parseTagFilterRequest(r)
if aH.handleError(w, err, http.StatusBadRequest) {
return
}
result, apiErr := (*aH.reader).GetTagFilters(context.Background(), query)
if apiErr != nil && aH.handleError(w, apiErr.Err, http.StatusInternalServerError) {
return
}
aH.writeJSON(w, r, result)
}
func (aH *APIHandler) setTTL(w http.ResponseWriter, r *http.Request) { func (aH *APIHandler) setTTL(w http.ResponseWriter, r *http.Request) {
ttlParams, err := parseDuration(r) ttlParams, err := parseDuration(r)
if aH.handleError(w, err, http.StatusBadRequest) { if aH.handleError(w, err, http.StatusBadRequest) {

View File

@ -37,6 +37,11 @@ type Reader interface {
GetServicesList(ctx context.Context) (*[]string, error) GetServicesList(ctx context.Context) (*[]string, error)
GetServiceMapDependencies(ctx context.Context, query *model.GetServicesParams) (*[]model.ServiceMapDependencyResponseItem, error) GetServiceMapDependencies(ctx context.Context, query *model.GetServicesParams) (*[]model.ServiceMapDependencyResponseItem, error)
GetTTL(ctx context.Context, ttlParams *model.GetTTLParams) (*model.GetTTLResponseItem, *model.ApiError) GetTTL(ctx context.Context, ttlParams *model.GetTTLParams) (*model.GetTTLResponseItem, *model.ApiError)
GetSpanFilters(ctx context.Context, query *model.SpanFilterParams) (*model.SpanFiltersResponse, *model.ApiError)
GetTagFilters(ctx context.Context, query *model.TagFilterParams) (*[]model.TagFilters, *model.ApiError)
GetFilteredSpans(ctx context.Context, query *model.GetFilteredSpansParams) (*model.GetFilterSpansResponse, *model.ApiError)
GetFilteredSpansAggregates(ctx context.Context, query *model.GetFilteredSpanAggregatesParams) (*model.GetFilteredSpansAggregatesResponse, *model.ApiError)
GetErrors(ctx context.Context, params *model.GetErrorsParams) (*[]model.Error, *model.ApiError) GetErrors(ctx context.Context, params *model.GetErrorsParams) (*[]model.Error, *model.ApiError)
GetErrorForId(ctx context.Context, params *model.GetErrorParams) (*model.ErrorWithSpan, *model.ApiError) GetErrorForId(ctx context.Context, params *model.GetErrorParams) (*model.ErrorWithSpan, *model.ApiError)
GetErrorForType(ctx context.Context, params *model.GetErrorParams) (*model.ErrorWithSpan, *model.ApiError) GetErrorForType(ctx context.Context, params *model.GetErrorParams) (*model.ErrorWithSpan, *model.ApiError)

View File

@ -19,9 +19,11 @@ import (
var allowedDimesions = []string{"calls", "duration"} var allowedDimesions = []string{"calls", "duration"}
var allowedFunctions = []string{"count", "ratePerSec", "sum", "avg", "min", "max", "p50", "p90", "p95", "p99"}
var allowedAggregations = map[string][]string{ var allowedAggregations = map[string][]string{
"calls": {"count", "rate_per_sec"}, "calls": {"count", "rate_per_sec"},
"duration": {"avg", "p50", "p95", "p99"}, "duration": {"avg", "p50", "p95", "p90", "p99", "min", "max", "sum"},
} }
func parseUser(r *http.Request) (*model.User, error) { func parseUser(r *http.Request) (*model.User, error) {
@ -480,6 +482,284 @@ func parseSpanSearchRequest(r *http.Request) (*model.SpanSearchParams, error) {
return params, nil return params, nil
} }
func parseSpanFilterRequest(r *http.Request) (*model.SpanFilterParams, error) {
startTime, err := parseTime("start", r)
if err != nil {
return nil, err
}
endTime, err := parseTimeMinusBuffer("end", r)
if err != nil {
return nil, err
}
params := &model.SpanFilterParams{
Start: startTime,
End: endTime,
ServiceName: []string{},
HttpRoute: []string{},
HttpCode: []string{},
HttpUrl: []string{},
HttpHost: []string{},
HttpMethod: []string{},
Component: []string{},
Status: []string{},
Operation: []string{},
GetFilters: []string{},
}
params.ServiceName = fetchArrayValues("serviceName", r)
params.Status = fetchArrayValues("status", r)
params.Operation = fetchArrayValues("operation", r)
params.HttpCode = fetchArrayValues("httpCode", r)
params.HttpUrl = fetchArrayValues("httpUrl", r)
params.HttpHost = fetchArrayValues("httpHost", r)
params.HttpRoute = fetchArrayValues("httpRoute", r)
params.HttpMethod = fetchArrayValues("httpMethod", r)
params.Component = fetchArrayValues("component", r)
params.GetFilters = fetchArrayValues("getFilters", r)
minDuration, err := parseTimestamp("minDuration", r)
if err == nil {
params.MinDuration = *minDuration
}
maxDuration, err := parseTimestamp("maxDuration", r)
if err == nil {
params.MaxDuration = *maxDuration
}
return params, nil
}
func parseFilteredSpansRequest(r *http.Request) (*model.GetFilteredSpansParams, error) {
startTime, err := parseTime("start", r)
if err != nil {
return nil, err
}
endTime, err := parseTimeMinusBuffer("end", r)
if err != nil {
return nil, err
}
params := &model.GetFilteredSpansParams{
Start: startTime,
End: endTime,
ServiceName: []string{},
HttpRoute: []string{},
HttpCode: []string{},
HttpUrl: []string{},
HttpHost: []string{},
HttpMethod: []string{},
Component: []string{},
Status: []string{},
Operation: []string{},
Limit: 100,
Order: "descending",
}
params.ServiceName = fetchArrayValues("serviceName", r)
params.Status = fetchArrayValues("status", r)
params.Operation = fetchArrayValues("operation", r)
params.HttpCode = fetchArrayValues("httpCode", r)
params.HttpUrl = fetchArrayValues("httpUrl", r)
params.HttpHost = fetchArrayValues("httpHost", r)
params.HttpRoute = fetchArrayValues("httpRoute", r)
params.HttpMethod = fetchArrayValues("httpMethod", r)
params.Component = fetchArrayValues("component", r)
limitStr := r.URL.Query().Get("limit")
if len(limitStr) != 0 {
limit, err := strconv.ParseInt(limitStr, 10, 64)
if err != nil {
return nil, errors.New("Limit param is not in correct format")
}
params.Limit = limit
} else {
params.Limit = 100
}
offsetStr := r.URL.Query().Get("offset")
if len(offsetStr) != 0 {
offset, err := strconv.ParseInt(offsetStr, 10, 64)
if err != nil {
return nil, errors.New("Offset param is not in correct format")
}
params.Offset = offset
}
tags, err := parseTagsV2("tags", r)
if err != nil {
return nil, err
}
if len(*tags) != 0 {
params.Tags = *tags
}
minDuration, err := parseTimestamp("minDuration", r)
if err == nil {
params.MinDuration = *minDuration
}
maxDuration, err := parseTimestamp("maxDuration", r)
if err == nil {
params.MaxDuration = *maxDuration
}
kind := r.URL.Query().Get("kind")
if len(kind) != 0 {
params.Kind = kind
}
return params, nil
}
func parseFilteredSpanAggregatesRequest(r *http.Request) (*model.GetFilteredSpanAggregatesParams, error) {
startTime, err := parseTime("start", r)
if err != nil {
return nil, err
}
endTime, err := parseTimeMinusBuffer("end", r)
if err != nil {
return nil, err
}
stepStr := r.URL.Query().Get("step")
if len(stepStr) == 0 {
return nil, errors.New("step param missing in query")
}
stepInt, err := strconv.Atoi(stepStr)
if err != nil {
return nil, errors.New("step param is not in correct format")
}
function := r.URL.Query().Get("function")
if len(function) == 0 {
return nil, errors.New("function param missing in query")
} else {
if !DoesExistInSlice(function, allowedFunctions) {
return nil, errors.New(fmt.Sprintf("given function: %s is not allowed in query", function))
}
}
var dimension, aggregationOption string
switch function {
case "count":
dimension = "calls"
aggregationOption = "count"
case "ratePerSec":
dimension = "calls"
aggregationOption = "rate_per_sec"
case "avg":
dimension = "duration"
aggregationOption = "avg"
case "sum":
dimension = "duration"
aggregationOption = "sum"
case "p50":
dimension = "duration"
aggregationOption = "p50"
case "p90":
dimension = "duration"
aggregationOption = "p90"
case "p95":
dimension = "duration"
aggregationOption = "p95"
case "p99":
dimension = "duration"
aggregationOption = "p99"
case "min":
dimension = "duration"
aggregationOption = "min"
case "max":
dimension = "duration"
aggregationOption = "max"
}
params := &model.GetFilteredSpanAggregatesParams{
Start: startTime,
End: endTime,
ServiceName: []string{},
HttpRoute: []string{},
HttpCode: []string{},
HttpUrl: []string{},
HttpHost: []string{},
HttpMethod: []string{},
Component: []string{},
Status: []string{},
Operation: []string{},
StepSeconds: stepInt,
Dimension: dimension,
AggregationOption: aggregationOption,
}
params.ServiceName = fetchArrayValues("serviceName", r)
params.Status = fetchArrayValues("status", r)
params.Operation = fetchArrayValues("operation", r)
params.HttpCode = fetchArrayValues("httpCode", r)
params.HttpUrl = fetchArrayValues("httpUrl", r)
params.HttpHost = fetchArrayValues("httpHost", r)
params.HttpRoute = fetchArrayValues("httpRoute", r)
params.HttpMethod = fetchArrayValues("httpMethod", r)
params.Component = fetchArrayValues("component", r)
tags, err := parseTagsV2("tags", r)
if err != nil {
return nil, err
}
if len(*tags) != 0 {
params.Tags = *tags
}
minDuration, err := parseTimestamp("minDuration", r)
if err == nil {
params.MinDuration = *minDuration
}
maxDuration, err := parseTimestamp("maxDuration", r)
if err == nil {
params.MaxDuration = *maxDuration
}
kind := r.URL.Query().Get("kind")
if len(kind) != 0 {
params.Kind = kind
}
groupBy := r.URL.Query().Get("groupBy")
if len(groupBy) != 0 {
params.GroupBy = groupBy
}
return params, nil
}
func parseErrorRequest(r *http.Request) (*model.GetErrorParams, error) { func parseErrorRequest(r *http.Request) (*model.GetErrorParams, error) {
params := &model.GetErrorParams{} params := &model.GetErrorParams{}
@ -502,6 +782,60 @@ func parseErrorRequest(r *http.Request) (*model.GetErrorParams, error) {
return params, nil return params, nil
} }
func parseTagFilterRequest(r *http.Request) (*model.TagFilterParams, error) {
startTime, err := parseTime("start", r)
if err != nil {
return nil, err
}
endTime, err := parseTimeMinusBuffer("end", r)
if err != nil {
return nil, err
}
params := &model.TagFilterParams{
Start: startTime,
End: endTime,
ServiceName: []string{},
HttpRoute: []string{},
HttpCode: []string{},
HttpUrl: []string{},
HttpHost: []string{},
HttpMethod: []string{},
Component: []string{},
Status: []string{},
Operation: []string{},
}
params.ServiceName = fetchArrayValues("serviceName", r)
params.Status = fetchArrayValues("status", r)
params.Operation = fetchArrayValues("operation", r)
params.HttpCode = fetchArrayValues("httpCode", r)
params.HttpUrl = fetchArrayValues("httpUrl", r)
params.HttpHost = fetchArrayValues("httpHost", r)
params.HttpRoute = fetchArrayValues("httpRoute", r)
params.HttpMethod = fetchArrayValues("httpMethod", r)
params.Component = fetchArrayValues("component", r)
minDuration, err := parseTimestamp("minDuration", r)
if err == nil {
params.MinDuration = *minDuration
}
maxDuration, err := parseTimestamp("maxDuration", r)
if err == nil {
params.MaxDuration = *maxDuration
}
return params, nil
}
func parseErrorsRequest(r *http.Request) (*model.GetErrorsParams, error) { func parseErrorsRequest(r *http.Request) (*model.GetErrorsParams, error) {
startTime, err := parseTime("start", r) startTime, err := parseTime("start", r)
@ -521,6 +855,19 @@ func parseErrorsRequest(r *http.Request) (*model.GetErrorsParams, error) {
return params, nil return params, nil
} }
func fetchArrayValues(param string, r *http.Request) []string {
valueStr := r.URL.Query().Get(param)
var values []string
if len(valueStr) == 0 {
return values
}
err := json.Unmarshal([]byte(valueStr), &values)
if err != nil {
zap.S().Error("Error in parsing service params", zap.Error(err))
}
return values
}
func parseTags(param string, r *http.Request) (*[]model.TagQuery, error) { func parseTags(param string, r *http.Request) (*[]model.TagQuery, error) {
tags := new([]model.TagQuery) tags := new([]model.TagQuery)
@ -539,6 +886,24 @@ func parseTags(param string, r *http.Request) (*[]model.TagQuery, error) {
return tags, nil return tags, nil
} }
func parseTagsV2(param string, r *http.Request) (*[]model.TagQueryV2, error) {
tags := new([]model.TagQueryV2)
tagsStr := r.URL.Query().Get(param)
if len(tagsStr) == 0 {
return tags, nil
}
err := json.Unmarshal([]byte(tagsStr), tags)
if err != nil {
zap.S().Error("Error in parsig tags", zap.Error(err))
return nil, fmt.Errorf("error in parsing %s ", param)
}
// zap.S().Info("Tags: ", *tags)
return tags, nil
}
func parseApplicationPercentileRequest(r *http.Request) (*model.ApplicationPercentileParams, error) { func parseApplicationPercentileRequest(r *http.Request) (*model.ApplicationPercentileParams, error) {
startTime, err := parseTime("start", r) startTime, err := parseTime("start", r)

View File

@ -78,6 +78,11 @@ type TagQuery struct {
Operator string Operator string
} }
type TagQueryV2 struct {
Key string
Values []string
Operator string
}
type SpanSearchAggregatesParams struct { type SpanSearchAggregatesParams struct {
ServiceName string ServiceName string
OperationName string OperationName string
@ -111,6 +116,82 @@ type SpanSearchParams struct {
Tags []TagQuery Tags []TagQuery
} }
type GetFilteredSpansParams struct {
ServiceName []string
Operation []string
Kind string
Status []string
HttpRoute []string
HttpCode []string
HttpUrl []string
HttpHost []string
HttpMethod []string
Component []string
Start *time.Time
End *time.Time
MinDuration string
MaxDuration string
Limit int64
Order string
Offset int64
Tags []TagQueryV2
}
type GetFilteredSpanAggregatesParams struct {
ServiceName []string
Operation []string
Kind string
Status []string
HttpRoute []string
HttpCode []string
HttpUrl []string
HttpHost []string
HttpMethod []string
Component []string
MinDuration string
MaxDuration string
Tags []TagQueryV2
Start *time.Time
End *time.Time
StepSeconds int
Dimension string
AggregationOption string
GroupBy string
Function string
}
type SpanFilterParams struct {
Status []string
ServiceName []string
HttpRoute []string
HttpCode []string
HttpUrl []string
HttpHost []string
HttpMethod []string
Component []string
Operation []string
GetFilters []string
MinDuration string
MaxDuration string
Start *time.Time
End *time.Time
}
type TagFilterParams struct {
Status []string
ServiceName []string
HttpRoute []string
HttpCode []string
HttpUrl []string
HttpHost []string
HttpMethod []string
Component []string
Operation []string
MinDuration string
MaxDuration string
Start *time.Time
End *time.Time
}
type TTLParams struct { type TTLParams struct {
Type string Type string
Duration string Duration string

View File

@ -1,6 +1,7 @@
package model package model
import ( import (
"database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strconv" "strconv"
@ -128,6 +129,22 @@ type SearchSpansResult struct {
Events [][]interface{} `json:"events"` Events [][]interface{} `json:"events"`
} }
type GetFilterSpansResponseItem struct {
Timestamp string `db:"timestamp" json:"timestamp"`
SpanID string `db:"spanID" json:"spanID"`
TraceID string `db:"traceID" json:"traceID"`
ServiceName string `db:"serviceName" json:"serviceName"`
Operation string `db:"name" json:"operation"`
DurationNano int64 `db:"durationNano" json:"durationNano"`
HttpCode string `db:"httpCode" json:"httpCode"`
HttpMethod string `db:"httpMethod" json:"httpMethod"`
}
type GetFilterSpansResponse struct {
Spans []GetFilterSpansResponseItem `json:"spans"`
TotalSpans int `json:"totalSpans"`
}
type TraceResult struct { type TraceResult struct {
Data []interface{} `json:"data" db:"data"` Data []interface{} `json:"data" db:"data"`
Total int `json:"total" db:"total"` Total int `json:"total" db:"total"`
@ -247,6 +264,9 @@ type TagItem struct {
TagCount int `json:"tagCount" db:"tagCount"` TagCount int `json:"tagCount" db:"tagCount"`
} }
type TagFilters struct {
TagKeys string `json:"tagKeys" db:"tagKeys"`
}
type ServiceMapDependencyResponseItem struct { type ServiceMapDependencyResponseItem struct {
Parent string `json:"parent,omitempty" db:"parent,omitempty"` Parent string `json:"parent,omitempty" db:"parent,omitempty"`
Child string `json:"child,omitempty" db:"child,omitempty"` Child string `json:"child,omitempty" db:"child,omitempty"`
@ -259,6 +279,21 @@ type SpanSearchAggregatesResponseItem struct {
Value float32 `json:"value,omitempty" db:"value"` Value float32 `json:"value,omitempty" db:"value"`
} }
type GetFilteredSpansAggregatesResponse struct {
Items map[int64]SpanAggregatesResponseItem `json:"items"`
}
type SpanAggregatesResponseItem struct {
Timestamp int64 `json:"timestamp,omitempty" `
Value float32 `json:"value,omitempty"`
GroupBy map[string]float32 `json:"groupBy,omitempty"`
}
type SpanAggregatesDBResponseItem struct {
Timestamp int64 `json:"timestamp,omitempty" db:"timestamp" `
Time string `json:"time,omitempty" db:"time"`
Value float32 `json:"value,omitempty" db:"value"`
GroupBy sql.NullString `json:"groupBy,omitempty" db:"groupBy"`
}
type SetTTLResponseItem struct { type SetTTLResponseItem struct {
Message string `json:"message"` Message string `json:"message"`
} }
@ -272,6 +307,71 @@ type GetTTLResponseItem struct {
TracesTime int `json:"traces_ttl_duration_hrs"` TracesTime int `json:"traces_ttl_duration_hrs"`
} }
type DBResponseMinMaxDuration struct {
MinDuration int `db:"min(durationNano)"`
MaxDuration int `db:"max(durationNano)"`
}
type DBResponseServiceName struct {
ServiceName string `db:"serviceName"`
Count int `db:"count"`
}
type DBResponseHttpCode struct {
HttpCode string `db:"httpCode"`
Count int `db:"count"`
}
type DBResponseHttpRoute struct {
HttpRoute string `db:"httpRoute"`
Count int `db:"count"`
}
type DBResponseHttpUrl struct {
HttpUrl string `db:"httpUrl"`
Count int `db:"count"`
}
type DBResponseHttpMethod struct {
HttpMethod string `db:"httpMethod"`
Count int `db:"count"`
}
type DBResponseHttpHost struct {
HttpHost string `db:"httpHost"`
Count int `db:"count"`
}
type DBResponseOperation struct {
Operation string `db:"name"`
Count int `db:"count"`
}
type DBResponseComponent struct {
Component sql.NullString `db:"component"`
Count int `db:"count"`
}
type DBResponseErrors struct {
NumErrors int `db:"numErrors"`
}
type DBResponseTotal struct {
NumTotal int `db:"numTotal"`
}
type SpanFiltersResponse struct {
ServiceName map[string]int `json:"serviceName"`
Status map[string]int `json:"status"`
Duration map[string]int `json:"duration"`
Operation map[string]int `json:"operation"`
HttpCode map[string]int `json:"httpCode"`
HttpUrl map[string]int `json:"httpUrl"`
HttpMethod map[string]int `json:"httpMethod"`
HttpRoute map[string]int `json:"httpRoute"`
HttpHost map[string]int `json:"httpHost"`
Component map[string]int `json:"component"`
}
type Error struct { type Error struct {
ExceptionType string `json:"exceptionType" db:"exceptionType"` ExceptionType string `json:"exceptionType" db:"exceptionType"`
ExceptionMsg string `json:"exceptionMessage" db:"exceptionMessage"` ExceptionMsg string `json:"exceptionMessage" db:"exceptionMessage"`