From 1c053e63b41a31840c8b13dfb5c839b9aafac4d7 Mon Sep 17 00:00:00 2001 From: Karsten Jeschkies Date: Thu, 8 Jul 2021 16:38:03 +0200 Subject: [PATCH 1/8] Return build info under `/version`. Closes #3221 --- pkg/loki/loki.go | 3 +++ pkg/loki/version_handler.go | 32 ++++++++++++++++++++++++ pkg/loki/version_handler_test.go | 38 +++++++++++++++++++++++++++++ pkg/querier/queryrange/roundtrip.go | 2 +- 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 pkg/loki/version_handler.go create mode 100644 pkg/loki/version_handler_test.go diff --git a/pkg/loki/loki.go b/pkg/loki/loki.go index 592aa202c88b..15c71250d6b3 100644 --- a/pkg/loki/loki.go +++ b/pkg/loki/loki.go @@ -263,6 +263,9 @@ func (t *Loki) Run() error { // This adds a way to see the config and the changes compared to the defaults t.Server.HTTP.Path("/config").HandlerFunc(configHandler(t.Cfg, newDefaultConfig())) + // Each component serves its version. + t.Server.HTTP.Path("/version").HandlerFunc(versionHandler()) + t.Server.HTTP.Path("/debug/fgprof").Handler(fgprof.Handler()) // Let's listen for events from this manager, and log them. diff --git a/pkg/loki/version_handler.go b/pkg/loki/version_handler.go new file mode 100644 index 000000000000..717d4b47333c --- /dev/null +++ b/pkg/loki/version_handler.go @@ -0,0 +1,32 @@ +package loki + +import ( + "encoding/json" + "net/http" + + "github.com/grafana/loki/pkg/util/build" +) + +type buildInfo struct { + Version string `json:"version"` + Revision string `json:"revision"` + Branch string `json:"branch"` + BuildUser string `json:"build_user"` + BuildDate string `json:"build_date"` +} + +func versionHandler() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + info := buildInfo { + Version: build.Version, + Revision: build.Revision, + Branch: build.Branch, + BuildUser: build.BuildUser, + BuildDate: build.BuildDate, + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(info) + } +} diff --git a/pkg/loki/version_handler_test.go b/pkg/loki/version_handler_test.go new file mode 100644 index 000000000000..ab4a3d891194 --- /dev/null +++ b/pkg/loki/version_handler_test.go @@ -0,0 +1,38 @@ +package loki + +import ( + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" + + "github.com/grafana/loki/pkg/util/build" + "github.com/stretchr/testify/assert" +) + +func TestVersionHandler(t *testing.T) { + build.Version = "0.0.1" + build.Branch = "main" + build.Revision= "foobar" + build.BuildDate = "yesterday" + build.BuildUser = "Turing" + + req := httptest.NewRequest("GET", "http://test.com/config?mode=diff", nil) + w := httptest.NewRecorder() + + h := versionHandler() + h(w, req) + resp := w.Result() + assert.Equal(t, http.StatusOK, resp.StatusCode) + + expected := `{ + "version":"0.0.1", + "branch":"main", + "build_date":"yesterday", + "build_user":"Turing", + "revision":"foobar" + }` + body, err := ioutil.ReadAll(resp.Body) + assert.NoError(t, err) + assert.JSONEq(t, expected, string(body)) +} diff --git a/pkg/querier/queryrange/roundtrip.go b/pkg/querier/queryrange/roundtrip.go index bfe6e41a7fa9..d41d2da858ee 100644 --- a/pkg/querier/queryrange/roundtrip.go +++ b/pkg/querier/queryrange/roundtrip.go @@ -254,7 +254,7 @@ func NewLogFilterTripperware( }, nil } -// NewSeriesripperware creates a new frontend tripperware responsible for handling series requests +// NewSeriesTripperware creates a new frontend tripperware responsible for handling series requests func NewSeriesTripperware( cfg Config, log log.Logger, From d412f182f42fec45672175bf2e612fd1e508265b Mon Sep 17 00:00:00 2001 From: Karsten Jeschkies Date: Thu, 8 Jul 2021 16:43:52 +0200 Subject: [PATCH 2/8] Update documentation. --- docs/sources/api/_index.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/sources/api/_index.md b/docs/sources/api/_index.md index 97b8ac69638e..3ad7c40dfc6d 100644 --- a/docs/sources/api/_index.md +++ b/docs/sources/api/_index.md @@ -19,6 +19,7 @@ These endpoints are exposed by all components: - [`GET /ready`](#get-ready) - [`GET /metrics`](#get-metrics) - [`GET /config`](#get-config) +- [`GET /version`](#get-version) These endpoints are exposed by the querier and the frontend: @@ -823,6 +824,12 @@ and the current are returned. A value of `defaults` returns the default configur In microservices mode, the `/config` endpoint is exposed by all components. +## `GET /version` + +`/version` exposes the build information in a JSON object. The fields are `version`, `revision ``build_date`, `build_user`, and `revision`. + +In microservices mode, the `/version` endpoint is exposed by all components. + ## Series The Series API is available under the following: From 7a5bf6a06fd1783de16815e9122da4c51d88cdfb Mon Sep 17 00:00:00 2001 From: Karsten Jeschkies Date: Thu, 8 Jul 2021 16:49:46 +0200 Subject: [PATCH 3/8] Correct docs. --- docs/sources/api/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/api/_index.md b/docs/sources/api/_index.md index 3ad7c40dfc6d..37134d492fb4 100644 --- a/docs/sources/api/_index.md +++ b/docs/sources/api/_index.md @@ -826,7 +826,7 @@ In microservices mode, the `/config` endpoint is exposed by all components. ## `GET /version` -`/version` exposes the build information in a JSON object. The fields are `version`, `revision ``build_date`, `build_user`, and `revision`. +`/version` exposes the build information in a JSON object. The fields are `version`, `revision`, `branch`, `build_date`, and `build_user`. In microservices mode, the `/version` endpoint is exposed by all components. From a1abdb88944d8c17bcdda0b83bc3b226561fdd71 Mon Sep 17 00:00:00 2001 From: Karsten Jeschkies Date: Thu, 8 Jul 2021 16:50:59 +0200 Subject: [PATCH 4/8] Format version handler code. --- pkg/loki/version_handler.go | 14 +++++++------- pkg/loki/version_handler_test.go | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkg/loki/version_handler.go b/pkg/loki/version_handler.go index 717d4b47333c..2acac4232876 100644 --- a/pkg/loki/version_handler.go +++ b/pkg/loki/version_handler.go @@ -17,16 +17,16 @@ type buildInfo struct { func versionHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - info := buildInfo { - Version: build.Version, - Revision: build.Revision, - Branch: build.Branch, - BuildUser: build.BuildUser, + info := buildInfo{ + Version: build.Version, + Revision: build.Revision, + Branch: build.Branch, + BuildUser: build.BuildUser, BuildDate: build.BuildDate, } w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode(info) + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(info) } } diff --git a/pkg/loki/version_handler_test.go b/pkg/loki/version_handler_test.go index ab4a3d891194..6a58b140fdec 100644 --- a/pkg/loki/version_handler_test.go +++ b/pkg/loki/version_handler_test.go @@ -13,7 +13,7 @@ import ( func TestVersionHandler(t *testing.T) { build.Version = "0.0.1" build.Branch = "main" - build.Revision= "foobar" + build.Revision = "foobar" build.BuildDate = "yesterday" build.BuildUser = "Turing" From 202e9c36574f8dc47318fa3a86f4f6125a15a7b0 Mon Sep 17 00:00:00 2001 From: Karsten Jeschkies Date: Thu, 8 Jul 2021 16:53:58 +0200 Subject: [PATCH 5/8] Ignore write error. --- pkg/loki/version_handler.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/loki/version_handler.go b/pkg/loki/version_handler.go index 2acac4232876..fceb9d932305 100644 --- a/pkg/loki/version_handler.go +++ b/pkg/loki/version_handler.go @@ -27,6 +27,10 @@ func versionHandler() http.HandlerFunc { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode(info) + + // We ignore errors here, because we cannot do anything about them. + // Write will trigger sending Status code, so we cannot send a different status code afterwards. + // Also this isn't internal error, but error communicating with client. + _ = json.NewEncoder(w).Encode(info) } } From c221621da1474b81b90488d3a91ed551e784ce01 Mon Sep 17 00:00:00 2001 From: Karsten Jeschkies Date: Thu, 8 Jul 2021 16:59:38 +0200 Subject: [PATCH 6/8] Sort imports. --- pkg/loki/version_handler_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/loki/version_handler_test.go b/pkg/loki/version_handler_test.go index 6a58b140fdec..3f92dc2f5501 100644 --- a/pkg/loki/version_handler_test.go +++ b/pkg/loki/version_handler_test.go @@ -6,8 +6,9 @@ import ( "net/http/httptest" "testing" - "github.com/grafana/loki/pkg/util/build" "github.com/stretchr/testify/assert" + + "github.com/grafana/loki/pkg/util/build" ) func TestVersionHandler(t *testing.T) { From c782a05b63f7f8a5df1bd3cb2825d41e508ac335 Mon Sep 17 00:00:00 2001 From: Karsten Jeschkies Date: Thu, 8 Jul 2021 17:19:36 +0200 Subject: [PATCH 7/8] Use `PrometheusVersion` struct. --- docs/sources/api/_index.md | 6 +++--- pkg/loki/loki.go | 2 +- pkg/loki/version_handler.go | 13 ++++--------- pkg/loki/version_handler_test.go | 8 +++++--- pkg/util/build/build.go | 2 ++ 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/docs/sources/api/_index.md b/docs/sources/api/_index.md index 37134d492fb4..24b6d2c752ce 100644 --- a/docs/sources/api/_index.md +++ b/docs/sources/api/_index.md @@ -19,7 +19,7 @@ These endpoints are exposed by all components: - [`GET /ready`](#get-ready) - [`GET /metrics`](#get-metrics) - [`GET /config`](#get-config) -- [`GET /version`](#get-version) +- [`GET /loki/api/v1/status/buildinfo`](#get-buildinfo) These endpoints are exposed by the querier and the frontend: @@ -824,9 +824,9 @@ and the current are returned. A value of `defaults` returns the default configur In microservices mode, the `/config` endpoint is exposed by all components. -## `GET /version` +## `GET buildinfo` -`/version` exposes the build information in a JSON object. The fields are `version`, `revision`, `branch`, `build_date`, and `build_user`. +`/loki/api/v1/status/buildinfo` exposes the build information in a JSON object. The fields are `version`, `revision`, `branch`, `buildDate`, `buildUser`, and `goVersion`. In microservices mode, the `/version` endpoint is exposed by all components. diff --git a/pkg/loki/loki.go b/pkg/loki/loki.go index 15c71250d6b3..1d116682d2e2 100644 --- a/pkg/loki/loki.go +++ b/pkg/loki/loki.go @@ -261,7 +261,7 @@ func (t *Loki) Run() error { t.Server.HTTP.Path("/ready").Handler(t.readyHandler(sm)) // This adds a way to see the config and the changes compared to the defaults - t.Server.HTTP.Path("/config").HandlerFunc(configHandler(t.Cfg, newDefaultConfig())) + t.Server.HTTP.Path("/loki/api/v1/status/buildinfo").HandlerFunc(configHandler(t.Cfg, newDefaultConfig())) // Each component serves its version. t.Server.HTTP.Path("/version").HandlerFunc(versionHandler()) diff --git a/pkg/loki/version_handler.go b/pkg/loki/version_handler.go index fceb9d932305..316d4825f700 100644 --- a/pkg/loki/version_handler.go +++ b/pkg/loki/version_handler.go @@ -4,25 +4,20 @@ import ( "encoding/json" "net/http" + prom "github.com/prometheus/prometheus/web/api/v1" + "github.com/grafana/loki/pkg/util/build" ) -type buildInfo struct { - Version string `json:"version"` - Revision string `json:"revision"` - Branch string `json:"branch"` - BuildUser string `json:"build_user"` - BuildDate string `json:"build_date"` -} - func versionHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - info := buildInfo{ + info := prom.PrometheusVersion{ Version: build.Version, Revision: build.Revision, Branch: build.Branch, BuildUser: build.BuildUser, BuildDate: build.BuildDate, + GoVersion: build.GoVersion, } w.Header().Set("Content-Type", "application/json") diff --git a/pkg/loki/version_handler_test.go b/pkg/loki/version_handler_test.go index 3f92dc2f5501..083f6118614d 100644 --- a/pkg/loki/version_handler_test.go +++ b/pkg/loki/version_handler_test.go @@ -17,6 +17,7 @@ func TestVersionHandler(t *testing.T) { build.Revision = "foobar" build.BuildDate = "yesterday" build.BuildUser = "Turing" + build.GoVersion = "42" req := httptest.NewRequest("GET", "http://test.com/config?mode=diff", nil) w := httptest.NewRecorder() @@ -29,9 +30,10 @@ func TestVersionHandler(t *testing.T) { expected := `{ "version":"0.0.1", "branch":"main", - "build_date":"yesterday", - "build_user":"Turing", - "revision":"foobar" + "buildDate":"yesterday", + "buildUser":"Turing", + "revision":"foobar", + "goVersion": "42" }` body, err := ioutil.ReadAll(resp.Body) assert.NoError(t, err) diff --git a/pkg/util/build/build.go b/pkg/util/build/build.go index bab8f4d52eb1..49fb3fe7bcb3 100644 --- a/pkg/util/build/build.go +++ b/pkg/util/build/build.go @@ -12,6 +12,7 @@ var ( Branch string BuildUser string BuildDate string + GoVersion string ) func init() { @@ -20,4 +21,5 @@ func init() { version.Branch = Branch version.BuildUser = BuildUser version.BuildDate = BuildDate + version.GoVersion = "???" } From 0882965e0cf774af91193d4bbf94c2558d71e6e0 Mon Sep 17 00:00:00 2001 From: Karsten Jeschkies Date: Fri, 9 Jul 2021 11:09:47 +0200 Subject: [PATCH 8/8] Set Go version. --- pkg/util/build/build.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/util/build/build.go b/pkg/util/build/build.go index 49fb3fe7bcb3..9a6b75a8bca9 100644 --- a/pkg/util/build/build.go +++ b/pkg/util/build/build.go @@ -1,6 +1,10 @@ package build -import "github.com/prometheus/common/version" +import ( + "runtime" + + "github.com/prometheus/common/version" +) // Version information passed to Prometheus version package. // Package path as used by linker changes based on vendoring being used or not, @@ -21,5 +25,5 @@ func init() { version.Branch = Branch version.BuildUser = BuildUser version.BuildDate = BuildDate - version.GoVersion = "???" + version.GoVersion = runtime.Version() }