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
-


@@ -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/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml b/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml
index 7ee41ca768..2bd2a48bde 100644
--- a/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml
+++ b/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml
@@ -40,7 +40,7 @@ services:
condition: on-failure
query-service:
- image: signoz/query-service:0.9.1
+ image: signoz/query-service:0.9.2
command: ["-config=/root/config/prometheus.yml"]
# ports:
# - "6060:6060" # pprof port
@@ -68,7 +68,7 @@ services:
- clickhouse
frontend:
- image: signoz/frontend:0.9.1
+ image: signoz/frontend:0.9.2
deploy:
restart_policy:
condition: on-failure
diff --git a/deploy/docker/clickhouse-setup/docker-compose.yaml b/deploy/docker/clickhouse-setup/docker-compose.yaml
index 102be2fe49..f8c2954446 100644
--- a/deploy/docker/clickhouse-setup/docker-compose.yaml
+++ b/deploy/docker/clickhouse-setup/docker-compose.yaml
@@ -39,7 +39,7 @@ services:
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
query-service:
- image: signoz/query-service:0.9.1
+ image: signoz/query-service:0.9.2
container_name: query-service
command: ["-config=/root/config/prometheus.yml"]
# ports:
@@ -66,7 +66,7 @@ services:
condition: service_healthy
frontend:
- image: signoz/frontend:0.9.1
+ image: signoz/frontend:0.9.2
container_name: frontend
restart: on-failure
depends_on:
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/src/api/index.ts b/frontend/src/api/index.ts
index 82f4bdc010..b59a224cdc 100644
--- a/frontend/src/api/index.ts
+++ b/frontend/src/api/index.ts
@@ -102,6 +102,11 @@ export const AxiosAlertManagerInstance = axios.create({
export const ApiV2Instance = axios.create({
baseURL: `${ENVIRONMENT.baseURL}${apiV2}`,
});
+ApiV2Instance.interceptors.response.use(
+ interceptorsResponse,
+ interceptorRejected,
+);
+ApiV2Instance.interceptors.request.use(interceptorsRequestResponse);
AxiosAlertManagerInstance.interceptors.response.use(
interceptorsResponse,
diff --git a/frontend/src/container/ListOfDashboard/ImportJSON/index.tsx b/frontend/src/container/ListOfDashboard/ImportJSON/index.tsx
index 021a5f9805..e1107fd9f2 100644
--- a/frontend/src/container/ListOfDashboard/ImportJSON/index.tsx
+++ b/frontend/src/container/ListOfDashboard/ImportJSON/index.tsx
@@ -15,7 +15,11 @@ import ROUTES from 'constants/routes';
import history from 'lib/history';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
+import { useDispatch } from 'react-redux';
import { generatePath } from 'react-router-dom';
+import { Dispatch } from 'redux';
+import AppActions from 'types/actions';
+import { FLUSH_DASHBOARD } from 'types/actions/dashboard';
import { DashboardData } from 'types/api/dashboard/getAll';
import { EditorContainer, FooterContainer } from './styles';
@@ -30,6 +34,8 @@ function ImportJSON({
const [isCreateDashboardError, setIsCreateDashboardError] = useState(
false,
);
+ const dispatch = useDispatch>();
+
const [dashboardCreating, setDashboardCreating] = useState(false);
const [editorValue, setEditorValue] = useState('');
@@ -86,6 +92,9 @@ function ImportJSON({
});
if (response.statusCode === 200) {
+ dispatch({
+ type: FLUSH_DASHBOARD,
+ });
setTimeout(() => {
history.push(
generatePath(ROUTES.DASHBOARD, {
diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx
index 08c6668775..c65c4570ec 100644
--- a/frontend/src/index.tsx
+++ b/frontend/src/index.tsx
@@ -5,6 +5,7 @@ import AppRoutes from 'AppRoutes';
import React from 'react';
import ReactDOM from 'react-dom';
import { QueryClient, QueryClientProvider } from 'react-query';
+import { ReactQueryDevtools } from 'react-query/devtools';
import { Provider } from 'react-redux';
import reportWebVitals from 'reportWebVitals';
import store from 'store';
@@ -28,6 +29,9 @@ ReactDOM.render(
+ {process.env.NODE_ENV === 'development' && (
+
+ )}
,
document.querySelector('#root'),
);
diff --git a/frontend/src/store/actions/dashboard/getQueryResults.ts b/frontend/src/store/actions/dashboard/getQueryResults.ts
index f1143a1431..17137b13c1 100644
--- a/frontend/src/store/actions/dashboard/getQueryResults.ts
+++ b/frontend/src/store/actions/dashboard/getQueryResults.ts
@@ -143,17 +143,23 @@ export async function GetMetricQueryRange({
`API responded with ${response.statusCode} - ${response.error}`,
);
}
-
if (response.payload?.data?.result) {
response.payload.data.result = response.payload.data.result.map(
(queryData) => {
const newQueryData = queryData;
- newQueryData.legend = legendMap[queryData.queryName];
+ newQueryData.legend = legendMap[queryData.queryName]; // Adds the legend if it is already defined by the user.
+ // If metric names is an empty object
if (isEmpty(queryData.metric)) {
- newQueryData.metric[queryData.queryName] = queryData.queryName;
- newQueryData.legend = queryData.queryName;
+ // If metrics list is empty && the user haven't defined a legend then add the legend equal to the name of the query.
+ if (!newQueryData.legend) {
+ newQueryData.legend = queryData.queryName;
+ }
+ // If name of the query and the legend if inserted is same then add the same to the metrics object.
+ if (queryData.queryName === newQueryData.legend) {
+ newQueryData.metric[queryData.queryName] = queryData.queryName;
+ }
}
- return queryData;
+ return newQueryData;
},
);
}
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() {