2021-01-03 18:15:44 +05:30
package app
import (
2021-05-22 19:51:56 +05:30
"context"
2021-01-03 18:15:44 +05:30
"encoding/json"
"fmt"
"net/http"
"github.com/gorilla/mux"
2021-09-02 13:18:47 +05:30
"github.com/jmoiron/sqlx"
2021-08-29 10:28:40 +05:30
jsoniter "github.com/json-iterator/go"
2021-09-02 13:18:47 +05:30
_ "github.com/mattn/go-sqlite3"
2021-01-09 19:10:34 +05:30
"github.com/posthog/posthog-go"
2021-08-29 10:28:40 +05:30
"github.com/prometheus/prometheus/promql"
2021-09-02 13:18:47 +05:30
"go.signoz.io/query-service/app/dashboards"
2021-08-29 10:28:40 +05:30
"go.signoz.io/query-service/model"
2021-01-03 18:15:44 +05:30
"go.uber.org/zap"
)
2021-08-29 10:28:40 +05:30
type status string
const (
statusSuccess status = "success"
statusError status = "error"
)
2021-01-03 18:15:44 +05:30
// NewRouter creates and configures a Gorilla Router.
func NewRouter ( ) * mux . Router {
return mux . NewRouter ( ) . UseEncodedPath ( )
}
// APIHandler implements the query service public API by registering routes at httpPrefix
type APIHandler struct {
// queryService *querysvc.QueryService
// queryParser queryParser
2021-01-09 19:10:34 +05:30
basePath string
apiPrefix string
2021-05-22 19:51:56 +05:30
reader * Reader
2021-01-09 19:10:34 +05:30
pc * posthog . Client
distinctId string
2021-09-02 13:18:47 +05:30
db * sqlx . DB
2021-08-29 10:28:40 +05:30
ready func ( http . HandlerFunc ) http . HandlerFunc
2021-01-03 18:15:44 +05:30
}
// NewAPIHandler returns an APIHandler
2021-09-02 13:18:47 +05:30
func NewAPIHandler ( reader * Reader , pc * posthog . Client , distinctId string ) ( * APIHandler , error ) {
2021-08-29 10:28:40 +05:30
2021-01-03 18:15:44 +05:30
aH := & APIHandler {
2021-05-22 19:51:56 +05:30
reader : reader ,
2021-01-09 19:10:34 +05:30
pc : pc ,
distinctId : distinctId ,
2021-01-03 18:15:44 +05:30
}
2021-08-29 10:28:40 +05:30
aH . ready = aH . testReady
2021-09-02 13:18:47 +05:30
2021-09-28 18:14:12 +05:30
err := dashboards . InitDB ( "/var/lib/signoz/signoz.db" )
2021-09-02 13:18:47 +05:30
if err != nil {
return nil , err
}
errReadingDashboards := dashboards . LoadDashboardFiles ( )
if errReadingDashboards != nil {
return nil , errReadingDashboards
}
return aH , nil
2021-01-03 18:15:44 +05:30
}
type structuredResponse struct {
Data interface { } ` json:"data" `
Total int ` json:"total" `
Limit int ` json:"limit" `
Offset int ` json:"offset" `
Errors [ ] structuredError ` json:"errors" `
}
type structuredError struct {
Code int ` json:"code,omitempty" `
Msg string ` json:"msg" `
// TraceID ui.TraceID `json:"traceID,omitempty"`
}
2021-08-29 10:28:40 +05:30
var corsHeaders = map [ string ] string {
"Access-Control-Allow-Headers" : "Accept, Authorization, Content-Type, Origin" ,
"Access-Control-Allow-Methods" : "GET, OPTIONS" ,
"Access-Control-Allow-Origin" : "*" ,
"Access-Control-Expose-Headers" : "Date" ,
}
// Enables cross-site script calls.
func setCORS ( w http . ResponseWriter ) {
for h , v := range corsHeaders {
w . Header ( ) . Set ( h , v )
}
}
type apiFunc func ( r * http . Request ) ( interface { } , * model . ApiError , func ( ) )
// Checks if server is ready, calls f if it is, returns 503 if it is not.
func ( aH * APIHandler ) testReady ( f http . HandlerFunc ) http . HandlerFunc {
return func ( w http . ResponseWriter , r * http . Request ) {
f ( w , r )
}
}
type response struct {
Status status ` json:"status" `
Data interface { } ` json:"data,omitempty" `
ErrorType model . ErrorType ` json:"errorType,omitempty" `
Error string ` json:"error,omitempty" `
}
func ( aH * APIHandler ) respondError ( w http . ResponseWriter , apiErr * model . ApiError , data interface { } ) {
json := jsoniter . ConfigCompatibleWithStandardLibrary
b , err := json . Marshal ( & response {
Status : statusError ,
ErrorType : apiErr . Typ ,
Error : apiErr . Err . Error ( ) ,
Data : data ,
} )
if err != nil {
zap . S ( ) . Error ( "msg" , "error marshalling json response" , "err" , err )
http . Error ( w , err . Error ( ) , http . StatusInternalServerError )
return
}
var code int
switch apiErr . Typ {
case model . ErrorBadData :
code = http . StatusBadRequest
case model . ErrorExec :
code = 422
case model . ErrorCanceled , model . ErrorTimeout :
code = http . StatusServiceUnavailable
case model . ErrorInternal :
code = http . StatusInternalServerError
case model . ErrorNotFound :
code = http . StatusNotFound
case model . ErrorNotImplemented :
code = http . StatusNotImplemented
default :
code = http . StatusInternalServerError
}
w . Header ( ) . Set ( "Content-Type" , "application/json" )
w . WriteHeader ( code )
if n , err := w . Write ( b ) ; err != nil {
zap . S ( ) . Error ( "msg" , "error writing response" , "bytesWritten" , n , "err" , err )
}
}
func ( aH * APIHandler ) respond ( w http . ResponseWriter , data interface { } ) {
json := jsoniter . ConfigCompatibleWithStandardLibrary
b , err := json . Marshal ( & response {
Status : statusSuccess ,
Data : data ,
} )
if err != nil {
zap . S ( ) . Error ( "msg" , "error marshalling json response" , "err" , err )
http . Error ( w , err . Error ( ) , http . StatusInternalServerError )
return
}
w . Header ( ) . Set ( "Content-Type" , "application/json" )
w . WriteHeader ( http . StatusOK )
if n , err := w . Write ( b ) ; err != nil {
zap . S ( ) . Error ( "msg" , "error writing response" , "bytesWritten" , n , "err" , err )
}
}
2021-01-03 18:15:44 +05:30
// RegisterRoutes registers routes for this handler on the given router
func ( aH * APIHandler ) RegisterRoutes ( router * mux . Router ) {
2021-08-29 10:28:40 +05:30
router . HandleFunc ( "/api/v1/query_range" , aH . queryRangeMetrics ) . Methods ( http . MethodGet )
router . HandleFunc ( "/api/v1/query" , aH . queryMetrics ) . Methods ( http . MethodGet )
2021-01-03 18:15:44 +05:30
2021-09-02 13:18:47 +05:30
router . HandleFunc ( "/api/v1/dashboards" , aH . getDashboards ) . Methods ( http . MethodGet )
router . HandleFunc ( "/api/v1/dashboards" , aH . createDashboards ) . Methods ( http . MethodPost )
router . HandleFunc ( "/api/v1/dashboards/{uuid}" , aH . getDashboard ) . Methods ( http . MethodGet )
router . HandleFunc ( "/api/v1/dashboards/{uuid}" , aH . updateDashboard ) . Methods ( http . MethodPut )
router . HandleFunc ( "/api/v1/dashboards/{uuid}" , aH . deleteDashboard ) . Methods ( http . MethodDelete )
2021-08-10 23:32:28 +05:30
router . HandleFunc ( "/api/v1/user" , aH . user ) . Methods ( http . MethodPost )
2021-05-27 12:52:34 +05:30
// router.HandleFunc("/api/v1/get_percentiles", aH.getApplicationPercentiles).Methods(http.MethodGet)
2021-01-03 18:15:44 +05:30
router . HandleFunc ( "/api/v1/services" , aH . getServices ) . Methods ( http . MethodGet )
2021-05-31 11:14:11 +05:30
router . HandleFunc ( "/api/v1/services/list" , aH . getServicesList ) . Methods ( http . MethodGet )
2021-05-29 16:32:11 +05:30
router . HandleFunc ( "/api/v1/service/overview" , aH . getServiceOverview ) . Methods ( http . MethodGet )
2021-05-29 22:15:49 +05:30
router . HandleFunc ( "/api/v1/service/dbOverview" , aH . getServiceDBOverview ) . Methods ( http . MethodGet )
2021-05-30 11:14:55 +05:30
router . HandleFunc ( "/api/v1/service/externalAvgDuration" , aH . GetServiceExternalAvgDuration ) . Methods ( http . MethodGet )
router . HandleFunc ( "/api/v1/service/externalErrors" , aH . getServiceExternalErrors ) . Methods ( http . MethodGet )
router . HandleFunc ( "/api/v1/service/external" , aH . getServiceExternal ) . Methods ( http . MethodGet )
2021-05-31 11:14:11 +05:30
router . HandleFunc ( "/api/v1/service/{service}/operations" , aH . getOperations ) . Methods ( http . MethodGet )
router . HandleFunc ( "/api/v1/service/top_endpoints" , aH . getTopEndpoints ) . Methods ( http . MethodGet )
2021-05-29 16:32:11 +05:30
router . HandleFunc ( "/api/v1/spans" , aH . searchSpans ) . Methods ( http . MethodGet )
2021-06-01 15:13:48 +05:30
router . HandleFunc ( "/api/v1/spans/aggregates" , aH . searchSpansAggregates ) . Methods ( http . MethodGet )
2021-05-31 11:14:11 +05:30
router . HandleFunc ( "/api/v1/tags" , aH . searchTags ) . Methods ( http . MethodGet )
router . HandleFunc ( "/api/v1/traces/{traceId}" , aH . searchTraces ) . Methods ( http . MethodGet )
router . HandleFunc ( "/api/v1/usage" , aH . getUsage ) . Methods ( http . MethodGet )
router . HandleFunc ( "/api/v1/serviceMapDependencies" , aH . serviceMapDependencies ) . Methods ( http . MethodGet )
2021-01-03 18:15:44 +05:30
}
2021-09-02 13:18:47 +05:30
func Intersection ( a , b [ ] int ) ( c [ ] int ) {
m := make ( map [ int ] bool )
for _ , item := range a {
m [ item ] = true
}
for _ , item := range b {
if _ , ok := m [ item ] ; ok {
c = append ( c , item )
}
}
return
}
func ( aH * APIHandler ) getDashboards ( w http . ResponseWriter , r * http . Request ) {
allDashboards , err := dashboards . GetDashboards ( )
if err != nil {
aH . respondError ( w , err , nil )
return
}
tagsFromReq , ok := r . URL . Query ( ) [ "tags" ]
if ! ok || len ( tagsFromReq ) == 0 || tagsFromReq [ 0 ] == "" {
aH . respond ( w , & allDashboards )
return
}
tags2Dash := make ( map [ string ] [ ] int )
for i := 0 ; i < len ( * allDashboards ) ; i ++ {
tags , ok := ( * allDashboards ) [ i ] . Data [ "tags" ] . ( [ ] interface { } )
if ! ok {
continue
}
tagsArray := make ( [ ] string , len ( tags ) )
for i , v := range tags {
tagsArray [ i ] = v . ( string )
}
for _ , tag := range tagsArray {
tags2Dash [ tag ] = append ( tags2Dash [ tag ] , i )
}
}
inter := make ( [ ] int , len ( * allDashboards ) )
for i := range inter {
inter [ i ] = i
}
for _ , tag := range tagsFromReq {
inter = Intersection ( inter , tags2Dash [ tag ] )
}
filteredDashboards := [ ] dashboards . Dashboard { }
for _ , val := range inter {
dash := ( * allDashboards ) [ val ]
filteredDashboards = append ( filteredDashboards , dash )
}
aH . respond ( w , & filteredDashboards )
}
func ( aH * APIHandler ) deleteDashboard ( w http . ResponseWriter , r * http . Request ) {
uuid := mux . Vars ( r ) [ "uuid" ]
err := dashboards . DeleteDashboard ( uuid )
if err != nil {
aH . respondError ( w , err , nil )
return
}
aH . respond ( w , nil )
}
func ( aH * APIHandler ) updateDashboard ( w http . ResponseWriter , r * http . Request ) {
uuid := mux . Vars ( r ) [ "uuid" ]
var postData map [ string ] interface { }
err := json . NewDecoder ( r . Body ) . Decode ( & postData )
if err != nil {
aH . respondError ( w , & model . ApiError { Typ : model . ErrorBadData , Err : err } , "Error reading request body" )
return
}
err = dashboards . IsPostDataSane ( & postData )
if err != nil {
aH . respondError ( w , & model . ApiError { Typ : model . ErrorBadData , Err : err } , "Error reading request body" )
return
}
if postData [ "uuid" ] != uuid {
aH . respondError ( w , & model . ApiError { Typ : model . ErrorBadData , Err : fmt . Errorf ( "uuid in request param and uuid in request body do not match" ) } , "Error reading request body" )
return
}
dashboard , apiError := dashboards . UpdateDashboard ( & postData )
if apiError != nil {
aH . respondError ( w , apiError , nil )
return
}
aH . respond ( w , dashboard )
}
func ( aH * APIHandler ) getDashboard ( w http . ResponseWriter , r * http . Request ) {
uuid := mux . Vars ( r ) [ "uuid" ]
dashboard , apiError := dashboards . GetDashboard ( uuid )
if apiError != nil {
aH . respondError ( w , apiError , nil )
return
}
aH . respond ( w , dashboard )
}
func ( aH * APIHandler ) createDashboards ( w http . ResponseWriter , r * http . Request ) {
var postData map [ string ] interface { }
err := json . NewDecoder ( r . Body ) . Decode ( & postData )
if err != nil {
aH . respondError ( w , & model . ApiError { Typ : model . ErrorInternal , Err : err } , "Error reading request body" )
return
}
err = dashboards . IsPostDataSane ( & postData )
if err != nil {
aH . respondError ( w , & model . ApiError { Typ : model . ErrorInternal , Err : err } , "Error reading request body" )
return
}
dash , apiErr := dashboards . CreateDashboard ( & postData )
if apiErr != nil {
aH . respondError ( w , apiErr , nil )
return
}
aH . respond ( w , dash )
}
2021-08-29 10:28:40 +05:30
func ( aH * APIHandler ) queryRangeMetrics ( w http . ResponseWriter , r * http . Request ) {
query , apiErrorObj := parseQueryRangeRequest ( r )
if apiErrorObj != nil {
aH . respondError ( w , apiErrorObj , nil )
return
}
// zap.S().Info(query, apiError)
ctx := r . Context ( )
if to := r . FormValue ( "timeout" ) ; to != "" {
var cancel context . CancelFunc
timeout , err := parseMetricsDuration ( to )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
ctx , cancel = context . WithTimeout ( ctx , timeout )
defer cancel ( )
}
res , qs , apiError := ( * aH . reader ) . GetQueryRangeResult ( ctx , query )
if apiError != nil {
aH . respondError ( w , apiError , nil )
return
}
if res . Err != nil {
zap . S ( ) . Error ( res . Err )
}
if res . Err != nil {
switch res . Err . ( type ) {
case promql . ErrQueryCanceled :
aH . respondError ( w , & model . ApiError { model . ErrorCanceled , res . Err } , nil )
case promql . ErrQueryTimeout :
aH . respondError ( w , & model . ApiError { model . ErrorTimeout , res . Err } , nil )
}
aH . respondError ( w , & model . ApiError { model . ErrorExec , res . Err } , nil )
}
response_data := & model . QueryData {
ResultType : res . Value . Type ( ) ,
Result : res . Value ,
Stats : qs ,
}
aH . respond ( w , response_data )
}
func ( aH * APIHandler ) queryMetrics ( w http . ResponseWriter , r * http . Request ) {
queryParams , apiErrorObj := parseInstantQueryMetricsRequest ( r )
if apiErrorObj != nil {
aH . respondError ( w , apiErrorObj , nil )
return
}
// zap.S().Info(query, apiError)
ctx := r . Context ( )
if to := r . FormValue ( "timeout" ) ; to != "" {
var cancel context . CancelFunc
timeout , err := parseMetricsDuration ( to )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
ctx , cancel = context . WithTimeout ( ctx , timeout )
defer cancel ( )
}
res , qs , apiError := ( * aH . reader ) . GetInstantQueryMetricsResult ( ctx , queryParams )
if apiError != nil {
aH . respondError ( w , apiError , nil )
return
}
if res . Err != nil {
zap . S ( ) . Error ( res . Err )
}
if res . Err != nil {
switch res . Err . ( type ) {
case promql . ErrQueryCanceled :
aH . respondError ( w , & model . ApiError { model . ErrorCanceled , res . Err } , nil )
case promql . ErrQueryTimeout :
aH . respondError ( w , & model . ApiError { model . ErrorTimeout , res . Err } , nil )
}
aH . respondError ( w , & model . ApiError { model . ErrorExec , res . Err } , nil )
}
response_data := & model . QueryData {
ResultType : res . Value . Type ( ) ,
Result : res . Value ,
Stats : qs ,
}
aH . respond ( w , response_data )
}
2021-01-09 19:10:34 +05:30
func ( aH * APIHandler ) user ( w http . ResponseWriter , r * http . Request ) {
email := r . URL . Query ( ) . Get ( "email" )
var err error
if len ( email ) == 0 {
err = fmt . Errorf ( "Email param is missing" )
}
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
( * aH . pc ) . Enqueue ( posthog . Identify {
DistinctId : aH . distinctId ,
Properties : posthog . NewProperties ( ) .
Set ( "email" , email ) ,
} )
}
2021-05-31 11:14:11 +05:30
func ( aH * APIHandler ) getOperations ( w http . ResponseWriter , r * http . Request ) {
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
vars := mux . Vars ( r )
serviceName := vars [ "service" ]
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
var err error
if len ( serviceName ) == 0 {
err = fmt . Errorf ( "service param not found" )
}
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
result , err := ( * aH . reader ) . GetOperations ( context . Background ( ) , serviceName )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
aH . writeJSON ( w , r , result )
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
func ( aH * APIHandler ) getServicesList ( w http . ResponseWriter , r * http . Request ) {
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
result , err := ( * aH . reader ) . GetServicesList ( context . Background ( ) )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
aH . writeJSON ( w , r , result )
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
func ( aH * APIHandler ) searchTags ( w http . ResponseWriter , r * http . Request ) {
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
serviceName := r . URL . Query ( ) . Get ( "service" )
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
result , err := ( * aH . reader ) . GetTags ( context . Background ( ) , serviceName )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
aH . writeJSON ( w , r , result )
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
func ( aH * APIHandler ) getTopEndpoints ( w http . ResponseWriter , r * http . Request ) {
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
query , err := parseGetTopEndpointsRequest ( r )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
result , err := ( * aH . reader ) . GetTopEndpoints ( context . Background ( ) , query )
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
aH . writeJSON ( w , r , result )
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
func ( aH * APIHandler ) getUsage ( w http . ResponseWriter , r * http . Request ) {
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
query , err := parseGetUsageRequest ( r )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
result , err := ( * aH . reader ) . GetUsage ( context . Background ( ) , query )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
aH . writeJSON ( w , r , result )
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
}
2021-01-03 18:15:44 +05:30
2021-05-29 22:15:49 +05:30
func ( aH * APIHandler ) getServiceDBOverview ( w http . ResponseWriter , r * http . Request ) {
2021-05-02 10:54:59 +05:30
2021-05-29 22:15:49 +05:30
query , err := parseGetServiceExternalRequest ( r )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-05-02 10:54:59 +05:30
2021-05-29 22:15:49 +05:30
result , err := ( * aH . reader ) . GetServiceDBOverview ( context . Background ( ) , query )
2021-05-02 10:54:59 +05:30
2021-05-29 22:15:49 +05:30
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-05-02 10:54:59 +05:30
2021-05-29 22:15:49 +05:30
aH . writeJSON ( w , r , result )
}
2021-05-02 10:54:59 +05:30
2021-05-30 11:14:55 +05:30
func ( aH * APIHandler ) getServiceExternal ( w http . ResponseWriter , r * http . Request ) {
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
query , err := parseGetServiceExternalRequest ( r )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
result , err := ( * aH . reader ) . GetServiceExternal ( context . Background ( ) , query )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
aH . writeJSON ( w , r , result )
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
}
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
func ( aH * APIHandler ) GetServiceExternalAvgDuration ( w http . ResponseWriter , r * http . Request ) {
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
query , err := parseGetServiceExternalRequest ( r )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
result , err := ( * aH . reader ) . GetServiceExternalAvgDuration ( context . Background ( ) , query )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
aH . writeJSON ( w , r , result )
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
}
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
func ( aH * APIHandler ) getServiceExternalErrors ( w http . ResponseWriter , r * http . Request ) {
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
query , err := parseGetServiceExternalRequest ( r )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
result , err := ( * aH . reader ) . GetServiceExternalErrors ( context . Background ( ) , query )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
aH . writeJSON ( w , r , result )
2021-04-26 21:55:11 +05:30
2021-05-30 11:14:55 +05:30
}
2021-04-26 21:55:11 +05:30
2021-05-29 16:32:11 +05:30
func ( aH * APIHandler ) getServiceOverview ( w http . ResponseWriter , r * http . Request ) {
2021-01-03 18:15:44 +05:30
2021-05-29 16:32:11 +05:30
query , err := parseGetServiceOverviewRequest ( r )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-05-29 16:32:11 +05:30
result , err := ( * aH . reader ) . GetServiceOverview ( context . Background ( ) , query )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-05-29 16:32:11 +05:30
aH . writeJSON ( w , r , result )
2021-01-03 18:15:44 +05:30
2021-05-29 16:32:11 +05:30
}
2021-01-03 18:15:44 +05:30
func ( aH * APIHandler ) getServices ( w http . ResponseWriter , r * http . Request ) {
query , err := parseGetServicesRequest ( r )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-05-22 19:51:56 +05:30
result , err := ( * aH . reader ) . GetServices ( context . Background ( ) , query )
2021-01-03 18:15:44 +05:30
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-09 19:10:34 +05:30
if len ( * result ) != 4 {
( * aH . pc ) . Enqueue ( posthog . Capture {
DistinctId : distinctId ,
Event : "Different Number of Services" ,
Properties : posthog . NewProperties ( ) . Set ( "number" , len ( * result ) ) ,
} )
}
2021-01-03 18:15:44 +05:30
aH . writeJSON ( w , r , result )
}
2021-05-05 00:03:57 +05:30
2021-05-31 11:14:11 +05:30
func ( aH * APIHandler ) serviceMapDependencies ( w http . ResponseWriter , r * http . Request ) {
query , err := parseGetServicesRequest ( r )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-05-05 00:03:57 +05:30
2021-05-31 11:14:11 +05:30
result , err := ( * aH . reader ) . GetServiceMapDependencies ( context . Background ( ) , query )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-05-05 00:03:57 +05:30
2021-05-31 11:14:11 +05:30
aH . writeJSON ( w , r , result )
}
2021-05-05 00:03:57 +05:30
2021-05-31 11:14:11 +05:30
func ( aH * APIHandler ) searchTraces ( w http . ResponseWriter , r * http . Request ) {
2021-05-05 00:03:57 +05:30
2021-05-31 11:14:11 +05:30
vars := mux . Vars ( r )
traceId := vars [ "traceId" ]
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
result , err := ( * aH . reader ) . SearchTraces ( context . Background ( ) , traceId )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
aH . writeJSON ( w , r , result )
2021-01-03 18:15:44 +05:30
2021-05-31 11:14:11 +05:30
}
2021-01-03 18:15:44 +05:30
2021-06-01 15:13:48 +05:30
func ( aH * APIHandler ) searchSpansAggregates ( w http . ResponseWriter , r * http . Request ) {
2021-01-03 18:15:44 +05:30
2021-06-01 15:13:48 +05:30
query , err := parseSearchSpanAggregatesRequest ( r )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-06-01 15:13:48 +05:30
result , err := ( * aH . reader ) . SearchSpansAggregate ( context . Background ( ) , query )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-06-01 15:13:48 +05:30
aH . writeJSON ( w , r , result )
}
2021-01-03 18:15:44 +05:30
2021-05-29 16:32:11 +05:30
func ( aH * APIHandler ) searchSpans ( w http . ResponseWriter , r * http . Request ) {
2021-01-03 18:15:44 +05:30
2021-05-29 16:32:11 +05:30
query , err := parseSpanSearchRequest ( r )
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
2021-01-03 18:15:44 +05:30
2021-05-29 16:32:11 +05:30
// result, err := druidQuery.SearchSpans(aH.client, query)
result , err := ( * aH . reader ) . SearchSpans ( context . Background ( ) , query )
2021-01-03 18:15:44 +05:30
2021-05-29 16:32:11 +05:30
if aH . handleError ( w , err , http . StatusBadRequest ) {
return
}
aH . writeJSON ( w , r , result )
}
2021-01-03 18:15:44 +05:30
2021-05-27 12:52:34 +05:30
// func (aH *APIHandler) getApplicationPercentiles(w http.ResponseWriter, r *http.Request) {
// // vars := mux.Vars(r)
2021-01-03 18:15:44 +05:30
2021-05-27 12:52:34 +05:30
// query, err := parseApplicationPercentileRequest(r)
// if aH.handleError(w, err, http.StatusBadRequest) {
// return
// }
2021-01-03 18:15:44 +05:30
2021-05-27 12:52:34 +05:30
// result, err := (*aH.reader).GetApplicationPercentiles(context.Background(), query)
// if aH.handleError(w, err, http.StatusBadRequest) {
// return
// }
// aH.writeJSON(w, r, result)
// }
2021-01-03 18:15:44 +05:30
func ( aH * APIHandler ) handleError ( w http . ResponseWriter , err error , statusCode int ) bool {
if err == nil {
return false
}
if statusCode == http . StatusInternalServerError {
zap . S ( ) . Error ( "HTTP handler, Internal Server Error" , zap . Error ( err ) )
}
structuredResp := structuredResponse {
Errors : [ ] structuredError {
{
Code : statusCode ,
Msg : err . Error ( ) ,
} ,
} ,
}
resp , _ := json . Marshal ( & structuredResp )
http . Error ( w , string ( resp ) , statusCode )
return true
}
func ( aH * APIHandler ) writeJSON ( w http . ResponseWriter , r * http . Request , response interface { } ) {
marshall := json . Marshal
if prettyPrint := r . FormValue ( "pretty" ) ; prettyPrint != "" && prettyPrint != "false" {
marshall = func ( v interface { } ) ( [ ] byte , error ) {
return json . MarshalIndent ( v , "" , " " )
}
}
resp , _ := marshall ( response )
w . Header ( ) . Set ( "Content-Type" , "application/json" )
w . Write ( resp )
}