mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-22 01:46:39 +00:00
chore: add new dashboard/alerts info events (#4214)
* chore: add new dashboard/alerts info events
This commit is contained in:
parent
c7b59d4405
commit
c66c8c2823
@ -480,7 +480,7 @@ func (s *Server) analyticsMiddleware(next http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := telemetry.IgnoredPaths()[path]; !ok {
|
if _, ok := telemetry.EnabledPaths()[path]; ok {
|
||||||
userEmail, err := auth.GetEmailFromJwt(r.Context())
|
userEmail, err := auth.GetEmailFromJwt(r.Context())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_PATH, data, userEmail)
|
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_PATH, data, userEmail)
|
||||||
|
|||||||
@ -43,6 +43,7 @@ import (
|
|||||||
promModel "github.com/prometheus/common/model"
|
promModel "github.com/prometheus/common/model"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"go.signoz.io/signoz/pkg/query-service/app/dashboards"
|
||||||
"go.signoz.io/signoz/pkg/query-service/app/logs"
|
"go.signoz.io/signoz/pkg/query-service/app/logs"
|
||||||
"go.signoz.io/signoz/pkg/query-service/app/services"
|
"go.signoz.io/signoz/pkg/query-service/app/services"
|
||||||
"go.signoz.io/signoz/pkg/query-service/auth"
|
"go.signoz.io/signoz/pkg/query-service/auth"
|
||||||
@ -51,6 +52,7 @@ import (
|
|||||||
"go.signoz.io/signoz/pkg/query-service/interfaces"
|
"go.signoz.io/signoz/pkg/query-service/interfaces"
|
||||||
"go.signoz.io/signoz/pkg/query-service/model"
|
"go.signoz.io/signoz/pkg/query-service/model"
|
||||||
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
|
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
|
||||||
|
"go.signoz.io/signoz/pkg/query-service/rules"
|
||||||
"go.signoz.io/signoz/pkg/query-service/telemetry"
|
"go.signoz.io/signoz/pkg/query-service/telemetry"
|
||||||
"go.signoz.io/signoz/pkg/query-service/utils"
|
"go.signoz.io/signoz/pkg/query-service/utils"
|
||||||
)
|
)
|
||||||
@ -3421,6 +3423,100 @@ func (r *ClickHouseReader) GetTagsInfoInLastHeartBeatInterval(ctx context.Contex
|
|||||||
return &tagsInfo, nil
|
return &tagsInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDashboardsInfo returns analytics data for dashboards
|
||||||
|
func (r *ClickHouseReader) GetDashboardsInfo(ctx context.Context) (*model.DashboardsInfo, error) {
|
||||||
|
dashboardsInfo := model.DashboardsInfo{}
|
||||||
|
// fetch dashboards from dashboard db
|
||||||
|
query := "SELECT data FROM dashboards"
|
||||||
|
var dashboardsData []dashboards.Dashboard
|
||||||
|
err := r.localDB.Select(&dashboardsData, query)
|
||||||
|
if err != nil {
|
||||||
|
zap.S().Debug("Error in processing sql query: ", err)
|
||||||
|
return &dashboardsInfo, err
|
||||||
|
}
|
||||||
|
for _, dashboard := range dashboardsData {
|
||||||
|
dashboardsInfo = countPanelsInDashboard(dashboard.Data)
|
||||||
|
}
|
||||||
|
dashboardsInfo.TotalDashboards = len(dashboardsData)
|
||||||
|
|
||||||
|
return &dashboardsInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func countPanelsInDashboard(data map[string]interface{}) model.DashboardsInfo {
|
||||||
|
var logsPanelCount, tracesPanelCount, metricsPanelCount int
|
||||||
|
// totalPanels := 0
|
||||||
|
if data != nil && data["widgets"] != nil {
|
||||||
|
widgets, ok := data["widgets"].(interface{})
|
||||||
|
if ok {
|
||||||
|
data, ok := widgets.([]interface{})
|
||||||
|
if ok {
|
||||||
|
for _, widget := range data {
|
||||||
|
sData, ok := widget.(map[string]interface{})
|
||||||
|
if ok && sData["query"] != nil {
|
||||||
|
// totalPanels++
|
||||||
|
query, ok := sData["query"].(interface{}).(map[string]interface{})
|
||||||
|
if ok && query["queryType"] == "builder" && query["builder"] != nil {
|
||||||
|
builderData, ok := query["builder"].(interface{}).(map[string]interface{})
|
||||||
|
if ok && builderData["queryData"] != nil {
|
||||||
|
builderQueryData, ok := builderData["queryData"].([]interface{})
|
||||||
|
if ok {
|
||||||
|
for _, queryData := range builderQueryData {
|
||||||
|
data, ok := queryData.(map[string]interface{})
|
||||||
|
if ok {
|
||||||
|
if data["dataSource"] == "traces" {
|
||||||
|
tracesPanelCount++
|
||||||
|
} else if data["dataSource"] == "metrics" {
|
||||||
|
metricsPanelCount++
|
||||||
|
} else if data["dataSource"] == "logs" {
|
||||||
|
logsPanelCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return model.DashboardsInfo{
|
||||||
|
LogsBasedPanels: logsPanelCount,
|
||||||
|
TracesBasedPanels: tracesPanelCount,
|
||||||
|
MetricBasedPanels: metricsPanelCount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ClickHouseReader) GetAlertsInfo(ctx context.Context) (*model.AlertsInfo, error) {
|
||||||
|
alertsInfo := model.AlertsInfo{}
|
||||||
|
// fetch alerts from rules db
|
||||||
|
query := "SELECT data FROM rules"
|
||||||
|
var alertsData []string
|
||||||
|
err := r.localDB.Select(&alertsData, query)
|
||||||
|
if err != nil {
|
||||||
|
zap.S().Debug("Error in processing sql query: ", err)
|
||||||
|
return &alertsInfo, err
|
||||||
|
}
|
||||||
|
for _, alert := range alertsData {
|
||||||
|
var rule rules.GettableRule
|
||||||
|
err = json.Unmarshal([]byte(alert), &rule)
|
||||||
|
if err != nil {
|
||||||
|
zap.S().Errorf("msg:", "invalid rule data", "\t err:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if rule.AlertType == "LOGS_BASED_ALERT" {
|
||||||
|
alertsInfo.LogsBasedAlerts = alertsInfo.LogsBasedAlerts + 1
|
||||||
|
} else if rule.AlertType == "METRIC_BASED_ALERT" {
|
||||||
|
alertsInfo.MetricBasedAlerts = alertsInfo.MetricBasedAlerts + 1
|
||||||
|
} else if rule.AlertType == "TRACES_BASED_ALERT" {
|
||||||
|
alertsInfo.TracesBasedAlerts = alertsInfo.TracesBasedAlerts + 1
|
||||||
|
}
|
||||||
|
alertsInfo.TotalAlerts = alertsInfo.TotalAlerts + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return &alertsInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *ClickHouseReader) GetLogFields(ctx context.Context) (*model.GetFieldsResponse, *model.ApiError) {
|
func (r *ClickHouseReader) GetLogFields(ctx context.Context) (*model.GetFieldsResponse, *model.ApiError) {
|
||||||
// response will contain top level fields from the otel log model
|
// response will contain top level fields from the otel log model
|
||||||
response := model.GetFieldsResponse{
|
response := model.GetFieldsResponse{
|
||||||
|
|||||||
@ -417,7 +417,7 @@ func (s *Server) analyticsMiddleware(next http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if telemetry.GetInstance().IsSampled() {
|
// if telemetry.GetInstance().IsSampled() {
|
||||||
if _, ok := telemetry.IgnoredPaths()[path]; !ok {
|
if _, ok := telemetry.EnabledPaths()[path]; ok {
|
||||||
userEmail, err := auth.GetEmailFromJwt(r.Context())
|
userEmail, err := auth.GetEmailFromJwt(r.Context())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_PATH, data, userEmail)
|
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_PATH, data, userEmail)
|
||||||
|
|||||||
@ -71,6 +71,8 @@ type Reader interface {
|
|||||||
GetListResultV3(ctx context.Context, query string) ([]*v3.Row, error)
|
GetListResultV3(ctx context.Context, query string) ([]*v3.Row, error)
|
||||||
LiveTailLogsV3(ctx context.Context, query string, timestampStart uint64, idStart string, client *v3.LogsLiveTailClient)
|
LiveTailLogsV3(ctx context.Context, query string, timestampStart uint64, idStart string, client *v3.LogsLiveTailClient)
|
||||||
|
|
||||||
|
GetDashboardsInfo(ctx context.Context) (*model.DashboardsInfo, error)
|
||||||
|
GetAlertsInfo(ctx context.Context) (*model.AlertsInfo, error)
|
||||||
GetTotalSpans(ctx context.Context) (uint64, error)
|
GetTotalSpans(ctx context.Context) (uint64, error)
|
||||||
GetSpansInLastHeartBeatInterval(ctx context.Context) (uint64, error)
|
GetSpansInLastHeartBeatInterval(ctx context.Context) (uint64, error)
|
||||||
GetTimeSeriesInfo(ctx context.Context) (map[string]interface{}, error)
|
GetTimeSeriesInfo(ctx context.Context) (map[string]interface{}, error)
|
||||||
|
|||||||
@ -615,6 +615,20 @@ type TagsInfo struct {
|
|||||||
Env string `json:"env"`
|
Env string `json:"env"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AlertsInfo struct {
|
||||||
|
TotalAlerts int `json:"totalAlerts"`
|
||||||
|
LogsBasedAlerts int `json:"logsBasedAlerts"`
|
||||||
|
MetricBasedAlerts int `json:"metricBasedAlerts"`
|
||||||
|
TracesBasedAlerts int `json:"tracesBasedAlerts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DashboardsInfo struct {
|
||||||
|
TotalDashboards int `json:"totalDashboards"`
|
||||||
|
LogsBasedPanels int `json:"logsBasedPanels"`
|
||||||
|
MetricBasedPanels int `json:"metricBasedPanels"`
|
||||||
|
TracesBasedPanels int `json:"tracesBasedPanels"`
|
||||||
|
}
|
||||||
|
|
||||||
type TagTelemetryData struct {
|
type TagTelemetryData struct {
|
||||||
ServiceName string `json:"serviceName" ch:"serviceName"`
|
ServiceName string `json:"serviceName" ch:"serviceName"`
|
||||||
Env string `json:"env" ch:"env"`
|
Env string `json:"env" ch:"env"`
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import (
|
|||||||
func TestThresholdRuleCombinations(t *testing.T) {
|
func TestThresholdRuleCombinations(t *testing.T) {
|
||||||
postableRule := PostableRule{
|
postableRule := PostableRule{
|
||||||
Alert: "Tricky Condition Tests",
|
Alert: "Tricky Condition Tests",
|
||||||
AlertType: "METRICS_BASED_ALERT",
|
AlertType: "METRIC_BASED_ALERT",
|
||||||
RuleType: RuleTypeThreshold,
|
RuleType: RuleTypeThreshold,
|
||||||
EvalWindow: Duration(5 * time.Minute),
|
EvalWindow: Duration(5 * time.Minute),
|
||||||
Frequency: Duration(1 * time.Minute),
|
Frequency: Duration(1 * time.Minute),
|
||||||
|
|||||||
@ -1,16 +1,11 @@
|
|||||||
package telemetry
|
package telemetry
|
||||||
|
|
||||||
func IgnoredPaths() map[string]struct{} {
|
func EnabledPaths() map[string]struct{} {
|
||||||
ignoredPaths := map[string]struct{}{
|
enabledPaths := map[string]struct{}{
|
||||||
"/api/v1/tags": {},
|
"/api/v1/channels": {},
|
||||||
"/api/v1/version": {},
|
|
||||||
"/api/v1/query_range": {},
|
|
||||||
"/api/v2/metrics/query_range": {},
|
|
||||||
"/api/v1/health": {},
|
|
||||||
"/api/v1/featureFlags": {},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ignoredPaths
|
return enabledPaths
|
||||||
}
|
}
|
||||||
|
|
||||||
func ignoreEvents(event string, attributes map[string]interface{}) bool {
|
func ignoreEvents(event string, attributes map[string]interface{}) bool {
|
||||||
|
|||||||
@ -38,6 +38,7 @@ const (
|
|||||||
TELEMETRY_EVENT_LOGS_FILTERS = "Logs Filters"
|
TELEMETRY_EVENT_LOGS_FILTERS = "Logs Filters"
|
||||||
TELEMETRY_EVENT_DISTRIBUTED = "Distributed"
|
TELEMETRY_EVENT_DISTRIBUTED = "Distributed"
|
||||||
TELEMETRY_EVENT_QUERY_RANGE_V3 = "Query Range V3 Metadata"
|
TELEMETRY_EVENT_QUERY_RANGE_V3 = "Query Range V3 Metadata"
|
||||||
|
TELEMETRY_EVENT_DASHBOARDS_ALERTS = "Dashboards/Alerts Info"
|
||||||
TELEMETRY_EVENT_ACTIVE_USER = "Active User"
|
TELEMETRY_EVENT_ACTIVE_USER = "Active User"
|
||||||
TELEMETRY_EVENT_ACTIVE_USER_PH = "Active User V2"
|
TELEMETRY_EVENT_ACTIVE_USER_PH = "Active User V2"
|
||||||
TELEMETRY_EVENT_USER_INVITATION_SENT = "User Invitation Sent"
|
TELEMETRY_EVENT_USER_INVITATION_SENT = "User Invitation Sent"
|
||||||
@ -53,6 +54,7 @@ var SAAS_EVENTS_LIST = map[string]struct{}{
|
|||||||
TELEMETRY_EVENT_ENVIRONMENT: {},
|
TELEMETRY_EVENT_ENVIRONMENT: {},
|
||||||
TELEMETRY_EVENT_USER_INVITATION_SENT: {},
|
TELEMETRY_EVENT_USER_INVITATION_SENT: {},
|
||||||
TELEMETRY_EVENT_USER_INVITATION_ACCEPTED: {},
|
TELEMETRY_EVENT_USER_INVITATION_ACCEPTED: {},
|
||||||
|
TELEMETRY_EVENT_DASHBOARDS_ALERTS: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
const api_key = "4Gmoa4ixJAUHx2BpJxsjwA1bEfnwEeRz"
|
const api_key = "4Gmoa4ixJAUHx2BpJxsjwA1bEfnwEeRz"
|
||||||
@ -61,9 +63,9 @@ const ph_api_key = "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w"
|
|||||||
const IP_NOT_FOUND_PLACEHOLDER = "NA"
|
const IP_NOT_FOUND_PLACEHOLDER = "NA"
|
||||||
const DEFAULT_NUMBER_OF_SERVICES = 6
|
const DEFAULT_NUMBER_OF_SERVICES = 6
|
||||||
|
|
||||||
const HEART_BEAT_DURATION = 6 * time.Hour
|
const HEART_BEAT_DURATION = 12 * time.Hour
|
||||||
|
|
||||||
const ACTIVE_USER_DURATION = 30 * time.Minute
|
const ACTIVE_USER_DURATION = 6 * time.Hour
|
||||||
|
|
||||||
// const HEART_BEAT_DURATION = 30 * time.Second
|
// const HEART_BEAT_DURATION = 30 * time.Second
|
||||||
// const ACTIVE_USER_DURATION = 30 * time.Second
|
// const ACTIVE_USER_DURATION = 30 * time.Second
|
||||||
@ -241,9 +243,27 @@ func createTelemetry() {
|
|||||||
}
|
}
|
||||||
telemetry.SendEvent(TELEMETRY_EVENT_HEART_BEAT, data, "")
|
telemetry.SendEvent(TELEMETRY_EVENT_HEART_BEAT, data, "")
|
||||||
|
|
||||||
|
alertsInfo, err := telemetry.reader.GetAlertsInfo(context.Background())
|
||||||
|
dashboardsInfo, err := telemetry.reader.GetDashboardsInfo(context.Background())
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
dashboardsAlertsData := map[string]interface{}{
|
||||||
|
"totalDashboards": dashboardsInfo.TotalDashboards,
|
||||||
|
"logsBasedPanels": dashboardsInfo.LogsBasedPanels,
|
||||||
|
"metricBasedPanels": dashboardsInfo.MetricBasedPanels,
|
||||||
|
"tracesBasedPanels": dashboardsInfo.TracesBasedPanels,
|
||||||
|
"totalAlerts": alertsInfo.TotalAlerts,
|
||||||
|
"logsBasedAlerts": alertsInfo.LogsBasedAlerts,
|
||||||
|
"metricBasedAlerts": alertsInfo.MetricBasedAlerts,
|
||||||
|
"tracesBasedAlerts": alertsInfo.TracesBasedAlerts,
|
||||||
|
}
|
||||||
|
telemetry.SendEvent(TELEMETRY_EVENT_DASHBOARDS_ALERTS, dashboardsAlertsData, "")
|
||||||
|
} else {
|
||||||
|
telemetry.SendEvent(TELEMETRY_EVENT_DASHBOARDS_ALERTS, map[string]interface{}{"error": err.Error()}, "")
|
||||||
|
}
|
||||||
|
|
||||||
getDistributedInfoInLastHeartBeatInterval, _ := telemetry.reader.GetDistributedInfoInLastHeartBeatInterval(context.Background())
|
getDistributedInfoInLastHeartBeatInterval, _ := telemetry.reader.GetDistributedInfoInLastHeartBeatInterval(context.Background())
|
||||||
telemetry.SendEvent(TELEMETRY_EVENT_DISTRIBUTED, getDistributedInfoInLastHeartBeatInterval, "")
|
telemetry.SendEvent(TELEMETRY_EVENT_DISTRIBUTED, getDistributedInfoInLastHeartBeatInterval, "")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user