diff --git a/README.md b/README.md index f9c7d1e816..094415aadb 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ SigNoz helps developers monitor applications and troubleshoot problems in their 👉 Run aggregates on trace data to get business relevant metrics - ![screenzy-1644432902955](https://user-images.githubusercontent.com/504541/153270713-1b2156e6-ec03-42de-975b-3c02b8ec1836.png)
![screenzy-1644432986784](https://user-images.githubusercontent.com/504541/153270725-0efb73b3-06ed-4207-bf13-9b7e2e17c4b8.png) @@ -88,8 +87,7 @@ You can find the complete list of languages here - https://opentelemetry.io/docs ## Getting Started - - + ### Deploy using Docker Please follow the steps listed [here](https://signoz.io/docs/deployment/docker/) to install using docker @@ -102,7 +100,6 @@ The [troubleshooting instructions](https://signoz.io/docs/deployment/troubleshoo ### Deploy in Kubernetes using Helm Please follow the steps listed [here](https://signoz.io/docs/deployment/helm_chart) to install using helm charts -

@@ -112,7 +109,7 @@ Please follow the steps listed [here](https://signoz.io/docs/deployment/helm_cha ### SigNoz vs Prometheus -Prometheus is good if you want to do just metrics. But if you want to have a seamless experience between metrics and traces, then current experience of stitching together Prometheus & Jaeger is not great. +Prometheus is good if you want to do just metrics. But if you want to have a seamless experience between metrics and traces, then current experience of stitching together Prometheus & Jaeger is not great. Our goal is to provide an integrated UI between metrics & traces - similar to what SaaS vendors like Datadog provides - and give advanced filtering and aggregation over traces, something which Jaeger currently lack. @@ -133,11 +130,28 @@ Moreover, SigNoz has few more advanced features wrt Jaeger: ## Contributing - -We ❤️ contributions big or small. Please read [CONTRIBUTING.md](CONTRIBUTING.md) to get started with making contributions to SigNoz. +We ❤️ contributions big or small. Please read [CONTRIBUTING.md](CONTRIBUTING.md) to get started with making contributions to SigNoz. Not sure how to get started? Just ping us on `#contributing` in our [slack community](https://signoz.io/slack) +### Project maintainers + +#### Backend + +- [Ankit Nayan](https://github.com/ankitnayan) +- [Nityananda Gohain](https://github.com/nityanandagohain) +- [Srikanth Chekuri](https://github.com/srikanthccv) +- [Vishal Sharma](https://github.com/makeavish) + +#### Frontend + +- [Palash Gupta](https://github.com/palashgdev) +- [Pranshu Chittora](https://github.com/pranshuchittora) + +#### DevOps + +- [Prashant Shahi](https://github.com/prashant-shahi) +

@@ -156,11 +170,8 @@ Join the [slack community](https://signoz.io/slack) to know more about distribut If you have any ideas, questions, or any feedback, please share on our [Github Discussions](https://github.com/SigNoz/signoz/discussions) -As always, thanks to our amazing contributors! +As always, thanks to our amazing contributors! - - - diff --git a/frontend/commitlint.config.js b/frontend/commitlint.config.js deleted file mode 100644 index 422b19445b..0000000000 --- a/frontend/commitlint.config.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = { extends: ['@commitlint/config-conventional'] }; diff --git a/frontend/commitlint.config.ts b/frontend/commitlint.config.ts new file mode 100644 index 0000000000..3f5e287f9e --- /dev/null +++ b/frontend/commitlint.config.ts @@ -0,0 +1 @@ +export default { extends: ['@commitlint/config-conventional'] }; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index a10bce6e81..ca86de66b0 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -32,8 +32,8 @@ "./conf/default.conf", "./public", "./tests", - "playwright.config.ts", - "./commitlint.config.js", + "./playwright.config.ts", + "./commitlint.config.ts", "./webpack.config.js", "./webpack.config.prod.js", "./jest.setup.ts" diff --git a/pkg/query-service/app/clickhouseReader/reader.go b/pkg/query-service/app/clickhouseReader/reader.go index 17f3e5b047..8a6e2e6d36 100644 --- a/pkg/query-service/app/clickhouseReader/reader.go +++ b/pkg/query-service/app/clickhouseReader/reader.go @@ -2906,3 +2906,77 @@ func (r *ClickHouseReader) GetMetricResult(ctx context.Context, query string) ([ } return seriesList, nil } + +func (r *ClickHouseReader) GetTotalSpans(ctx context.Context) (uint64, error) { + + var totalSpans uint64 + + queryStr := fmt.Sprintf("SELECT count() from %s.%s;", signozTraceDBName, signozTraceTableName) + r.db.QueryRow(ctx, queryStr).Scan(&totalSpans) + + return totalSpans, nil +} + +func (r *ClickHouseReader) GetSpansInLastHeartBeatInterval(ctx context.Context) (uint64, error) { + + var spansInLastHeartBeatInterval uint64 + + queryStr := fmt.Sprintf("SELECT count() from %s.%s where timestamp > toUnixTimestamp(now()-toIntervalMinute(%d));", signozTraceDBName, signozSpansTable, 30) + + r.db.QueryRow(ctx, queryStr).Scan(&spansInLastHeartBeatInterval) + + return spansInLastHeartBeatInterval, nil +} + +// func sum(array []tsByMetricName) uint64 { +// var result uint64 +// result = 0 +// for _, v := range array { +// result += v.count +// } +// return result +// } + +func (r *ClickHouseReader) GetTimeSeriesInfo(ctx context.Context) (map[string]interface{}, error) { + + queryStr := fmt.Sprintf("SELECT count() as count from %s.%s group by metric_name order by count desc;", signozMetricDBName, signozTSTableName) + + // r.db.Select(ctx, &tsByMetricName, queryStr) + + rows, _ := r.db.Query(ctx, queryStr) + + var totalTS uint64 + totalTS = 0 + + var maxTS uint64 + maxTS = 0 + + count := 0 + for rows.Next() { + + var value uint64 + rows.Scan(&value) + totalTS += value + if count == 0 { + maxTS = value + } + count += 1 + } + + timeSeriesData := map[string]interface{}{} + timeSeriesData["totalTS"] = totalTS + timeSeriesData["maxTS"] = maxTS + + return timeSeriesData, nil +} + +func (r *ClickHouseReader) GetSamplesInfoInLastHeartBeatInterval(ctx context.Context) (uint64, error) { + + var totalSamples uint64 + + queryStr := fmt.Sprintf("select count() from %s.%s where timestamp_ms > toUnixTimestamp(now()-toIntervalMinute(%d))*1000;", signozMetricDBName, signozSampleTableName, 30) + + r.db.QueryRow(ctx, queryStr).Scan(&totalSamples) + + return totalSamples, nil +} diff --git a/pkg/query-service/app/http_handler.go b/pkg/query-service/app/http_handler.go index 400c9f2de4..51ff99a8a9 100644 --- a/pkg/query-service/app/http_handler.go +++ b/pkg/query-service/app/http_handler.go @@ -22,6 +22,7 @@ import ( "go.signoz.io/query-service/constants" "go.signoz.io/query-service/dao" am "go.signoz.io/query-service/integrations/alertManager" + "go.signoz.io/query-service/interfaces" "go.signoz.io/query-service/model" "go.signoz.io/query-service/telemetry" "go.signoz.io/query-service/version" @@ -46,14 +47,14 @@ type APIHandler struct { // queryParser queryParser basePath string apiPrefix string - reader *Reader + reader *interfaces.Reader relationalDB dao.ModelDao alertManager am.Manager ready func(http.HandlerFunc) http.HandlerFunc } // NewAPIHandler returns an APIHandler -func NewAPIHandler(reader *Reader, relationalDB dao.ModelDao) (*APIHandler, error) { +func NewAPIHandler(reader *interfaces.Reader, relationalDB dao.ModelDao) (*APIHandler, error) { alertManager := am.New("") aH := &APIHandler{ diff --git a/pkg/query-service/app/server.go b/pkg/query-service/app/server.go index 7904e813e2..5bccea66e2 100644 --- a/pkg/query-service/app/server.go +++ b/pkg/query-service/app/server.go @@ -19,6 +19,7 @@ import ( "go.signoz.io/query-service/constants" "go.signoz.io/query-service/dao" "go.signoz.io/query-service/healthcheck" + "go.signoz.io/query-service/interfaces" "go.signoz.io/query-service/telemetry" "go.signoz.io/query-service/utils" "go.uber.org/zap" @@ -65,7 +66,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) { localDB.SetMaxOpenConns(10) - var reader Reader + var reader interfaces.Reader storage := os.Getenv("STORAGE") if storage == "clickhouse" { zap.S().Info("Using ClickHouse as datastore ...") @@ -76,6 +77,8 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) { return nil, fmt.Errorf("Storage type: %s is not supported in query service", storage) } + telemetry.GetInstance().SetReader(reader) + apiHandler, err := NewAPIHandler(&reader, dao.DB()) if err != nil { return nil, err diff --git a/pkg/query-service/go.mod b/pkg/query-service/go.mod index 2effc47563..1d5dfa8e8d 100644 --- a/pkg/query-service/go.mod +++ b/pkg/query-service/go.mod @@ -140,4 +140,4 @@ require ( k8s.io/client-go v8.0.0+incompatible // indirect ) -replace github.com/prometheus/prometheus => github.com/SigNoz/prometheus v1.9.72 +replace github.com/prometheus/prometheus => github.com/SigNoz/prometheus v1.9.73 diff --git a/pkg/query-service/go.sum b/pkg/query-service/go.sum index 17a4a6e144..d69fb82481 100644 --- a/pkg/query-service/go.sum +++ b/pkg/query-service/go.sum @@ -57,8 +57,8 @@ github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/SigNoz/govaluate v0.0.0-20220522085550-d19c08c206cb h1:bneLSKPf9YUSFmafKx32bynV6QrzViL/s+ZDvQxH1E4= github.com/SigNoz/govaluate v0.0.0-20220522085550-d19c08c206cb/go.mod h1:JznGDNg9x1cujDKa22RaQOimOvvEfy3nxzDGd8XDgmA= -github.com/SigNoz/prometheus v1.9.72 h1:0p4ZN/NUb5jChB3blqpKKmANCAMWLp7N5L9YyyV7SQs= -github.com/SigNoz/prometheus v1.9.72/go.mod h1:Y4J9tGDmacMC+EcOTp+EIAn2C1sN+9kE+idyVKadiVM= +github.com/SigNoz/prometheus v1.9.73 h1:f6PjQrJGoCot9iJp/tWoKwgy0HTIqicYave4K3fT9ro= +github.com/SigNoz/prometheus v1.9.73/go.mod h1:Y4J9tGDmacMC+EcOTp+EIAn2C1sN+9kE+idyVKadiVM= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= diff --git a/pkg/query-service/app/interface.go b/pkg/query-service/interfaces/interface.go similarity index 92% rename from pkg/query-service/app/interface.go rename to pkg/query-service/interfaces/interface.go index fadbcd1e79..9c52a4497d 100644 --- a/pkg/query-service/app/interface.go +++ b/pkg/query-service/interfaces/interface.go @@ -1,4 +1,4 @@ -package app +package interfaces import ( "context" @@ -54,4 +54,9 @@ type Reader interface { GetMetricAutocompleteTagKey(ctx context.Context, params *model.MetricAutocompleteTagParams) (*[]string, *model.ApiError) GetMetricAutocompleteTagValue(ctx context.Context, params *model.MetricAutocompleteTagParams) (*[]string, *model.ApiError) GetMetricResult(ctx context.Context, query string) ([]*model.Series, error) + + GetTotalSpans(ctx context.Context) (uint64, error) + GetSpansInLastHeartBeatInterval(ctx context.Context) (uint64, error) + GetTimeSeriesInfo(ctx context.Context) (map[string]interface{}, error) + GetSamplesInfoInLastHeartBeatInterval(ctx context.Context) (uint64, error) } diff --git a/pkg/query-service/telemetry/ignoredPaths.go b/pkg/query-service/telemetry/ignoredPaths.go index 00ceb1c79a..e564cce2a2 100644 --- a/pkg/query-service/telemetry/ignoredPaths.go +++ b/pkg/query-service/telemetry/ignoredPaths.go @@ -2,8 +2,11 @@ package telemetry func IgnoredPaths() map[string]struct{} { ignoredPaths := map[string]struct{}{ - "/api/v1/tags": {}, - "/api/v1/version": {}, + "/api/v1/tags": {}, + "/api/v1/version": {}, + "/api/v1/query_range": {}, + "/api/v2/metrics/query_range": {}, + "/api/v1/services/list": {}, } return ignoredPaths diff --git a/pkg/query-service/telemetry/telemetry.go b/pkg/query-service/telemetry/telemetry.go index 1f5360fa40..ca402e4da8 100644 --- a/pkg/query-service/telemetry/telemetry.go +++ b/pkg/query-service/telemetry/telemetry.go @@ -1,6 +1,7 @@ package telemetry import ( + "context" "io/ioutil" "net/http" "os" @@ -8,6 +9,7 @@ import ( "time" "go.signoz.io/query-service/constants" + "go.signoz.io/query-service/interfaces" "go.signoz.io/query-service/model" "go.signoz.io/query-service/version" "gopkg.in/segmentio/analytics-go.v3" @@ -25,6 +27,10 @@ const ( const api_key = "4Gmoa4ixJAUHx2BpJxsjwA1bEfnwEeRz" const IP_NOT_FOUND_PLACEHOLDER = "NA" +const HEART_BEAT_DURATION = 6 * time.Hour + +// const HEART_BEAT_DURATION = 10 * time.Second + var telemetry *Telemetry var once sync.Once @@ -34,6 +40,7 @@ type Telemetry struct { isEnabled bool isAnonymous bool distinctId string + reader interfaces.Reader } func createTelemetry() { @@ -46,11 +53,24 @@ func createTelemetry() { telemetry.SetTelemetryEnabled(constants.IsTelemetryEnabled()) telemetry.SendEvent(TELEMETRY_EVENT_HEART_BEAT, data) - ticker := time.NewTicker(6 * time.Hour) + ticker := time.NewTicker(HEART_BEAT_DURATION) go func() { for { select { case <-ticker.C: + totalSpans, _ := telemetry.reader.GetTotalSpans(context.Background()) + spansInLastHeartBeatInterval, _ := telemetry.reader.GetSpansInLastHeartBeatInterval(context.Background()) + getSamplesInfoInLastHeartBeatInterval, _ := telemetry.reader.GetSamplesInfoInLastHeartBeatInterval(context.Background()) + tsInfo, _ := telemetry.reader.GetTimeSeriesInfo(context.Background()) + + data := map[string]interface{}{ + "totalSpans": totalSpans, + "spansInLastHeartBeatInterval": spansInLastHeartBeatInterval, + "getSamplesInfoInLastHeartBeatInterval": getSamplesInfoInLastHeartBeatInterval, + } + for key, value := range tsInfo { + data[key] = value + } telemetry.SendEvent(TELEMETRY_EVENT_HEART_BEAT, data) } } @@ -153,6 +173,10 @@ func (a *Telemetry) SetTelemetryEnabled(value bool) { a.isEnabled = value } +func (a *Telemetry) SetReader(reader interfaces.Reader) { + a.reader = reader +} + func GetInstance() *Telemetry { once.Do(func() {