-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into enable-new-search-bar-for-logs
- Loading branch information
Showing
81 changed files
with
3,617 additions
and
3,126 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
--- | ||
name: Request Dashboard | ||
about: Request a new dashboard for the SigNoz Dashboards repository | ||
title: '' | ||
labels: 'dashboard-template' | ||
assignees: '' | ||
|
||
--- | ||
|
||
## 📝 Dashboard Request Template | ||
|
||
*Use this template to request a new dashboard for the SigNoz Dashboards repository. Please provide as much detail as possible to help us understand your needs.* | ||
|
||
--- | ||
|
||
### 1. Dashboard Name | ||
|
||
Name of the requested dashboard (e.g., MySQL Monitoring Dashboard): | ||
|
||
--- | ||
|
||
### 2. Expected Dashboard Sections and Panels | ||
|
||
#### Section Name | ||
|
||
Brief description of the section (e.g., "Resource usage metrics for MySQL database"). | ||
|
||
#### Panel Name | ||
|
||
Panel description (e.g., "Value-type panels displaying current CPU usage, memory usage, etc."). | ||
|
||
- **Example:** | ||
- **Section**: Resource Metrics | ||
- **Panel**: CPU Usage - Displays the current CPU usage across all database instances. | ||
- **Panel**: Memory Usage - Displays the total memory used by the MySQL process. | ||
|
||
(Repeat this format for additional sections and panels) | ||
|
||
--- | ||
|
||
### 3. Expected Variables | ||
|
||
List any variables you expect to use in the dashboard (e.g., `deployment.environment`, `hostname`, etc.). | ||
|
||
--- | ||
|
||
### 4. Additional Comments or Requirements | ||
|
||
Any additional details or special requirements for the dashboard? | ||
|
||
--- | ||
|
||
### 📋 Notes | ||
|
||
Please review the [CONTRIBUTING.md](https://github.com/SigNoz/dashboards/blob/main/CONTRIBUTING.md) for guidelines on dashboard structure, naming conventions, and how to submit a pull request. | ||
|
||
--- | ||
Thank you for your request! We will review it and provide feedback or guidance as necessary. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package anomaly | ||
|
||
import ( | ||
"context" | ||
|
||
querierV2 "go.signoz.io/signoz/pkg/query-service/app/querier/v2" | ||
"go.signoz.io/signoz/pkg/query-service/app/queryBuilder" | ||
) | ||
|
||
type DailyProvider struct { | ||
BaseSeasonalProvider | ||
} | ||
|
||
var _ BaseProvider = (*DailyProvider)(nil) | ||
|
||
func (dp *DailyProvider) GetBaseSeasonalProvider() *BaseSeasonalProvider { | ||
return &dp.BaseSeasonalProvider | ||
} | ||
|
||
// NewDailyProvider uses the same generic option type | ||
func NewDailyProvider(opts ...GenericProviderOption[*DailyProvider]) *DailyProvider { | ||
dp := &DailyProvider{ | ||
BaseSeasonalProvider: BaseSeasonalProvider{}, | ||
} | ||
|
||
for _, opt := range opts { | ||
opt(dp) | ||
} | ||
|
||
dp.querierV2 = querierV2.NewQuerier(querierV2.QuerierOptions{ | ||
Reader: dp.reader, | ||
Cache: dp.cache, | ||
KeyGenerator: queryBuilder.NewKeyGenerator(), | ||
FluxInterval: dp.fluxInterval, | ||
FeatureLookup: dp.ff, | ||
}) | ||
|
||
return dp | ||
} | ||
|
||
func (p *DailyProvider) GetAnomalies(ctx context.Context, req *GetAnomaliesRequest) (*GetAnomaliesResponse, error) { | ||
req.Seasonality = SeasonalityDaily | ||
return p.getAnomalies(ctx, req) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package anomaly | ||
|
||
import ( | ||
"context" | ||
|
||
querierV2 "go.signoz.io/signoz/pkg/query-service/app/querier/v2" | ||
"go.signoz.io/signoz/pkg/query-service/app/queryBuilder" | ||
) | ||
|
||
type HourlyProvider struct { | ||
BaseSeasonalProvider | ||
} | ||
|
||
var _ BaseProvider = (*HourlyProvider)(nil) | ||
|
||
func (hp *HourlyProvider) GetBaseSeasonalProvider() *BaseSeasonalProvider { | ||
return &hp.BaseSeasonalProvider | ||
} | ||
|
||
// NewHourlyProvider now uses the generic option type | ||
func NewHourlyProvider(opts ...GenericProviderOption[*HourlyProvider]) *HourlyProvider { | ||
hp := &HourlyProvider{ | ||
BaseSeasonalProvider: BaseSeasonalProvider{}, | ||
} | ||
|
||
for _, opt := range opts { | ||
opt(hp) | ||
} | ||
|
||
hp.querierV2 = querierV2.NewQuerier(querierV2.QuerierOptions{ | ||
Reader: hp.reader, | ||
Cache: hp.cache, | ||
KeyGenerator: queryBuilder.NewKeyGenerator(), | ||
FluxInterval: hp.fluxInterval, | ||
FeatureLookup: hp.ff, | ||
}) | ||
|
||
return hp | ||
} | ||
|
||
func (p *HourlyProvider) GetAnomalies(ctx context.Context, req *GetAnomaliesRequest) (*GetAnomaliesResponse, error) { | ||
req.Seasonality = SeasonalityHourly | ||
return p.getAnomalies(ctx, req) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
package anomaly | ||
|
||
import ( | ||
"math" | ||
"time" | ||
|
||
"go.signoz.io/signoz/pkg/query-service/common" | ||
v3 "go.signoz.io/signoz/pkg/query-service/model/v3" | ||
) | ||
|
||
type Seasonality string | ||
|
||
const ( | ||
SeasonalityHourly Seasonality = "hourly" | ||
SeasonalityDaily Seasonality = "daily" | ||
SeasonalityWeekly Seasonality = "weekly" | ||
) | ||
|
||
var ( | ||
oneWeekOffset = 24 * 7 * time.Hour.Milliseconds() | ||
oneDayOffset = 24 * time.Hour.Milliseconds() | ||
oneHourOffset = time.Hour.Milliseconds() | ||
fiveMinOffset = 5 * time.Minute.Milliseconds() | ||
) | ||
|
||
func (s Seasonality) IsValid() bool { | ||
switch s { | ||
case SeasonalityHourly, SeasonalityDaily, SeasonalityWeekly: | ||
return true | ||
default: | ||
return false | ||
} | ||
} | ||
|
||
type GetAnomaliesRequest struct { | ||
Params *v3.QueryRangeParamsV3 | ||
Seasonality Seasonality | ||
} | ||
|
||
type GetAnomaliesResponse struct { | ||
Results []*v3.Result | ||
} | ||
|
||
// anomalyParams is the params for anomaly detection | ||
// prediction = avg(past_period_query) + avg(current_season_query) - mean(past_season_query, past2_season_query, past3_season_query) | ||
// | ||
// ^ ^ | ||
// | | | ||
// (rounded value for past peiod) + (seasonal growth) | ||
// | ||
// score = abs(value - prediction) / stddev (current_season_query) | ||
type anomalyQueryParams struct { | ||
// CurrentPeriodQuery is the query range params for period user is looking at or eval window | ||
// Example: (now-5m, now), (now-30m, now), (now-1h, now) | ||
// The results obtained from this query are used to compare with predicted values | ||
// and to detect anomalies | ||
CurrentPeriodQuery *v3.QueryRangeParamsV3 | ||
// PastPeriodQuery is the query range params for past seasonal period | ||
// Example: For weekly seasonality, (now-1w-5m, now-1w) | ||
// : For daily seasonality, (now-1d-5m, now-1d) | ||
// : For hourly seasonality, (now-1h-5m, now-1h) | ||
PastPeriodQuery *v3.QueryRangeParamsV3 | ||
// CurrentSeasonQuery is the query range params for current period (seasonal) | ||
// Example: For weekly seasonality, this is the query range params for the (now-1w-5m, now) | ||
// : For daily seasonality, this is the query range params for the (now-1d-5m, now) | ||
// : For hourly seasonality, this is the query range params for the (now-1h-5m, now) | ||
CurrentSeasonQuery *v3.QueryRangeParamsV3 | ||
// PastSeasonQuery is the query range params for past seasonal period to the current season | ||
// Example: For weekly seasonality, this is the query range params for the (now-2w-5m, now-1w) | ||
// : For daily seasonality, this is the query range params for the (now-2d-5m, now-1d) | ||
// : For hourly seasonality, this is the query range params for the (now-2h-5m, now-1h) | ||
PastSeasonQuery *v3.QueryRangeParamsV3 | ||
|
||
// Past2SeasonQuery is the query range params for past 2 seasonal period to the current season | ||
// Example: For weekly seasonality, this is the query range params for the (now-3w-5m, now-2w) | ||
// : For daily seasonality, this is the query range params for the (now-3d-5m, now-2d) | ||
// : For hourly seasonality, this is the query range params for the (now-3h-5m, now-2h) | ||
Past2SeasonQuery *v3.QueryRangeParamsV3 | ||
// Past3SeasonQuery is the query range params for past 3 seasonal period to the current season | ||
// Example: For weekly seasonality, this is the query range params for the (now-4w-5m, now-3w) | ||
// : For daily seasonality, this is the query range params for the (now-4d-5m, now-3d) | ||
// : For hourly seasonality, this is the query range params for the (now-4h-5m, now-3h) | ||
Past3SeasonQuery *v3.QueryRangeParamsV3 | ||
} | ||
|
||
func updateStepInterval(req *v3.QueryRangeParamsV3) { | ||
start := req.Start | ||
end := req.End | ||
|
||
req.Step = int64(math.Max(float64(common.MinAllowedStepInterval(start, end)), 60)) | ||
for _, q := range req.CompositeQuery.BuilderQueries { | ||
// If the step interval is less than the minimum allowed step interval, set it to the minimum allowed step interval | ||
if minStep := common.MinAllowedStepInterval(start, end); q.StepInterval < minStep { | ||
q.StepInterval = minStep | ||
} | ||
} | ||
} | ||
|
||
func prepareAnomalyQueryParams(req *v3.QueryRangeParamsV3, seasonality Seasonality) *anomalyQueryParams { | ||
start := req.Start | ||
end := req.End | ||
|
||
currentPeriodQuery := &v3.QueryRangeParamsV3{ | ||
Start: start, | ||
End: end, | ||
CompositeQuery: req.CompositeQuery.Clone(), | ||
Variables: make(map[string]interface{}, 0), | ||
NoCache: false, | ||
} | ||
updateStepInterval(currentPeriodQuery) | ||
|
||
var pastPeriodStart, pastPeriodEnd int64 | ||
|
||
switch seasonality { | ||
// for one week period, we fetch the data from the past week with 5 min offset | ||
case SeasonalityWeekly: | ||
pastPeriodStart = start - oneWeekOffset - fiveMinOffset | ||
pastPeriodEnd = end - oneWeekOffset | ||
// for one day period, we fetch the data from the past day with 5 min offset | ||
case SeasonalityDaily: | ||
pastPeriodStart = start - oneDayOffset - fiveMinOffset | ||
pastPeriodEnd = end - oneDayOffset | ||
// for one hour period, we fetch the data from the past hour with 5 min offset | ||
case SeasonalityHourly: | ||
pastPeriodStart = start - oneHourOffset - fiveMinOffset | ||
pastPeriodEnd = end - oneHourOffset | ||
} | ||
|
||
pastPeriodQuery := &v3.QueryRangeParamsV3{ | ||
Start: pastPeriodStart, | ||
End: pastPeriodEnd, | ||
CompositeQuery: req.CompositeQuery.Clone(), | ||
Variables: make(map[string]interface{}, 0), | ||
NoCache: false, | ||
} | ||
updateStepInterval(pastPeriodQuery) | ||
|
||
// seasonality growth trend | ||
var currentGrowthPeriodStart, currentGrowthPeriodEnd int64 | ||
switch seasonality { | ||
case SeasonalityWeekly: | ||
currentGrowthPeriodStart = start - oneWeekOffset | ||
currentGrowthPeriodEnd = end | ||
case SeasonalityDaily: | ||
currentGrowthPeriodStart = start - oneDayOffset | ||
currentGrowthPeriodEnd = end | ||
case SeasonalityHourly: | ||
currentGrowthPeriodStart = start - oneHourOffset | ||
currentGrowthPeriodEnd = end | ||
} | ||
|
||
currentGrowthQuery := &v3.QueryRangeParamsV3{ | ||
Start: currentGrowthPeriodStart, | ||
End: currentGrowthPeriodEnd, | ||
CompositeQuery: req.CompositeQuery.Clone(), | ||
Variables: make(map[string]interface{}, 0), | ||
NoCache: false, | ||
} | ||
updateStepInterval(currentGrowthQuery) | ||
|
||
var pastGrowthPeriodStart, pastGrowthPeriodEnd int64 | ||
switch seasonality { | ||
case SeasonalityWeekly: | ||
pastGrowthPeriodStart = start - 2*oneWeekOffset | ||
pastGrowthPeriodEnd = start - 1*oneWeekOffset | ||
case SeasonalityDaily: | ||
pastGrowthPeriodStart = start - 2*oneDayOffset | ||
pastGrowthPeriodEnd = start - 1*oneDayOffset | ||
case SeasonalityHourly: | ||
pastGrowthPeriodStart = start - 2*oneHourOffset | ||
pastGrowthPeriodEnd = start - 1*oneHourOffset | ||
} | ||
|
||
pastGrowthQuery := &v3.QueryRangeParamsV3{ | ||
Start: pastGrowthPeriodStart, | ||
End: pastGrowthPeriodEnd, | ||
CompositeQuery: req.CompositeQuery.Clone(), | ||
Variables: make(map[string]interface{}, 0), | ||
NoCache: false, | ||
} | ||
updateStepInterval(pastGrowthQuery) | ||
|
||
var past2GrowthPeriodStart, past2GrowthPeriodEnd int64 | ||
switch seasonality { | ||
case SeasonalityWeekly: | ||
past2GrowthPeriodStart = start - 3*oneWeekOffset | ||
past2GrowthPeriodEnd = start - 2*oneWeekOffset | ||
case SeasonalityDaily: | ||
past2GrowthPeriodStart = start - 3*oneDayOffset | ||
past2GrowthPeriodEnd = start - 2*oneDayOffset | ||
case SeasonalityHourly: | ||
past2GrowthPeriodStart = start - 3*oneHourOffset | ||
past2GrowthPeriodEnd = start - 2*oneHourOffset | ||
} | ||
|
||
past2GrowthQuery := &v3.QueryRangeParamsV3{ | ||
Start: past2GrowthPeriodStart, | ||
End: past2GrowthPeriodEnd, | ||
CompositeQuery: req.CompositeQuery.Clone(), | ||
Variables: make(map[string]interface{}, 0), | ||
NoCache: false, | ||
} | ||
updateStepInterval(past2GrowthQuery) | ||
|
||
var past3GrowthPeriodStart, past3GrowthPeriodEnd int64 | ||
switch seasonality { | ||
case SeasonalityWeekly: | ||
past3GrowthPeriodStart = start - 4*oneWeekOffset | ||
past3GrowthPeriodEnd = start - 3*oneWeekOffset | ||
case SeasonalityDaily: | ||
past3GrowthPeriodStart = start - 4*oneDayOffset | ||
past3GrowthPeriodEnd = start - 3*oneDayOffset | ||
case SeasonalityHourly: | ||
past3GrowthPeriodStart = start - 4*oneHourOffset | ||
past3GrowthPeriodEnd = start - 3*oneHourOffset | ||
} | ||
|
||
past3GrowthQuery := &v3.QueryRangeParamsV3{ | ||
Start: past3GrowthPeriodStart, | ||
End: past3GrowthPeriodEnd, | ||
CompositeQuery: req.CompositeQuery.Clone(), | ||
Variables: make(map[string]interface{}, 0), | ||
NoCache: false, | ||
} | ||
updateStepInterval(past3GrowthQuery) | ||
|
||
return &anomalyQueryParams{ | ||
CurrentPeriodQuery: currentPeriodQuery, | ||
PastPeriodQuery: pastPeriodQuery, | ||
CurrentSeasonQuery: currentGrowthQuery, | ||
PastSeasonQuery: pastGrowthQuery, | ||
Past2SeasonQuery: past2GrowthQuery, | ||
Past3SeasonQuery: past3GrowthQuery, | ||
} | ||
} | ||
|
||
type anomalyQueryResults struct { | ||
CurrentPeriodResults []*v3.Result | ||
PastPeriodResults []*v3.Result | ||
CurrentSeasonResults []*v3.Result | ||
PastSeasonResults []*v3.Result | ||
Past2SeasonResults []*v3.Result | ||
Past3SeasonResults []*v3.Result | ||
} |
Oops, something went wrong.