diff --git a/.drone.yml b/.drone.yml index 2abd26a3e19..e944426e4b7 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1224,7 +1224,7 @@ steps: repo: - grafana/grafana - commands: - - ./scripts/ci-frontend-metrics.sh | ./bin/grabpl publish-metrics $${GRAFANA_MISC_STATS_API_KEY} + - ./scripts/ci-frontend-metrics.sh | ./bin/build publish-metrics $${GRAFANA_MISC_STATS_API_KEY} depends_on: - test-a11y-frontend environment: @@ -5114,6 +5114,6 @@ kind: secret name: packages_secret_access_key --- kind: signature -hmac: 7b6e3697e7278f2efc8a8c3865df9bd4ad3526e883c27c57f4a08c2f51869793 +hmac: 20e4a947fba1881cbb9b18c8f11b2c896652c701e9c5018e135632034778b4f1 ... diff --git a/pkg/build/cmd/main.go b/pkg/build/cmd/main.go index fe7db03c8e9..c2f6e731c79 100644 --- a/pkg/build/cmd/main.go +++ b/pkg/build/cmd/main.go @@ -108,6 +108,12 @@ func main() { &noInstallDepsFlag, }, }, + { + Name: "publish-metrics", + Usage: "Publish a set of metrics from stdin", + ArgsUsage: "", + Action: ArgCountWrapper(1, PublishMetrics), + }, } if err := app.Run(os.Args); err != nil { diff --git a/pkg/build/cmd/publishmetrics.go b/pkg/build/cmd/publishmetrics.go new file mode 100644 index 00000000000..d88911fc328 --- /dev/null +++ b/pkg/build/cmd/publishmetrics.go @@ -0,0 +1,41 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "log" + "os" + "regexp" + + "github.com/grafana/grafana/pkg/build/metrics" + "github.com/urfave/cli/v2" +) + +func PublishMetrics(c *cli.Context) error { + apiKey := c.Args().Get(0) + + input, err := io.ReadAll(os.Stdin) + if err != nil { + return cli.NewExitError(fmt.Sprintf("Reading from stdin failed: %s", err), 1) + } + + reMetrics := regexp.MustCompile(`(?ms)^Metrics: (\{.+\})`) + ms := reMetrics.FindSubmatch(input) + if len(ms) == 0 { + return cli.NewExitError(fmt.Sprintf("Input on wrong format: %q", string(input)), 1) + } + + m := map[string]string{} + if err := json.Unmarshal(ms[1], &m); err != nil { + return cli.NewExitError(fmt.Sprintf("decoding metrics failed: %s", err), 1) + } + + log.Printf("Received metrics %+v", m) + + if err := metrics.Publish(m, apiKey); err != nil { + return cli.NewExitError(fmt.Sprintf("publishing metrics failed: %s", err), 1) + } + + return nil +} diff --git a/pkg/build/metrics/publish.go b/pkg/build/metrics/publish.go new file mode 100644 index 00000000000..934f8168802 --- /dev/null +++ b/pkg/build/metrics/publish.go @@ -0,0 +1,72 @@ +package metrics + +import ( + "bytes" + "encoding/json" + "fmt" + "log" + "strconv" + "time" + + "net/http" +) + +type payload struct { + Name string `json:"name"` + Value int `json:"value"` + Interval int `json:"interval"` + MType string `json:"mtype"` + Time int64 `json:"time"` +} + +// Publish publishes a set of metrics. +func Publish(metrics map[string]string, apiKey string) error { + log.Println("Publishing metrics") + + t := time.Now().Unix() + data := []payload{} + for k, vS := range metrics { + v, err := strconv.Atoi(vS) + if err != nil { + return fmt.Errorf("key %q has value on invalid format: %q", k, vS) + } + data = append(data, payload{ + Name: k, + Value: v, + Interval: 60, + MType: "gauge", + Time: t, + }) + } + + buf := bytes.Buffer{} + enc := json.NewEncoder(&buf) + if err := enc.Encode(data); err != nil { + return err + } + + log.Printf("Publishing metrics to https://:@graphite-us-central1.grafana.net/metrics, JSON: %s", + buf.String()) + + u := fmt.Sprintf("https://6371:%s@graphite-us-central1.grafana.net/metrics", apiKey) + + //nolint:gosec + resp, err := http.Post(u, "application/json", &buf) + if err != nil { + return fmt.Errorf("metrics publishing failed: %w", err) + } + + defer func() { + if err := resp.Body.Close(); err != nil { + log.Println("Error closing HTTP body", err) + } + }() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return fmt.Errorf("metrics publishing failed with status code %d", resp.StatusCode) + } + + log.Printf("Metrics successfully published") + + return nil +} diff --git a/scripts/drone/steps/lib.star b/scripts/drone/steps/lib.star index ae39e0b032d..5753a37fa6a 100644 --- a/scripts/drone/steps/lib.star +++ b/scripts/drone/steps/lib.star @@ -609,7 +609,7 @@ def frontend_metrics_step(edition, trigger=None): }, 'failure': 'ignore', 'commands': [ - './scripts/ci-frontend-metrics.sh | ./bin/grabpl publish-metrics $${GRAFANA_MISC_STATS_API_KEY}', + './scripts/ci-frontend-metrics.sh | ./bin/build publish-metrics $${GRAFANA_MISC_STATS_API_KEY}', ], } if trigger: