mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-11 17:59:09 +08:00
chore: update query service telemetry (#3735)
* chore: update query service telemetry * chore: address review comments * chore: add group call and update metrics condition * chore: update company_domain
This commit is contained in:
parent
5b858f2963
commit
f8d3fa0fdb
@ -5,7 +5,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
_ "net/http/pprof" // http profiler
|
||||
@ -20,9 +20,11 @@ import (
|
||||
"github.com/soheilhy/cmux"
|
||||
"go.signoz.io/signoz/ee/query-service/app/api"
|
||||
"go.signoz.io/signoz/ee/query-service/app/db"
|
||||
"go.signoz.io/signoz/ee/query-service/constants"
|
||||
"go.signoz.io/signoz/ee/query-service/dao"
|
||||
"go.signoz.io/signoz/ee/query-service/interfaces"
|
||||
baseInterface "go.signoz.io/signoz/pkg/query-service/interfaces"
|
||||
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
|
||||
|
||||
licensepkg "go.signoz.io/signoz/ee/query-service/license"
|
||||
"go.signoz.io/signoz/ee/query-service/usage"
|
||||
@ -198,6 +200,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
|
||||
}
|
||||
|
||||
telemetry.GetInstance().SetReader(reader)
|
||||
telemetry.GetInstance().SetSaasOperator(constants.SaasSegmentKey)
|
||||
|
||||
var c cache.Cache
|
||||
if serverOptions.CacheConfigPath != "" {
|
||||
@ -385,20 +388,20 @@ func (lrw *loggingResponseWriter) Flush() {
|
||||
lrw.ResponseWriter.(http.Flusher).Flush()
|
||||
}
|
||||
|
||||
func extractDashboardMetaData(path string, r *http.Request) (map[string]interface{}, bool) {
|
||||
pathToExtractBodyFrom := "/api/v2/metrics/query_range"
|
||||
func extractQueryRangeV3Data(path string, r *http.Request) (map[string]interface{}, bool) {
|
||||
pathToExtractBodyFrom := "/api/v3/query_range"
|
||||
|
||||
data := map[string]interface{}{}
|
||||
var postData *basemodel.QueryRangeParamsV2
|
||||
var postData *v3.QueryRangeParamsV3
|
||||
|
||||
if path == pathToExtractBodyFrom && (r.Method == "POST") {
|
||||
if r.Body != nil {
|
||||
bodyBytes, err := ioutil.ReadAll(r.Body)
|
||||
bodyBytes, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
r.Body.Close() // must close
|
||||
r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
|
||||
r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
|
||||
json.Unmarshal(bodyBytes, &postData)
|
||||
|
||||
} else {
|
||||
@ -409,24 +412,31 @@ func extractDashboardMetaData(path string, r *http.Request) (map[string]interfac
|
||||
return nil, false
|
||||
}
|
||||
|
||||
signozMetricNotFound := false
|
||||
|
||||
signozMetricsUsed := false
|
||||
signozLogsUsed := false
|
||||
dataSources := []string{}
|
||||
if postData != nil {
|
||||
signozMetricNotFound = telemetry.GetInstance().CheckSigNozMetricsV2(postData.CompositeMetricQuery)
|
||||
|
||||
if postData.CompositeMetricQuery != nil {
|
||||
data["queryType"] = postData.CompositeMetricQuery.QueryType
|
||||
data["panelType"] = postData.CompositeMetricQuery.PanelType
|
||||
if postData.CompositeQuery != nil {
|
||||
data["queryType"] = postData.CompositeQuery.QueryType
|
||||
data["panelType"] = postData.CompositeQuery.PanelType
|
||||
|
||||
signozLogsUsed, signozMetricsUsed = telemetry.GetInstance().CheckSigNozSignals(postData)
|
||||
}
|
||||
|
||||
data["datasource"] = postData.DataSource
|
||||
}
|
||||
|
||||
if signozMetricNotFound {
|
||||
telemetry.GetInstance().AddActiveMetricsUser()
|
||||
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_DASHBOARDS_METADATA, data, true)
|
||||
if signozMetricsUsed || signozLogsUsed {
|
||||
if signozMetricsUsed {
|
||||
dataSources = append(dataSources, "metrics")
|
||||
telemetry.GetInstance().AddActiveMetricsUser()
|
||||
}
|
||||
if signozLogsUsed {
|
||||
dataSources = append(dataSources, "logs")
|
||||
telemetry.GetInstance().AddActiveLogsUser()
|
||||
}
|
||||
data["dataSources"] = dataSources
|
||||
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_QUERY_RANGE_V3, data, true)
|
||||
}
|
||||
|
||||
return data, true
|
||||
}
|
||||
|
||||
@ -449,7 +459,7 @@ func (s *Server) analyticsMiddleware(next http.Handler) http.Handler {
|
||||
route := mux.CurrentRoute(r)
|
||||
path, _ := route.GetPathTemplate()
|
||||
|
||||
dashboardMetadata, metadataExists := extractDashboardMetaData(path, r)
|
||||
queryRangeV3data, metadataExists := extractQueryRangeV3Data(path, r)
|
||||
getActiveLogs(path, r)
|
||||
|
||||
lrw := NewLoggingResponseWriter(w)
|
||||
@ -457,7 +467,7 @@ func (s *Server) analyticsMiddleware(next http.Handler) http.Handler {
|
||||
|
||||
data := map[string]interface{}{"path": path, "statusCode": lrw.statusCode}
|
||||
if metadataExists {
|
||||
for key, value := range dashboardMetadata {
|
||||
for key, value := range queryRangeV3data {
|
||||
data[key] = value
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ const (
|
||||
|
||||
var LicenseSignozIo = "https://license.signoz.io/api/v1"
|
||||
var LicenseAPIKey = GetOrDefaultEnv("SIGNOZ_LICENSE_API_KEY", "")
|
||||
|
||||
var SaasSegmentKey = GetOrDefaultEnv("SIGNOZ_SAAS_SEGMENT_KEY", "")
|
||||
var SpanLimitStr = GetOrDefaultEnv("SPAN_LIMIT", "5000")
|
||||
|
||||
func GetOrDefaultEnv(key string, fallback string) string {
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
_ "net/http/pprof" // http profiler
|
||||
@ -24,6 +24,7 @@ import (
|
||||
"go.signoz.io/signoz/pkg/query-service/app/logparsingpipeline"
|
||||
"go.signoz.io/signoz/pkg/query-service/app/opamp"
|
||||
opAmpModel "go.signoz.io/signoz/pkg/query-service/app/opamp/model"
|
||||
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
|
||||
|
||||
"go.signoz.io/signoz/pkg/query-service/app/explorer"
|
||||
"go.signoz.io/signoz/pkg/query-service/auth"
|
||||
@ -320,20 +321,21 @@ func (lrw *loggingResponseWriter) WriteHeader(code int) {
|
||||
func (lrw *loggingResponseWriter) Flush() {
|
||||
lrw.ResponseWriter.(http.Flusher).Flush()
|
||||
}
|
||||
func extractDashboardMetaData(path string, r *http.Request) (map[string]interface{}, bool) {
|
||||
pathToExtractBodyFrom := "/api/v2/metrics/query_range"
|
||||
|
||||
func extractQueryRangeV3Data(path string, r *http.Request) (map[string]interface{}, bool) {
|
||||
pathToExtractBodyFrom := "/api/v3/query_range"
|
||||
|
||||
data := map[string]interface{}{}
|
||||
var postData *model.QueryRangeParamsV2
|
||||
var postData *v3.QueryRangeParamsV3
|
||||
|
||||
if path == pathToExtractBodyFrom && (r.Method == "POST") {
|
||||
if r.Body != nil {
|
||||
bodyBytes, err := ioutil.ReadAll(r.Body)
|
||||
bodyBytes, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
r.Body.Close() // must close
|
||||
r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
|
||||
r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
|
||||
json.Unmarshal(bodyBytes, &postData)
|
||||
|
||||
} else {
|
||||
@ -344,24 +346,31 @@ func extractDashboardMetaData(path string, r *http.Request) (map[string]interfac
|
||||
return nil, false
|
||||
}
|
||||
|
||||
signozMetricNotFound := false
|
||||
|
||||
signozMetricsUsed := false
|
||||
signozLogsUsed := false
|
||||
dataSources := []string{}
|
||||
if postData != nil {
|
||||
signozMetricNotFound = telemetry.GetInstance().CheckSigNozMetricsV2(postData.CompositeMetricQuery)
|
||||
|
||||
if postData.CompositeMetricQuery != nil {
|
||||
data["queryType"] = postData.CompositeMetricQuery.QueryType
|
||||
data["panelType"] = postData.CompositeMetricQuery.PanelType
|
||||
if postData.CompositeQuery != nil {
|
||||
data["queryType"] = postData.CompositeQuery.QueryType
|
||||
data["panelType"] = postData.CompositeQuery.PanelType
|
||||
|
||||
signozLogsUsed, signozMetricsUsed = telemetry.GetInstance().CheckSigNozSignals(postData)
|
||||
}
|
||||
|
||||
data["datasource"] = postData.DataSource
|
||||
}
|
||||
|
||||
if signozMetricNotFound {
|
||||
telemetry.GetInstance().AddActiveMetricsUser()
|
||||
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_DASHBOARDS_METADATA, data, true)
|
||||
if signozMetricsUsed || signozLogsUsed {
|
||||
if signozMetricsUsed {
|
||||
dataSources = append(dataSources, "metrics")
|
||||
telemetry.GetInstance().AddActiveMetricsUser()
|
||||
}
|
||||
if signozLogsUsed {
|
||||
dataSources = append(dataSources, "logs")
|
||||
telemetry.GetInstance().AddActiveLogsUser()
|
||||
}
|
||||
data["dataSources"] = dataSources
|
||||
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_QUERY_RANGE_V3, data, true)
|
||||
}
|
||||
|
||||
return data, true
|
||||
}
|
||||
|
||||
@ -384,7 +393,7 @@ func (s *Server) analyticsMiddleware(next http.Handler) http.Handler {
|
||||
route := mux.CurrentRoute(r)
|
||||
path, _ := route.GetPathTemplate()
|
||||
|
||||
dashboardMetadata, metadataExists := extractDashboardMetaData(path, r)
|
||||
queryRangeV3data, metadataExists := extractQueryRangeV3Data(path, r)
|
||||
getActiveLogs(path, r)
|
||||
|
||||
lrw := NewLoggingResponseWriter(w)
|
||||
@ -392,7 +401,7 @@ func (s *Server) analyticsMiddleware(next http.Handler) http.Handler {
|
||||
|
||||
data := map[string]interface{}{"path": path, "statusCode": lrw.statusCode}
|
||||
if metadataExists {
|
||||
for key, value := range dashboardMetadata {
|
||||
for key, value := range queryRangeV3data {
|
||||
data[key] = value
|
||||
}
|
||||
}
|
||||
|
@ -143,6 +143,7 @@ func (mds *ModelDaoSqlite) initializeOrgPreferences(ctx context.Context) error {
|
||||
telemetry.GetInstance().SetCountUsers(int8(countUsers))
|
||||
if countUsers > 0 {
|
||||
telemetry.GetInstance().SetCompanyDomain(users[countUsers-1].Email)
|
||||
telemetry.GetInstance().SetUserEmail(users[countUsers-1].Email)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -7,6 +7,7 @@ func IgnoredPaths() map[string]struct{} {
|
||||
"/api/v1/query_range": {},
|
||||
"/api/v2/metrics/query_range": {},
|
||||
"/api/v1/health": {},
|
||||
"/api/v1/featureFlags": {},
|
||||
}
|
||||
|
||||
return ignoredPaths
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"go.signoz.io/signoz/pkg/query-service/constants"
|
||||
"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/version"
|
||||
"gopkg.in/segmentio/analytics-go.v3"
|
||||
)
|
||||
@ -35,7 +36,7 @@ const (
|
||||
TELEMETRY_EVENT_LANGUAGE = "Language"
|
||||
TELEMETRY_EVENT_LOGS_FILTERS = "Logs Filters"
|
||||
TELEMETRY_EVENT_DISTRIBUTED = "Distributed"
|
||||
TELEMETRY_EVENT_DASHBOARDS_METADATA = "Dashboards Metadata"
|
||||
TELEMETRY_EVENT_QUERY_RANGE_V3 = "Query Range V3 Metadata"
|
||||
TELEMETRY_EVENT_ACTIVE_USER = "Active User"
|
||||
TELEMETRY_EVENT_ACTIVE_USER_PH = "Active User V2"
|
||||
)
|
||||
@ -74,28 +75,34 @@ func (a *Telemetry) IsSampled() bool {
|
||||
|
||||
}
|
||||
|
||||
func (telemetry *Telemetry) CheckSigNozMetricsV2(compositeQuery *model.CompositeMetricQuery) bool {
|
||||
func (telemetry *Telemetry) CheckSigNozSignals(postData *v3.QueryRangeParamsV3) (bool, bool) {
|
||||
signozLogsUsed := false
|
||||
signozMetricsUsed := false
|
||||
|
||||
signozMetricsNotFound := false
|
||||
|
||||
if compositeQuery.BuilderQueries != nil && len(compositeQuery.BuilderQueries) > 0 {
|
||||
if !strings.Contains(compositeQuery.BuilderQueries["A"].MetricName, "signoz_") && len(compositeQuery.BuilderQueries["A"].MetricName) > 0 {
|
||||
signozMetricsNotFound = true
|
||||
if postData.CompositeQuery.QueryType == v3.QueryTypeBuilder {
|
||||
for _, query := range postData.CompositeQuery.BuilderQueries {
|
||||
if query.DataSource == v3.DataSourceLogs && len(query.Filters.Items) > 0 {
|
||||
signozLogsUsed = true
|
||||
} else if query.DataSource == v3.DataSourceMetrics &&
|
||||
!strings.Contains(query.AggregateAttribute.Key, "signoz_") &&
|
||||
len(query.AggregateAttribute.Key) > 0 {
|
||||
signozMetricsUsed = true
|
||||
}
|
||||
}
|
||||
} else if postData.CompositeQuery.QueryType == v3.QueryTypePromQL {
|
||||
for _, query := range postData.CompositeQuery.PromQueries {
|
||||
if !strings.Contains(query.Query, "signoz_") && len(query.Query) > 0 {
|
||||
signozMetricsUsed = true
|
||||
}
|
||||
}
|
||||
} else if postData.CompositeQuery.QueryType == v3.QueryTypeClickHouseSQL {
|
||||
for _, query := range postData.CompositeQuery.ClickHouseQueries {
|
||||
if strings.Contains(query.Query, "signoz_metrics") && len(query.Query) > 0 {
|
||||
signozMetricsUsed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if compositeQuery.PromQueries != nil && len(compositeQuery.PromQueries) > 0 {
|
||||
if !strings.Contains(compositeQuery.PromQueries["A"].Query, "signoz_") && len(compositeQuery.PromQueries["A"].Query) > 0 {
|
||||
signozMetricsNotFound = true
|
||||
}
|
||||
}
|
||||
if compositeQuery.ClickHouseQueries != nil && len(compositeQuery.ClickHouseQueries) > 0 {
|
||||
if !strings.Contains(compositeQuery.ClickHouseQueries["A"].Query, "signoz_") && len(compositeQuery.ClickHouseQueries["A"].Query) > 0 {
|
||||
signozMetricsNotFound = true
|
||||
}
|
||||
}
|
||||
|
||||
return signozMetricsNotFound
|
||||
return signozLogsUsed, signozMetricsUsed
|
||||
}
|
||||
|
||||
func (telemetry *Telemetry) AddActiveTracesUser() {
|
||||
@ -116,8 +123,10 @@ func (telemetry *Telemetry) AddActiveLogsUser() {
|
||||
|
||||
type Telemetry struct {
|
||||
operator analytics.Client
|
||||
saasOperator analytics.Client
|
||||
phOperator ph.Client
|
||||
ipAddress string
|
||||
userEmail string
|
||||
isEnabled bool
|
||||
isAnonymous bool
|
||||
distinctId string
|
||||
@ -249,10 +258,25 @@ func getOutboundIP() string {
|
||||
}
|
||||
|
||||
func (a *Telemetry) IdentifyUser(user *model.User) {
|
||||
if user.Email == "admin@admin.com" || user.Email == "admin@signoz.cloud" {
|
||||
return
|
||||
}
|
||||
a.SetCompanyDomain(user.Email)
|
||||
a.SetUserEmail(user.Email)
|
||||
if !a.isTelemetryEnabled() || a.isTelemetryAnonymous() {
|
||||
return
|
||||
}
|
||||
if a.saasOperator != nil {
|
||||
a.saasOperator.Enqueue(analytics.Identify{
|
||||
UserId: a.userEmail,
|
||||
Traits: analytics.NewTraits().SetName(user.Name).SetEmail(user.Email),
|
||||
})
|
||||
a.saasOperator.Enqueue(analytics.Group{
|
||||
UserId: a.userEmail,
|
||||
GroupId: a.getCompanyDomain(),
|
||||
Traits: analytics.NewTraits().Set("company_domain", a.getCompanyDomain()),
|
||||
})
|
||||
}
|
||||
|
||||
a.operator.Enqueue(analytics.Identify{
|
||||
UserId: a.ipAddress,
|
||||
@ -272,6 +296,21 @@ func (a *Telemetry) SetCountUsers(countUsers int8) {
|
||||
a.countUsers = countUsers
|
||||
}
|
||||
|
||||
func (a *Telemetry) SetUserEmail(email string) {
|
||||
a.userEmail = email
|
||||
}
|
||||
|
||||
func (a *Telemetry) GetUserEmail() string {
|
||||
return a.userEmail
|
||||
}
|
||||
|
||||
func (a *Telemetry) SetSaasOperator(saasOperatorKey string) {
|
||||
if saasOperatorKey == "" {
|
||||
return
|
||||
}
|
||||
a.saasOperator = analytics.New(saasOperatorKey)
|
||||
}
|
||||
|
||||
func (a *Telemetry) SetCompanyDomain(email string) {
|
||||
|
||||
email_split := strings.Split(email, "@")
|
||||
@ -342,6 +381,15 @@ func (a *Telemetry) SendEvent(event string, data map[string]interface{}, opts ..
|
||||
userId = a.GetDistinctId()
|
||||
}
|
||||
|
||||
if a.saasOperator != nil && a.GetUserEmail() != "" &&
|
||||
(event == TELEMETRY_EVENT_NUMBER_OF_SERVICES || event == TELEMETRY_EVENT_ACTIVE_USER) {
|
||||
a.saasOperator.Enqueue(analytics.Track{
|
||||
Event: event,
|
||||
UserId: a.GetUserEmail(),
|
||||
Properties: properties,
|
||||
})
|
||||
}
|
||||
|
||||
a.operator.Enqueue(analytics.Track{
|
||||
Event: event,
|
||||
UserId: userId,
|
||||
|
Loading…
x
Reference in New Issue
Block a user