Exemple #1
0
func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error {
	metrics.M_Alerting_Notification_Sent_PagerDuty.Inc(1)

	if evalContext.Rule.State == m.AlertStateOK && !this.AutoResolve {
		this.log.Info("Not sending a trigger to Pagerduty", "state", evalContext.Rule.State, "auto resolve", this.AutoResolve)
		return nil
	}

	eventType := "trigger"
	if evalContext.Rule.State == m.AlertStateOK {
		eventType = "resolve"
	}

	this.log.Info("Notifying Pagerduty", "event_type", eventType)

	bodyJSON := simplejson.New()
	bodyJSON.Set("service_key", this.Key)
	bodyJSON.Set("description", evalContext.Rule.Name+" - "+evalContext.Rule.Message)
	bodyJSON.Set("client", "Grafana")
	bodyJSON.Set("event_type", eventType)
	bodyJSON.Set("incident_key", "alertId-"+strconv.FormatInt(evalContext.Rule.Id, 10))

	ruleUrl, err := evalContext.GetRuleUrl()
	if err != nil {
		this.log.Error("Failed get rule link", "error", err)
		return err
	}
	bodyJSON.Set("client_url", ruleUrl)

	if evalContext.ImagePublicUrl != "" {
		contexts := make([]interface{}, 1)
		imageJSON := simplejson.New()
		imageJSON.Set("type", "image")
		imageJSON.Set("src", evalContext.ImagePublicUrl)
		contexts[0] = imageJSON
		bodyJSON.Set("contexts", contexts)
	}

	body, _ := bodyJSON.MarshalJSON()

	cmd := &m.SendWebhookSync{
		Url:        pagerdutyEventApiUrl,
		Body:       string(body),
		HttpMethod: "POST",
	}

	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
		this.log.Error("Failed to send notification to Pagerduty", "error", err, "body", string(body))
		return err
	}

	return nil
}
Exemple #2
0
func (this *TelegramNotifier) Notify(evalContext *alerting.EvalContext) error {
	this.log.Info("Sending alert notification to", "bot_token", this.BotToken)
	this.log.Info("Sending alert notification to", "chat_id", this.ChatID)
	metrics.M_Alerting_Notification_Sent_Telegram.Inc(1)

	bodyJSON := simplejson.New()

	bodyJSON.Set("chat_id", this.ChatID)
	bodyJSON.Set("parse_mode", "html")

	message := fmt.Sprintf("%s\nState: %s\nMessage: %s\n", evalContext.GetNotificationTitle(), evalContext.Rule.Name, evalContext.Rule.Message)

	ruleUrl, err := evalContext.GetRuleUrl()
	if err == nil {
		message = message + fmt.Sprintf("URL: %s\n", ruleUrl)
	}
	bodyJSON.Set("text", message)

	url := fmt.Sprintf(telegeramApiUrl, this.BotToken, "sendMessage")
	body, _ := bodyJSON.MarshalJSON()

	cmd := &m.SendWebhookSync{
		Url:        url,
		Body:       string(body),
		HttpMethod: "POST",
	}

	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
		this.log.Error("Failed to send webhook", "error", err, "webhook", this.Name)
		return err
	}

	return nil
}
Exemple #3
0
func (this *WebhookNotifier) Notify(evalContext *alerting.EvalContext) error {
	this.log.Info("Sending webhook")
	metrics.M_Alerting_Notification_Sent_Webhook.Inc(1)

	bodyJSON := simplejson.New()
	bodyJSON.Set("title", evalContext.GetNotificationTitle())
	bodyJSON.Set("ruleId", evalContext.Rule.Id)
	bodyJSON.Set("ruleName", evalContext.Rule.Name)
	bodyJSON.Set("state", evalContext.Rule.State)
	bodyJSON.Set("evalMatches", evalContext.EvalMatches)

	ruleUrl, err := evalContext.GetRuleUrl()
	if err == nil {
		bodyJSON.Set("rule_url", ruleUrl)
	}

	if evalContext.ImagePublicUrl != "" {
		bodyJSON.Set("image_url", evalContext.ImagePublicUrl)
	}

	body, _ := bodyJSON.MarshalJSON()

	cmd := &m.SendWebhookSync{
		Url:      this.Url,
		User:     this.User,
		Password: this.Password,
		Body:     string(body),
	}

	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
		this.log.Error("Failed to send webhook", "error", err, "webhook", this.Name)
	}

	return nil
}
Exemple #4
0
func (e *apiClient) createRequest(query string) (*http.Request, error) {
	u, err := url.Parse(e.Url)
	if err != nil {
		return nil, err
	}

	u.Path = path.Join(u.Path, "query")

	payload := simplejson.New()
	payload.Set("query", query)

	jsonPayload, err := payload.MarshalJSON()
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(string(jsonPayload)))
	if err != nil {
		return nil, err
	}

	req.Header.Set("User-Agent", "Grafana")
	req.Header.Set("Content-Type", "application/json")

	if e.BasicAuth {
		req.SetBasicAuth(e.BasicAuthUser, e.BasicAuthPassword)
	}

	return req, nil
}
Exemple #5
0
func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
	executionError := ""
	annotationData := simplejson.New()

	evalContext.Rule.State = handler.GetStateFromEvaluation(evalContext)

	if evalContext.Error != nil {
		executionError = evalContext.Error.Error()
		annotationData.Set("errorMessage", executionError)
	}

	if evalContext.Firing {
		annotationData = simplejson.NewFromAny(evalContext.EvalMatches)
	}

	countStateResult(evalContext.Rule.State)
	if evalContext.ShouldUpdateAlertState() {
		handler.log.Info("New state change", "alertId", evalContext.Rule.Id, "newState", evalContext.Rule.State, "prev state", evalContext.PrevAlertState)

		cmd := &m.SetAlertStateCommand{
			AlertId:  evalContext.Rule.Id,
			OrgId:    evalContext.Rule.OrgId,
			State:    evalContext.Rule.State,
			Error:    executionError,
			EvalData: annotationData,
		}

		if err := bus.Dispatch(cmd); err != nil {
			handler.log.Error("Failed to save state", "error", err)
		}

		// save annotation
		item := annotations.Item{
			OrgId:       evalContext.Rule.OrgId,
			DashboardId: evalContext.Rule.DashboardId,
			PanelId:     evalContext.Rule.PanelId,
			Type:        annotations.AlertType,
			AlertId:     evalContext.Rule.Id,
			Title:       evalContext.Rule.Name,
			Text:        evalContext.GetStateModel().Text,
			NewState:    string(evalContext.Rule.State),
			PrevState:   string(evalContext.PrevAlertState),
			Epoch:       time.Now().Unix(),
			Data:        annotationData,
		}

		annotationRepo := annotations.GetRepository()
		if err := annotationRepo.Save(&item); err != nil {
			handler.log.Error("Failed to save annotation for new alert state", "error", err)
		}

		if evalContext.ShouldSendNotification() {
			handler.notifier.Notify(evalContext)
		}
	}

	return nil
}
Exemple #6
0
// NewDashboard creates a new dashboard
func NewDashboard(title string) *Dashboard {
	dash := &Dashboard{}
	dash.Data = simplejson.New()
	dash.Data.Set("title", title)
	dash.Title = title
	dash.Created = time.Now()
	dash.Updated = time.Now()
	dash.UpdateSlug()
	return dash
}
Exemple #7
0
func (this *SensuNotifier) Notify(evalContext *alerting.EvalContext) error {
	this.log.Info("Sending sensu result")
	metrics.M_Alerting_Notification_Sent_Sensu.Inc(1)

	bodyJSON := simplejson.New()
	bodyJSON.Set("ruleId", evalContext.Rule.Id)
	// Sensu alerts cannot have spaces in them
	bodyJSON.Set("name", strings.Replace(evalContext.Rule.Name, " ", "_", -1))
	// Sensu alerts require a command
	// We set it to the grafana ruleID
	bodyJSON.Set("source", "grafana_rule_"+strconv.FormatInt(evalContext.Rule.Id, 10))
	// Finally, sensu expects an output
	// We set it to a default output
	bodyJSON.Set("output", "Grafana Metric Condition Met")
	bodyJSON.Set("evalMatches", evalContext.EvalMatches)

	if evalContext.Rule.State == "alerting" {
		bodyJSON.Set("status", 2)
	} else if evalContext.Rule.State == "no_data" {
		bodyJSON.Set("status", 1)
	} else {
		bodyJSON.Set("status", 0)
	}

	ruleUrl, err := evalContext.GetRuleUrl()
	if err == nil {
		bodyJSON.Set("ruleUrl", ruleUrl)
	}

	if evalContext.ImagePublicUrl != "" {
		bodyJSON.Set("imageUrl", evalContext.ImagePublicUrl)
	}

	if evalContext.Rule.Message != "" {
		bodyJSON.Set("message", evalContext.Rule.Message)
	}

	body, _ := bodyJSON.MarshalJSON()

	cmd := &m.SendWebhookSync{
		Url:        this.Url,
		User:       this.User,
		Password:   this.Password,
		Body:       string(body),
		HttpMethod: "POST",
	}

	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
		this.log.Error("Failed to send sensu event", "error", err, "sensu", this.Name)
		return err
	}

	return nil
}
Exemple #8
0
func TestPluginDashboards(t *testing.T) {

	Convey("When asking plugin dashboard info", t, func() {
		setting.Cfg = ini.Empty()
		sec, _ := setting.Cfg.NewSection("plugin.test-app")
		sec.NewKey("path", "../../tests/test-app")
		err := Init()

		So(err, ShouldBeNil)

		bus.AddHandler("test", func(query *m.GetDashboardQuery) error {
			if query.Slug == "nginx-connections" {
				dash := m.NewDashboard("Nginx Connections")
				dash.Data.Set("revision", "1.1")
				query.Result = dash
				return nil
			}

			return m.ErrDashboardNotFound
		})

		bus.AddHandler("test", func(query *m.GetDashboardsByPluginIdQuery) error {
			var data = simplejson.New()
			data.Set("title", "Nginx Connections")
			data.Set("revision", 22)

			query.Result = []*m.Dashboard{
				{Slug: "nginx-connections", Data: data},
			}
			return nil
		})

		dashboards, err := GetPluginDashboards(1, "test-app")

		So(err, ShouldBeNil)

		Convey("should return 2 dashboarrd", func() {
			So(len(dashboards), ShouldEqual, 2)
		})

		Convey("should include installed version info", func() {
			So(dashboards[0].Title, ShouldEqual, "Nginx Connections")
			So(dashboards[0].Revision, ShouldEqual, 25)
			So(dashboards[0].ImportedRevision, ShouldEqual, 22)
			So(dashboards[0].ImportedUri, ShouldEqual, "db/nginx-connections")

			So(dashboards[1].Revision, ShouldEqual, 2)
			So(dashboards[1].ImportedRevision, ShouldEqual, 0)
		})
	})

}
Exemple #9
0
func (this *OpsGenieNotifier) createAlert(evalContext *alerting.EvalContext) error {
	this.log.Info("Creating OpsGenie alert", "ruleId", evalContext.Rule.Id, "notification", this.Name)

	ruleUrl, err := evalContext.GetRuleUrl()
	if err != nil {
		this.log.Error("Failed get rule link", "error", err)
		return err
	}

	bodyJSON := simplejson.New()
	bodyJSON.Set("apiKey", this.ApiKey)
	bodyJSON.Set("message", evalContext.Rule.Name)
	bodyJSON.Set("source", "Grafana")
	bodyJSON.Set("alias", "alertId-"+strconv.FormatInt(evalContext.Rule.Id, 10))
	bodyJSON.Set("description", fmt.Sprintf("%s - %s\n%s", evalContext.Rule.Name, ruleUrl, evalContext.Rule.Message))

	details := simplejson.New()
	details.Set("url", ruleUrl)
	if evalContext.ImagePublicUrl != "" {
		details.Set("image", evalContext.ImagePublicUrl)
	}

	bodyJSON.Set("details", details)
	body, _ := bodyJSON.MarshalJSON()

	cmd := &m.SendWebhookSync{
		Url:        opsgenieCreateAlertURL,
		Body:       string(body),
		HttpMethod: "POST",
	}

	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
		this.log.Error("Failed to send notification to OpsGenie", "error", err, "body", string(body))
	}

	return nil
}
func TestTokenClient(t *testing.T) {
	SkipConvey("Token client", t, func() {
		dsInfo := &models.DataSource{
			JsonData: simplejson.New(),
			Url:      "",
		}

		client := NewTokenClient(dsInfo)

		body, err := client.RequestTokenData(context.TODO())

		So(err, ShouldBeNil)
		//So(len(body.Functions), ShouldBeGreaterThan, 1)
		So(len(body.Metrics), ShouldBeGreaterThan, 1)
	})
}
Exemple #11
0
func (this *OpsGenieNotifier) closeAlert(evalContext *alerting.EvalContext) error {
	this.log.Info("Closing OpsGenie alert", "ruleId", evalContext.Rule.Id, "notification", this.Name)

	bodyJSON := simplejson.New()
	bodyJSON.Set("apiKey", this.ApiKey)
	bodyJSON.Set("alias", "alertId-"+strconv.FormatInt(evalContext.Rule.Id, 10))
	body, _ := bodyJSON.MarshalJSON()

	cmd := &m.SendWebhookSync{
		Url:        opsgenieCloseAlertURL,
		Body:       string(body),
		HttpMethod: "POST",
	}

	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
		this.log.Error("Failed to send notification to OpsGenie", "error", err, "body", string(body))
	}

	return nil
}
Exemple #12
0
func (this *DashTemplateEvaluator) Eval() (*simplejson.Json, error) {
	this.result = simplejson.New()
	this.variables = make(map[string]string)
	this.varRegex, _ = regexp.Compile(`(\$\{\w+\})`)

	// check that we have all inputs we need
	for _, inputDef := range this.template.Get("__inputs").MustArray() {
		inputDefJson := simplejson.NewFromAny(inputDef)
		inputName := inputDefJson.Get("name").MustString()
		inputType := inputDefJson.Get("type").MustString()
		input := this.findInput(inputName, inputType)

		if input == nil {
			return nil, &DashboardInputMissingError{VariableName: inputName}
		}

		this.variables["${"+inputName+"}"] = input.Value
	}

	return simplejson.NewFromAny(this.evalObject(this.template)), nil
}
Exemple #13
0
func TestDashboardModel(t *testing.T) {

	Convey("When generating slug", t, func() {
		dashboard := NewDashboard("Grafana Play Home")
		dashboard.UpdateSlug()

		So(dashboard.Slug, ShouldEqual, "grafana-play-home")
	})

	Convey("Given a dashboard json", t, func() {
		json := simplejson.New()
		json.Set("title", "test dash")

		Convey("With tags as string value", func() {
			json.Set("tags", "")
			dash := NewDashboardFromJson(json)

			So(len(dash.GetTags()), ShouldEqual, 0)
		})
	})

}
Exemple #14
0
func TestMQEQueryParser(t *testing.T) {
	Convey("MQE query parser", t, func() {
		parser := &QueryParser{}

		dsInfo := &models.DataSource{JsonData: simplejson.New()}
		queryContext := &tsdb.QueryContext{}

		Convey("can parse simple mqe model", func() {
			json := `
      {
        "cluster": [],
        "hosts": [
          "staples-lab-1"
        ],
        "metrics": [
          {
            "metric": "os.cpu.all*"
          }
        ],
        "rawQuery": "",
        "refId": "A"
      }
      `
			modelJson, err := simplejson.NewJson([]byte(json))
			So(err, ShouldBeNil)

			query, err := parser.Parse(modelJson, dsInfo, queryContext)
			So(err, ShouldBeNil)
			So(query.UseRawQuery, ShouldBeFalse)

			So(len(query.Cluster), ShouldEqual, 0)
			So(query.Hosts[0], ShouldEqual, "staples-lab-1")
			So(query.Metrics[0].Metric, ShouldEqual, "os.cpu.all*")
		})

		Convey("can parse multi serie mqe model", func() {
			json := `
      {
        "cluster": [
          "demoapp"
        ],
        "hosts": [
          "staples-lab-1"
        ],
        "metrics": [
          {
            "metric": "os.cpu.all.active_percentage"
          },
          {
            "metric": "os.disk.sda.io_time"
          }
        ],
        "functionList": [
          {
            "func": "aggregate.min"
          },
          {
             "func": "aggregate.max"
          }
        ],
        "rawQuery": "",
        "refId": "A",
        "addClusterToAlias": true,
        "addHostToAlias": true
      }
      `
			modelJson, err := simplejson.NewJson([]byte(json))
			So(err, ShouldBeNil)

			query, err := parser.Parse(modelJson, dsInfo, queryContext)
			So(err, ShouldBeNil)
			So(query.UseRawQuery, ShouldBeFalse)
			So(query.Cluster[0], ShouldEqual, "demoapp")
			So(query.Metrics[0].Metric, ShouldEqual, "os.cpu.all.active_percentage")
			So(query.Metrics[1].Metric, ShouldEqual, "os.disk.sda.io_time")
			So(query.FunctionList[0].Func, ShouldEqual, "aggregate.min")
			So(query.FunctionList[1].Func, ShouldEqual, "aggregate.max")
		})

		Convey("can parse raw query", func() {
			json := `
      {
        "addClusterToAlias": true,
        "addHostToAlias": true,
        "cluster": [],
        "hosts": [
          "staples-lab-1"
        ],
        "metrics": [
          {
            "alias": "cpu active",
            "metric": "os.cpu.all.active_percentage"
          },
          {
            "alias": "disk sda time",
            "metric": "os.disk.sda.io_time"
          }
        ],
        "rawQuery": true,
        "query": "raw-query",
        "refId": "A"
      }
      `
			modelJson, err := simplejson.NewJson([]byte(json))
			So(err, ShouldBeNil)

			query, err := parser.Parse(modelJson, dsInfo, queryContext)
			So(err, ShouldBeNil)

			So(query.UseRawQuery, ShouldBeTrue)
			So(query.RawQuery, ShouldEqual, "raw-query")
			So(query.AddClusterToAlias, ShouldBeTrue)
			So(query.AddHostToAlias, ShouldBeTrue)
		})
	})
}
Exemple #15
0
func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
	oldState := evalContext.Rule.State

	executionError := ""
	annotationData := simplejson.New()
	if evalContext.Error != nil {
		handler.log.Error("Alert Rule Result Error", "ruleId", evalContext.Rule.Id, "error", evalContext.Error)
		evalContext.Rule.State = m.AlertStateExecError
		executionError = evalContext.Error.Error()
		annotationData.Set("errorMessage", executionError)
	} else if evalContext.Firing {
		evalContext.Rule.State = m.AlertStateAlerting
		annotationData = simplejson.NewFromAny(evalContext.EvalMatches)
	} else {
		if evalContext.NoDataFound {
			if evalContext.Rule.NoDataState != m.NoDataKeepState {
				evalContext.Rule.State = evalContext.Rule.NoDataState.ToAlertState()
			}
		} else {
			evalContext.Rule.State = m.AlertStateOK
		}
	}

	countStateResult(evalContext.Rule.State)
	if handler.shouldUpdateAlertState(evalContext, oldState) {
		handler.log.Info("New state change", "alertId", evalContext.Rule.Id, "newState", evalContext.Rule.State, "oldState", oldState)

		cmd := &m.SetAlertStateCommand{
			AlertId:  evalContext.Rule.Id,
			OrgId:    evalContext.Rule.OrgId,
			State:    evalContext.Rule.State,
			Error:    executionError,
			EvalData: annotationData,
		}

		if err := bus.Dispatch(cmd); err != nil {
			handler.log.Error("Failed to save state", "error", err)
		}

		// save annotation
		item := annotations.Item{
			OrgId:       evalContext.Rule.OrgId,
			DashboardId: evalContext.Rule.DashboardId,
			PanelId:     evalContext.Rule.PanelId,
			Type:        annotations.AlertType,
			AlertId:     evalContext.Rule.Id,
			Title:       evalContext.Rule.Name,
			Text:        evalContext.GetStateModel().Text,
			NewState:    string(evalContext.Rule.State),
			PrevState:   string(oldState),
			Epoch:       time.Now().Unix(),
			Data:        annotationData,
		}

		annotationRepo := annotations.GetRepository()
		if err := annotationRepo.Save(&item); err != nil {
			handler.log.Error("Failed to save annotation for new alert state", "error", err)
		}

		if (oldState == m.AlertStatePending) && (evalContext.Rule.State == m.AlertStateOK) {
			handler.log.Info("Notfication not sent", "oldState", oldState, "newState", evalContext.Rule.State)
		} else {
			handler.notifier.Notify(evalContext)
		}

	}

	return nil
}
func TestInfluxdbQueryParser(t *testing.T) {
	Convey("Influxdb query parser", t, func() {

		parser := &InfluxdbQueryParser{}
		dsInfo := &tsdb.DataSourceInfo{
			JsonData: simplejson.New(),
		}

		Convey("can parse influxdb json model", func() {
			json := `
        {
        "dsType": "influxdb",
        "groupBy": [
          {
            "params": [
              "$interval"
            ],
            "type": "time"
          },
          {
            "params": [
              "datacenter"
            ],
            "type": "tag"
          },
          {
            "params": [
              "none"
            ],
            "type": "fill"
          }
        ],
        "measurement": "logins.count",
        "policy": "default",
        "refId": "B",
        "resultFormat": "time_series",
        "select": [
          [
            {
              "type": "field",
              "params": [
                "value"
              ]
            },
            {
              "type": "count",
              "params": []
            }
          ],
          [
            {
              "type": "field",
              "params": [
                "value"
              ]
            },
            {
              "type": "bottom",
              "params": [
                3
              ]
            }
          ],
          [
            {
              "type": "field",
              "params": [
                "value"
              ]
            },
            {
              "type": "mean",
              "params": []
            },
            {
              "type": "math",
              "params": [
                " / 100"
              ]
            }
          ]
        ],
        "alias": "serie alias",
        "tags": [
          {
            "key": "datacenter",
            "operator": "=",
            "value": "America"
          },
          {
            "condition": "OR",
            "key": "hostname",
            "operator": "=",
            "value": "server1"
          }
        ]
      }
      `
			dsInfo.JsonData.Set("timeInterval", ">20s")
			modelJson, err := simplejson.NewJson([]byte(json))
			So(err, ShouldBeNil)

			res, err := parser.Parse(modelJson, dsInfo)
			So(err, ShouldBeNil)
			So(len(res.GroupBy), ShouldEqual, 3)
			So(len(res.Selects), ShouldEqual, 3)
			So(len(res.Tags), ShouldEqual, 2)
			So(res.Interval, ShouldEqual, ">20s")
			So(res.Alias, ShouldEqual, "serie alias")
		})

		Convey("can part raw query json model", func() {
			json := `
      {
        "dsType": "influxdb",
        "groupBy": [
          {
            "params": [
              "$interval"
            ],
            "type": "time"
          },
          {
            "params": [
              "null"
            ],
            "type": "fill"
          }
        ],
        "interval": ">10s",
        "policy": "default",
        "query": "RawDummieQuery",
        "rawQuery": true,
        "refId": "A",
        "resultFormat": "time_series",
        "select": [
          [
            {
              "params": [
                "value"
              ],
              "type": "field"
            },
            {
              "params": [

              ],
              "type": "mean"
            }
          ]
        ],
        "tags": [

        ]
      }
      `

			modelJson, err := simplejson.NewJson([]byte(json))
			So(err, ShouldBeNil)

			res, err := parser.Parse(modelJson, dsInfo)
			So(err, ShouldBeNil)
			So(res.RawQuery, ShouldEqual, "RawDummieQuery")
			So(len(res.GroupBy), ShouldEqual, 2)
			So(len(res.Selects), ShouldEqual, 1)
			So(len(res.Tags), ShouldEqual, 0)
			So(res.Interval, ShouldEqual, ">10s")
		})
	})
}
func TestDataSourceCache(t *testing.T) {
	Convey("When caching a datasource proxy", t, func() {
		clearCache()
		ds := DataSource{
			Id:   1,
			Url:  "http://k8s:8001",
			Type: "Kubernetes",
		}

		t1, err := ds.GetHttpTransport()
		So(err, ShouldBeNil)

		t2, err := ds.GetHttpTransport()
		So(err, ShouldBeNil)

		Convey("Should be using the cached proxy", func() {
			So(t2, ShouldEqual, t1)
		})
	})

	Convey("When getting kubernetes datasource proxy", t, func() {
		clearCache()
		setting.SecretKey = "password"

		json := simplejson.New()
		json.Set("tlsAuth", true)
		json.Set("tlsAuthWithCACert", true)

		t := time.Now()
		ds := DataSource{
			Url:     "http://k8s:8001",
			Type:    "Kubernetes",
			Updated: t.Add(-2 * time.Minute),
		}

		transport, err := ds.GetHttpTransport()
		So(err, ShouldBeNil)

		Convey("Should have no cert", func() {
			So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, true)
		})

		ds.JsonData = json
		ds.SecureJsonData = map[string][]byte{
			"tlsCACert":     util.Encrypt([]byte(caCert), "password"),
			"tlsClientCert": util.Encrypt([]byte(clientCert), "password"),
			"tlsClientKey":  util.Encrypt([]byte(clientKey), "password"),
		}
		ds.Updated = t.Add(-1 * time.Minute)

		transport, err = ds.GetHttpTransport()
		So(err, ShouldBeNil)

		Convey("Should add cert", func() {
			So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, false)
			So(len(transport.TLSClientConfig.Certificates), ShouldEqual, 1)
		})

		ds.JsonData = nil
		ds.SecureJsonData = map[string][]byte{}
		ds.Updated = t

		transport, err = ds.GetHttpTransport()
		So(err, ShouldBeNil)

		Convey("Should remove cert", func() {
			So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, true)
			So(len(transport.TLSClientConfig.Certificates), ShouldEqual, 0)
		})
	})
}
func TestAlertNotificationSQLAccess(t *testing.T) {
	Convey("Testing Alert notification sql access", t, func() {
		InitTestDB(t)
		var err error

		Convey("Alert notifications should be empty", func() {
			cmd := &m.GetAlertNotificationsQuery{
				OrgId: 2,
				Name:  "email",
			}

			err := GetAlertNotifications(cmd)
			fmt.Printf("errror %v", err)
			So(err, ShouldBeNil)
			So(cmd.Result, ShouldBeNil)
		})

		Convey("Can save Alert Notification", func() {
			cmd := &m.CreateAlertNotificationCommand{
				Name:     "ops",
				Type:     "email",
				OrgId:    1,
				Settings: simplejson.New(),
			}

			err = CreateAlertNotificationCommand(cmd)
			So(err, ShouldBeNil)
			So(cmd.Result.Id, ShouldNotEqual, 0)
			So(cmd.Result.OrgId, ShouldNotEqual, 0)
			So(cmd.Result.Type, ShouldEqual, "email")

			Convey("Cannot save Alert Notification with the same name", func() {
				err = CreateAlertNotificationCommand(cmd)
				So(err, ShouldNotBeNil)
			})

			Convey("Can update alert notification", func() {
				newCmd := &m.UpdateAlertNotificationCommand{
					Name:     "NewName",
					Type:     "webhook",
					OrgId:    cmd.Result.OrgId,
					Settings: simplejson.New(),
					Id:       cmd.Result.Id,
				}
				err := UpdateAlertNotification(newCmd)
				So(err, ShouldBeNil)
				So(newCmd.Result.Name, ShouldEqual, "NewName")
			})
		})

		Convey("Can search using an array of ids", func() {
			cmd1 := m.CreateAlertNotificationCommand{Name: "nagios", Type: "webhook", OrgId: 1, Settings: simplejson.New()}
			cmd2 := m.CreateAlertNotificationCommand{Name: "slack", Type: "webhook", OrgId: 1, Settings: simplejson.New()}
			cmd3 := m.CreateAlertNotificationCommand{Name: "ops2", Type: "email", OrgId: 1, Settings: simplejson.New()}
			cmd4 := m.CreateAlertNotificationCommand{IsDefault: true, Name: "default", Type: "email", OrgId: 1, Settings: simplejson.New()}

			otherOrg := m.CreateAlertNotificationCommand{Name: "default", Type: "email", OrgId: 2, Settings: simplejson.New()}

			So(CreateAlertNotificationCommand(&cmd1), ShouldBeNil)
			So(CreateAlertNotificationCommand(&cmd2), ShouldBeNil)
			So(CreateAlertNotificationCommand(&cmd3), ShouldBeNil)
			So(CreateAlertNotificationCommand(&cmd4), ShouldBeNil)
			So(CreateAlertNotificationCommand(&otherOrg), ShouldBeNil)

			Convey("search", func() {
				query := &m.GetAlertNotificationsToSendQuery{
					Ids:   []int64{cmd1.Result.Id, cmd2.Result.Id, 112341231},
					OrgId: 1,
				}

				err := GetAlertNotificationsToSend(query)
				So(err, ShouldBeNil)
				So(len(query.Result), ShouldEqual, 3)
			})

			Convey("all", func() {
				query := &m.GetAllAlertNotificationsQuery{
					OrgId: 1,
				}

				err := GetAllAlertNotifications(query)
				So(err, ShouldBeNil)
				So(len(query.Result), ShouldEqual, 4)
			})
		})
	})
}
Exemple #19
0
func TestOpenTsdbExecutor(t *testing.T) {
	Convey("OpenTsdb query testing", t, func() {

		exec := &OpenTsdbExecutor{}

		Convey("Build metric with downsampling enabled", func() {

			query := &tsdb.Query{
				Model: simplejson.New(),
			}

			query.Model.Set("metric", "cpu.average.percent")
			query.Model.Set("aggregator", "avg")
			query.Model.Set("disableDownsampling", false)
			query.Model.Set("downsampleInterval", "")
			query.Model.Set("downsampleAggregator", "avg")
			query.Model.Set("downsampleFillPolicy", "none")

			metric := exec.buildMetric(query)

			So(len(metric), ShouldEqual, 3)
			So(metric["metric"], ShouldEqual, "cpu.average.percent")
			So(metric["aggregator"], ShouldEqual, "avg")
			So(metric["downsample"], ShouldEqual, "1m-avg")

		})

		Convey("Build metric with downsampling diabled", func() {

			query := &tsdb.Query{
				Model: simplejson.New(),
			}

			query.Model.Set("metric", "cpu.average.percent")
			query.Model.Set("aggregator", "avg")
			query.Model.Set("disableDownsampling", true)
			query.Model.Set("downsampleInterval", "")
			query.Model.Set("downsampleAggregator", "avg")
			query.Model.Set("downsampleFillPolicy", "none")

			metric := exec.buildMetric(query)

			So(len(metric), ShouldEqual, 2)
			So(metric["metric"], ShouldEqual, "cpu.average.percent")
			So(metric["aggregator"], ShouldEqual, "avg")

		})

		Convey("Build metric with downsampling enabled with params", func() {

			query := &tsdb.Query{
				Model: simplejson.New(),
			}

			query.Model.Set("metric", "cpu.average.percent")
			query.Model.Set("aggregator", "avg")
			query.Model.Set("disableDownsampling", false)
			query.Model.Set("downsampleInterval", "5m")
			query.Model.Set("downsampleAggregator", "sum")
			query.Model.Set("downsampleFillPolicy", "null")

			metric := exec.buildMetric(query)

			So(len(metric), ShouldEqual, 3)
			So(metric["metric"], ShouldEqual, "cpu.average.percent")
			So(metric["aggregator"], ShouldEqual, "avg")
			So(metric["downsample"], ShouldEqual, "5m-sum-null")
		})

		Convey("Build metric with tags with downsampling disabled", func() {

			query := &tsdb.Query{
				Model: simplejson.New(),
			}

			query.Model.Set("metric", "cpu.average.percent")
			query.Model.Set("aggregator", "avg")
			query.Model.Set("disableDownsampling", true)
			query.Model.Set("downsampleInterval", "5m")
			query.Model.Set("downsampleAggregator", "sum")
			query.Model.Set("downsampleFillPolicy", "null")

			tags := simplejson.New()
			tags.Set("env", "prod")
			tags.Set("app", "grafana")
			query.Model.Set("tags", tags.MustMap())

			metric := exec.buildMetric(query)

			So(len(metric), ShouldEqual, 3)
			So(metric["metric"], ShouldEqual, "cpu.average.percent")
			So(metric["aggregator"], ShouldEqual, "avg")
			So(metric["downsample"], ShouldEqual, nil)
			So(len(metric["tags"].(map[string]interface{})), ShouldEqual, 2)
			So(metric["tags"].(map[string]interface{})["env"], ShouldEqual, "prod")
			So(metric["tags"].(map[string]interface{})["app"], ShouldEqual, "grafana")
			So(metric["tags"].(map[string]interface{})["ip"], ShouldEqual, nil)
		})

		Convey("Build metric with rate enabled but counter disabled", func() {

			query := &tsdb.Query{
				Model: simplejson.New(),
			}

			query.Model.Set("metric", "cpu.average.percent")
			query.Model.Set("aggregator", "avg")
			query.Model.Set("disableDownsampling", true)
			query.Model.Set("shouldComputeRate", true)
			query.Model.Set("isCounter", false)

			tags := simplejson.New()
			tags.Set("env", "prod")
			tags.Set("app", "grafana")
			query.Model.Set("tags", tags.MustMap())

			metric := exec.buildMetric(query)

			So(len(metric), ShouldEqual, 5)
			So(metric["metric"], ShouldEqual, "cpu.average.percent")
			So(metric["aggregator"], ShouldEqual, "avg")
			So(len(metric["tags"].(map[string]interface{})), ShouldEqual, 2)
			So(metric["tags"].(map[string]interface{})["env"], ShouldEqual, "prod")
			So(metric["tags"].(map[string]interface{})["app"], ShouldEqual, "grafana")
			So(metric["tags"].(map[string]interface{})["ip"], ShouldEqual, nil)
			So(metric["rate"], ShouldEqual, true)
			So(metric["rateOptions"].(map[string]interface{})["counter"], ShouldEqual, false)
		})

		Convey("Build metric with rate and counter enabled", func() {

			query := &tsdb.Query{
				Model: simplejson.New(),
			}

			query.Model.Set("metric", "cpu.average.percent")
			query.Model.Set("aggregator", "avg")
			query.Model.Set("disableDownsampling", true)
			query.Model.Set("shouldComputeRate", true)
			query.Model.Set("isCounter", true)
			query.Model.Set("counterMax", 45)
			query.Model.Set("counterResetValue", 60)

			tags := simplejson.New()
			tags.Set("env", "prod")
			tags.Set("app", "grafana")
			query.Model.Set("tags", tags.MustMap())

			metric := exec.buildMetric(query)

			So(len(metric), ShouldEqual, 5)
			So(metric["metric"], ShouldEqual, "cpu.average.percent")
			So(metric["aggregator"], ShouldEqual, "avg")
			So(len(metric["tags"].(map[string]interface{})), ShouldEqual, 2)
			So(metric["tags"].(map[string]interface{})["env"], ShouldEqual, "prod")
			So(metric["tags"].(map[string]interface{})["app"], ShouldEqual, "grafana")
			So(metric["tags"].(map[string]interface{})["ip"], ShouldEqual, nil)
			So(metric["rate"], ShouldEqual, true)
			So(len(metric["rateOptions"].(map[string]interface{})), ShouldEqual, 3)
			So(metric["rateOptions"].(map[string]interface{})["counter"], ShouldEqual, true)
			So(metric["rateOptions"].(map[string]interface{})["counterMax"], ShouldEqual, 45)
			So(metric["rateOptions"].(map[string]interface{})["resetValue"], ShouldEqual, 60)
		})

	})
}
Exemple #20
0
func TestDataSourceProxy(t *testing.T) {

	Convey("When getting graphite datasource proxy", t, func() {
		ds := m.DataSource{Url: "htttp://graphite:8080", Type: m.DS_GRAPHITE}
		targetUrl, err := url.Parse(ds.Url)
		proxy := NewReverseProxy(&ds, "/render", targetUrl)
		proxy.Transport, err = DataProxyTransport(&ds)
		So(err, ShouldBeNil)

		transport, ok := proxy.Transport.(*http.Transport)
		So(ok, ShouldBeTrue)
		So(transport.TLSClientConfig.InsecureSkipVerify, ShouldBeTrue)

		requestUrl, _ := url.Parse("http://grafana.com/sub")
		req := http.Request{URL: requestUrl}

		proxy.Director(&req)

		Convey("Can translate request url and path", func() {
			So(req.URL.Host, ShouldEqual, "graphite:8080")
			So(req.URL.Path, ShouldEqual, "/render")
		})
	})

	Convey("When getting influxdb datasource proxy", t, func() {
		ds := m.DataSource{
			Type:     m.DS_INFLUXDB_08,
			Url:      "http://influxdb:8083",
			Database: "site",
			User:     "******",
			Password: "******",
		}

		targetUrl, _ := url.Parse(ds.Url)
		proxy := NewReverseProxy(&ds, "", targetUrl)

		requestUrl, _ := url.Parse("http://grafana.com/sub")
		req := http.Request{URL: requestUrl}

		proxy.Director(&req)

		Convey("Should add db to url", func() {
			So(req.URL.Path, ShouldEqual, "/db/site/")
		})

		Convey("Should add username and password", func() {
			queryVals := req.URL.Query()
			So(queryVals["u"][0], ShouldEqual, "user")
			So(queryVals["p"][0], ShouldEqual, "password")
		})
	})

	Convey("When getting kubernetes datasource proxy", t, func() {
		setting.SecretKey = "password"

		json := simplejson.New()
		json.Set("tlsAuth", true)
		json.Set("tlsAuthWithCACert", true)
		ds := m.DataSource{
			Url:      "htttp://k8s:8001",
			Type:     "Kubernetes",
			JsonData: json,
			SecureJsonData: map[string][]byte{
				"tlsCACert":     util.Encrypt([]byte(caCert), "password"),
				"tlsClientCert": util.Encrypt([]byte(clientCert), "password"),
				"tlsClientKey":  util.Encrypt([]byte(clientKey), "password"),
			},
		}
		targetUrl, err := url.Parse(ds.Url)
		proxy := NewReverseProxy(&ds, "", targetUrl)
		proxy.Transport, err = DataProxyTransport(&ds)
		So(err, ShouldBeNil)

		transport, ok := proxy.Transport.(*http.Transport)

		Convey("Should add cert", func() {
			So(ok, ShouldBeTrue)
			So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, false)
			So(len(transport.TLSClientConfig.Certificates), ShouldEqual, 1)
		})
	})

}
Exemple #21
0
func TestAlertingDataAccess(t *testing.T) {
	Convey("Testing Alerting data access", t, func() {
		InitTestDB(t)

		testDash := insertTestDashboard("dashboard with alerts", 1, "alert")

		items := []*m.Alert{
			{
				PanelId:     1,
				DashboardId: testDash.Id,
				OrgId:       testDash.OrgId,
				Name:        "Alerting title",
				Message:     "Alerting message",
				Settings:    simplejson.New(),
				Frequency:   1,
			},
		}

		cmd := m.SaveAlertsCommand{
			Alerts:      items,
			DashboardId: testDash.Id,
			OrgId:       1,
			UserId:      1,
		}

		err := SaveAlerts(&cmd)

		Convey("Can create one alert", func() {
			So(err, ShouldBeNil)
		})

		Convey("Can read properties", func() {
			alertQuery := m.GetAlertsQuery{DashboardId: testDash.Id, PanelId: 1, OrgId: 1}
			err2 := HandleAlertsQuery(&alertQuery)

			alert := alertQuery.Result[0]
			So(err2, ShouldBeNil)
			So(alert.Name, ShouldEqual, "Alerting title")
			So(alert.Message, ShouldEqual, "Alerting message")
			So(alert.State, ShouldEqual, "no_data")
			So(alert.Frequency, ShouldEqual, 1)
		})

		Convey("Alerts with same dashboard id and panel id should update", func() {
			modifiedItems := items
			modifiedItems[0].Name = "Name"

			modifiedCmd := m.SaveAlertsCommand{
				DashboardId: testDash.Id,
				OrgId:       1,
				UserId:      1,
				Alerts:      modifiedItems,
			}

			err := SaveAlerts(&modifiedCmd)

			Convey("Can save alerts with same dashboard and panel id", func() {
				So(err, ShouldBeNil)
			})

			Convey("Alerts should be updated", func() {
				query := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1}
				err2 := HandleAlertsQuery(&query)

				So(err2, ShouldBeNil)
				So(len(query.Result), ShouldEqual, 1)
				So(query.Result[0].Name, ShouldEqual, "Name")

				Convey("Alert state should not be updated", func() {
					So(query.Result[0].State, ShouldEqual, "no_data")
				})
			})

			Convey("Updates without changes should be ignored", func() {
				err3 := SaveAlerts(&modifiedCmd)
				So(err3, ShouldBeNil)
			})
		})

		Convey("Multiple alerts per dashboard", func() {
			multipleItems := []*m.Alert{
				{
					DashboardId: testDash.Id,
					PanelId:     1,
					Name:        "1",
					OrgId:       1,
					Settings:    simplejson.New(),
				},
				{
					DashboardId: testDash.Id,
					PanelId:     2,
					Name:        "2",
					OrgId:       1,
					Settings:    simplejson.New(),
				},
				{
					DashboardId: testDash.Id,
					PanelId:     3,
					Name:        "3",
					OrgId:       1,
					Settings:    simplejson.New(),
				},
			}

			cmd.Alerts = multipleItems
			err = SaveAlerts(&cmd)

			Convey("Should save 3 dashboards", func() {
				So(err, ShouldBeNil)

				queryForDashboard := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1}
				err2 := HandleAlertsQuery(&queryForDashboard)

				So(err2, ShouldBeNil)
				So(len(queryForDashboard.Result), ShouldEqual, 3)
			})

			Convey("should updated two dashboards and delete one", func() {
				missingOneAlert := multipleItems[:2]

				cmd.Alerts = missingOneAlert
				err = SaveAlerts(&cmd)

				Convey("should delete the missing alert", func() {
					query := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1}
					err2 := HandleAlertsQuery(&query)
					So(err2, ShouldBeNil)
					So(len(query.Result), ShouldEqual, 2)
				})
			})
		})

		Convey("When dashboard is removed", func() {
			items := []*m.Alert{
				{
					PanelId:     1,
					DashboardId: testDash.Id,
					Name:        "Alerting title",
					Message:     "Alerting message",
				},
			}

			cmd := m.SaveAlertsCommand{
				Alerts:      items,
				DashboardId: testDash.Id,
				OrgId:       1,
				UserId:      1,
			}

			SaveAlerts(&cmd)

			err = DeleteDashboard(&m.DeleteDashboardCommand{
				OrgId: 1,
				Slug:  testDash.Slug,
			})

			So(err, ShouldBeNil)

			Convey("Alerts should be removed", func() {
				query := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1}
				err2 := HandleAlertsQuery(&query)

				So(testDash.Id, ShouldEqual, 1)
				So(err2, ShouldBeNil)
				So(len(query.Result), ShouldEqual, 0)
			})
		})
	})
}