mirror of
https://github.com/grafana/grafana.git
synced 2024-11-29 20:24:18 -06:00
2276e9556a
* set query in rules response * Theme: tweaking dark theme colors (#33007) * Library Panels: Add library panel tab to share modal (#32953) * Explore: Scroll split panes in Explore independently (#32978) * Change default prometheus to latest and prometheus v1 to prometheus1 * Update README * Remove prometheus1 block as not used * Explore: Separatae scrolling in split view * Update snapshot * Allow skip migrations in tests via environment variable (#32958) * Dashboard: Fix issue where Slack notifications won't link to users (#32861) * DashboardPage: refactored styles from sass to emotion (#32955) * DashboardPage: refactored styles from sass to emotion * refactored dashboardPage component to be alot easier to read and understand * more refactoring... * more cleaning... * fixes frontend test * fixes frontend test- I hope * fixes frontend test- I hope * moves dashboard scss styles back to it's standalone file * GraphNG: use theme font family and size for axis labels (#33009) * GraphNG: use theme font family and size for axis labels * fix test * AlertingNG: Slack notification channel (#32675) * AlertingNG: Slack notification channel Signed-off-by: Ganesh Vernekar <ganeshvern@gmail.com> * Add tests Signed-off-by: Ganesh Vernekar <ganeshvern@gmail.com> * Fix review comments Signed-off-by: Ganesh Vernekar <ganeshvern@gmail.com> * Fix review comments and small refactoring Signed-off-by: Ganesh Vernekar <ganeshvern@gmail.com> * GraphNG: stacking (#30749) * First iteration * Dev dash * Re-use StackingMode type * Fix ts and api issues * Stacking work resurected * Fix overrides * Correct values in tooltip and updated test dashboard * Update dev dashboard * Apply correct bands for stacking * Merge fix * Update snapshot * Revert go.sum * Handle null values correctyl and make filleBelowTo and stacking mutual exclusive * Snapshots update * Graph->Time series stacking migration * Review comments * Indicate overrides in StandardEditorContext * Change stacking UI editor, migrate stacking to object option * Small refactor, fix for hiding series and dev dashboard * VizLegend: sets a min and max value of the seriesCount control in Storybook (#33022) * Alerting: Filter rules list (#32818) * Chore: Reduces strict errors (#33012) * Chore: reduces strict error in OptionPicker tests * Chore: reduces strict errors in FormDropdownCtrl * Chore: reduces has no initializer and is not definitely assigned in the constructor errors * Chore: reduces has no initializer and is not definitely assigned in the constructor errors * Chore: lowers strict count limit * Tests: updates snapshots * Tests: updates snapshots * Chore: updates after PR comments * Refactor: removes throw and changes signature for DashboardSrv.getCurrent * [Alerting]: Several modifications in alert rules (#32983) * [Alerting]: Use common properties for all rules * Add Labels in rules * Fix update ruleGroup API Return 400 Bad Request response when the request contains a UID that does not exist * Check permissions and return namespace id * Apply suggestions from code review Co-authored-by: gotjosh <josue@grafana.com> * WIP (#33025) * Chore: Bump strict error count limit (#33035) * set query in rules response Co-authored-by: Torkel Ödegaard <torkel@grafana.org> Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Co-authored-by: Dafydd <72009875+dafydd-t@users.noreply.github.com> Co-authored-by: n-wbrown <n-wbrown@users.noreply.github.com> Co-authored-by: Uchechukwu Obasi <obasiuche62@gmail.com> Co-authored-by: Leon Sorokin <leeoniya@gmail.com> Co-authored-by: Ganesh Vernekar <15064823+codesome@users.noreply.github.com> Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com> Co-authored-by: Nathan Rodman <nathanrodman@gmail.com> Co-authored-by: Hugo Häggmark <hugo.haggmark@grafana.com> Co-authored-by: Sofia Papagiannaki <papagian@users.noreply.github.com> Co-authored-by: gotjosh <josue@grafana.com> Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
160 lines
5.8 KiB
Go
160 lines
5.8 KiB
Go
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
apiv1 "github.com/prometheus/client_golang/api/prometheus/v1"
|
|
|
|
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
|
|
|
apimodels "github.com/grafana/alerting-api/pkg/api"
|
|
"github.com/grafana/grafana/pkg/api/response"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/state"
|
|
)
|
|
|
|
type PrometheusSrv struct {
|
|
log log.Logger
|
|
stateTracker *state.StateTracker
|
|
store store.RuleStore
|
|
}
|
|
|
|
func (srv PrometheusSrv) RouteGetAlertStatuses(c *models.ReqContext) response.Response {
|
|
alertResponse := apimodels.AlertResponse{
|
|
DiscoveryBase: apimodels.DiscoveryBase{
|
|
Status: "success",
|
|
},
|
|
Data: apimodels.AlertDiscovery{
|
|
Alerts: []*apimodels.Alert{},
|
|
},
|
|
}
|
|
for _, alertState := range srv.stateTracker.GetAll() {
|
|
startsAt := alertState.StartsAt
|
|
alertResponse.Data.Alerts = append(alertResponse.Data.Alerts, &apimodels.Alert{
|
|
Labels: map[string]string(alertState.Labels),
|
|
Annotations: map[string]string{}, //TODO: Once annotations are added to the evaluation result, set them here
|
|
State: alertState.State.String(),
|
|
ActiveAt: &startsAt,
|
|
Value: "", //TODO: once the result of the evaluation is added to the evaluation result, set it here
|
|
})
|
|
}
|
|
return response.JSON(http.StatusOK, alertResponse)
|
|
}
|
|
|
|
func (srv PrometheusSrv) RouteGetRuleStatuses(c *models.ReqContext) response.Response {
|
|
ruleResponse := apimodels.RuleResponse{
|
|
DiscoveryBase: apimodels.DiscoveryBase{
|
|
Status: "success",
|
|
},
|
|
Data: apimodels.RuleDiscovery{},
|
|
}
|
|
|
|
ruleGroupQuery := ngmodels.ListOrgRuleGroupsQuery{
|
|
OrgID: c.SignedInUser.OrgId,
|
|
}
|
|
if err := srv.store.GetOrgRuleGroups(&ruleGroupQuery); err != nil {
|
|
ruleResponse.DiscoveryBase.Status = "error"
|
|
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rule groups: %s", err.Error())
|
|
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
|
|
return response.JSON(http.StatusInternalServerError, ruleResponse)
|
|
}
|
|
|
|
for _, r := range ruleGroupQuery.Result {
|
|
if len(r) < 3 {
|
|
continue
|
|
}
|
|
groupId, namespaceUID, namespace := r[0], r[1], r[2]
|
|
alertRuleQuery := ngmodels.ListRuleGroupAlertRulesQuery{OrgID: c.SignedInUser.OrgId, NamespaceUID: namespaceUID, RuleGroup: groupId}
|
|
if err := srv.store.GetRuleGroupAlertRules(&alertRuleQuery); err != nil {
|
|
ruleResponse.DiscoveryBase.Status = "error"
|
|
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rules for group %s: %s", groupId, err.Error())
|
|
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
|
|
return response.JSON(http.StatusInternalServerError, ruleResponse)
|
|
}
|
|
|
|
newGroup := &apimodels.RuleGroup{
|
|
Name: groupId,
|
|
// This doesn't make sense in our architecture
|
|
// so we use this field for passing to the frontend the namespace
|
|
File: namespace,
|
|
LastEvaluation: time.Time{},
|
|
EvaluationTime: 0, // TODO: see if we are able to pass this along with evaluation results
|
|
}
|
|
for _, rule := range alertRuleQuery.Result {
|
|
instanceQuery := ngmodels.ListAlertInstancesQuery{
|
|
DefinitionOrgID: c.SignedInUser.OrgId,
|
|
DefinitionUID: rule.UID,
|
|
}
|
|
if err := srv.store.ListAlertInstances(&instanceQuery); err != nil {
|
|
ruleResponse.DiscoveryBase.Status = "error"
|
|
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting alerts for rule %s: %s", rule.UID, err.Error())
|
|
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
|
|
return response.JSON(http.StatusInternalServerError, ruleResponse)
|
|
}
|
|
|
|
alertingRule := apimodels.AlertingRule{
|
|
State: "inactive",
|
|
Name: rule.Title,
|
|
Query: rule.DataToString(), // TODO: don't escape <>& etc
|
|
Duration: rule.For.Seconds(),
|
|
Annotations: rule.Annotations,
|
|
}
|
|
|
|
newRule := apimodels.Rule{
|
|
Name: rule.Title,
|
|
Labels: nil, // TODO: NG AlertRule does not have labels but does have annotations
|
|
Health: "ok", // TODO: update this in the future when error and noData states are being evaluated and set
|
|
Type: apiv1.RuleTypeAlerting,
|
|
LastEvaluation: time.Time{}, // TODO: set this to be rule evaluation time once it is being set
|
|
EvaluationTime: 0, // TODO: set this once we are saving it or adding it to evaluation results
|
|
}
|
|
for _, instance := range instanceQuery.Result {
|
|
activeAt := instance.CurrentStateSince
|
|
alert := &apimodels.Alert{
|
|
Labels: map[string]string(instance.Labels),
|
|
Annotations: nil, // TODO: set these once they are added to evaluation results
|
|
State: translateInstanceState(instance.CurrentState),
|
|
ActiveAt: &activeAt,
|
|
Value: "", // TODO: set this once it is added to the evaluation results
|
|
}
|
|
if instance.LastEvalTime.After(newRule.LastEvaluation) {
|
|
newRule.LastEvaluation = instance.LastEvalTime
|
|
newGroup.LastEvaluation = instance.LastEvalTime
|
|
}
|
|
switch alert.State {
|
|
case "pending":
|
|
if alertingRule.State == "inactive" {
|
|
alertingRule.State = "pending"
|
|
}
|
|
case "firing":
|
|
alertingRule.State = "firing"
|
|
}
|
|
|
|
alertingRule.Alerts = append(alertingRule.Alerts, alert)
|
|
}
|
|
alertingRule.Rule = newRule
|
|
newGroup.Rules = append(newGroup.Rules, alertingRule)
|
|
newGroup.Interval = float64(rule.IntervalSeconds)
|
|
}
|
|
ruleResponse.Data.RuleGroups = append(ruleResponse.Data.RuleGroups, newGroup)
|
|
}
|
|
return response.JSON(http.StatusOK, ruleResponse)
|
|
}
|
|
|
|
func translateInstanceState(state ngmodels.InstanceStateType) string {
|
|
switch {
|
|
case state == ngmodels.InstanceStateFiring:
|
|
return "firing"
|
|
case state == ngmodels.InstanceStateNormal:
|
|
return "inactive"
|
|
case state == ngmodels.InstanceStatePending:
|
|
return "pending"
|
|
default:
|
|
return "inactive"
|
|
}
|
|
}
|