Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui: react: Add runtime and build info page #2832

Merged
merged 7 commits into from
Jul 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ We use *breaking* word for marking changes that are not backward compatible (rel
* [#2665](https://github.com/thanos-io/thanos/pull/2665) Swift: fix issue with missing Content-Type HTTP headers.
- [#2800](https://github.com/thanos-io/thanos/pull/2800) Query: Fix handling of `--web.external-prefix` and `--web.route-prefix`

### Changed
### Added
- [#2832](https://github.com/thanos-io/thanos/pull/2832) ui: React: Add runtime and build info page

## [v0.14.0](https://github.com/thanos-io/thanos/releases) - IN PROGRESS

Expand Down
36 changes: 35 additions & 1 deletion cmd/thanos/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"fmt"
"math"
"net/http"
"os"
"runtime"
"strings"
"time"

Expand All @@ -19,6 +21,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/common/route"
"github.com/prometheus/common/version"
"github.com/prometheus/prometheus/discovery/file"
"github.com/prometheus/prometheus/discovery/targetgroup"
"github.com/prometheus/prometheus/pkg/labels"
Expand Down Expand Up @@ -412,9 +415,38 @@ func runQuery(
router = router.WithPrefix(webRoutePrefix)
}

buildInfo := &v1.ThanosVersion{
Version: version.Version,
Revision: version.Revision,
Branch: version.Branch,
BuildUser: version.BuildUser,
BuildDate: version.BuildDate,
GoVersion: version.GoVersion,
}

CWD, err := os.Getwd()
if err != nil {
CWD = "<error retrieving current working directory>"
level.Warn(logger).Log("msg", "failed to retrieve current working directory", "err", err)
}

birth := time.Now()

var runtimeInfo v1.RuntimeInfoFn = func() v1.RuntimeInfo {
status := v1.RuntimeInfo{
StartTime: birth,
CWD: CWD,
GoroutineCount: runtime.NumGoroutine(),
GOMAXPROCS: runtime.GOMAXPROCS(0),
GOGC: os.Getenv("GOGC"),
GODEBUG: os.Getenv("GODEBUG"),
}
return status
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could just return this struct directly, no need for a variable. But I'd guess that the compiler already does this optimization for us. Plus, I'm surprised that none of our linters caught this. Perhaps we could improve the linters to catch functions that look like:

func foo() test {
  a := test{}
  return a
}

In the distant future? 😄

}

ins := extpromhttp.NewInstrumentationMiddleware(reg)
// TODO(bplotka in PR #513 review): pass all flags, not only the flags needed by prefix rewriting.
ui.NewQueryUI(logger, reg, stores, webExternalPrefix, webPrefixHeaderName).Register(router, ins)
ui.NewQueryUI(logger, reg, stores, webExternalPrefix, webPrefixHeaderName, runtimeInfo, *buildInfo).Register(router, ins)

api := v1.NewAPI(
logger,
Expand All @@ -431,6 +463,8 @@ func runQuery(
flagsMap,
instantDefaultMaxSourceResolution,
maxConcurrentQueries,
runtimeInfo,
buildInfo,
onprem marked this conversation as resolved.
Show resolved Hide resolved
)

api.Register(router.WithPrefix("/api/v1"), tracer, logger, ins)
Expand Down
39 changes: 39 additions & 0 deletions pkg/query/api/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,29 @@ func (e *ApiError) Error() string {
return fmt.Sprintf("%s: %s", e.Typ, e.Err)
}

// ThanosVersion contains build information about Thanos.
type ThanosVersion struct {
onprem marked this conversation as resolved.
Show resolved Hide resolved
Version string `json:"version"`
Revision string `json:"revision"`
Branch string `json:"branch"`
BuildUser string `json:"buildUser"`
BuildDate string `json:"buildDate"`
GoVersion string `json:"goVersion"`
}

// RuntimeInfo contains runtime information about Thanos.
type RuntimeInfo struct {
StartTime time.Time `json:"startTime"`
CWD string `json:"CWD"`
GoroutineCount int `json:"goroutineCount"`
GOMAXPROCS int `json:"GOMAXPROCS"`
GOGC string `json:"GOGC"`
GODEBUG string `json:"GODEBUG"`
}

// RuntimeInfoFn returns updated runtime information about Thanos.
type RuntimeInfoFn func() RuntimeInfo

type response struct {
Status status `json:"status"`
Data interface{} `json:"data,omitempty"`
Expand Down Expand Up @@ -119,6 +142,8 @@ type API struct {
enableRulePartialResponse bool
replicaLabels []string
flagsMap map[string]string
runtimeInfo RuntimeInfoFn
buildInfo *ThanosVersion

storeSet *query.StoreSet
defaultInstantQueryMaxSourceResolution time.Duration
Expand All @@ -141,6 +166,8 @@ func NewAPI(
flagsMap map[string]string,
defaultInstantQueryMaxSourceResolution time.Duration,
maxConcurrentQueries int,
runtimeInfo RuntimeInfoFn,
buildInfo *ThanosVersion,
) *API {
return &API{
logger: logger,
Expand All @@ -157,6 +184,8 @@ func NewAPI(
flagsMap: flagsMap,
storeSet: storeSet,
defaultInstantQueryMaxSourceResolution: defaultInstantQueryMaxSourceResolution,
runtimeInfo: runtimeInfo,
buildInfo: buildInfo,

now: time.Now,
}
Expand Down Expand Up @@ -195,6 +224,8 @@ func (api *API) Register(r *route.Router, tracer opentracing.Tracer, logger log.
r.Post("/labels", instr("label_names", api.labelNames))

r.Get("/status/flags", instr("status_flags", api.flags))
r.Get("/status/runtimeinfo", instr("status_runtime", api.serveRuntimeInfo))
r.Get("/status/buildinfo", instr("status_build", api.serveBuildInfo))

r.Get("/stores", instr("stores", api.stores))

Expand Down Expand Up @@ -683,6 +714,14 @@ func (api *API) flags(r *http.Request) (interface{}, []error, *ApiError) {
return api.flagsMap, nil, nil
}

func (api *API) serveRuntimeInfo(r *http.Request) (interface{}, []error, *ApiError) {
return api.runtimeInfo(), nil, nil
}

func (api *API) serveBuildInfo(r *http.Request) (interface{}, []error, *ApiError) {
return api.buildInfo, nil, nil
}

// NewRulesHandler created handler compatible with HTTP /api/v1/rules https://prometheus.io/docs/prometheus/latest/querying/api/#rules
// which uses gRPC Unary Rules API.
func NewRulesHandler(client rules.UnaryClient, enablePartialResponse bool) func(*http.Request) (interface{}, []error, *ApiError) {
Expand Down
88 changes: 44 additions & 44 deletions pkg/ui/bindata.go

Large diffs are not rendered by default.

47 changes: 14 additions & 33 deletions pkg/ui/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package ui
import (
"html/template"
"net/http"
"os"
"path"
"sort"
"strings"
Expand All @@ -16,10 +15,10 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/model"
"github.com/prometheus/common/route"
"github.com/prometheus/common/version"
"github.com/thanos-io/thanos/pkg/component"
extpromhttp "github.com/thanos-io/thanos/pkg/extprom/http"
"github.com/thanos-io/thanos/pkg/query"
v1 "github.com/thanos-io/thanos/pkg/query/api"
)

type Query struct {
Expand All @@ -28,33 +27,22 @@ type Query struct {

externalPrefix, prefixHeader string

cwd string
birth time.Time
reg prometheus.Registerer
now func() model.Time
cwd string
birth time.Time
version v1.ThanosVersion
reg prometheus.Registerer
now func() model.Time
}

type thanosVersion struct {
Version string `json:"version"`
Revision string `json:"revision"`
Branch string `json:"branch"`
BuildUser string `json:"buildUser"`
BuildDate string `json:"buildDate"`
GoVersion string `json:"goVersion"`
}

func NewQueryUI(logger log.Logger, reg prometheus.Registerer, storeSet *query.StoreSet, externalPrefix, prefixHeader string) *Query {
cwd, err := os.Getwd()
if err != nil {
cwd = "<error retrieving current working directory>"
}
func NewQueryUI(logger log.Logger, reg prometheus.Registerer, storeSet *query.StoreSet, externalPrefix, prefixHeader string, runtimeInfo v1.RuntimeInfoFn, buildInfo v1.ThanosVersion) *Query {
return &Query{
BaseUI: NewBaseUI(logger, "query_menu.html", queryTmplFuncs(), externalPrefix, prefixHeader, component.Query),
storeSet: storeSet,
externalPrefix: externalPrefix,
prefixHeader: prefixHeader,
cwd: cwd,
birth: time.Now(),
cwd: runtimeInfo().CWD,
birth: runtimeInfo().StartTime,
version: buildInfo,
reg: reg,
now: model.Now,
}
Expand Down Expand Up @@ -118,18 +106,11 @@ func (q *Query) status(w http.ResponseWriter, r *http.Request) {
q.executeTemplate(w, "status.html", prefix, struct {
Birth time.Time
CWD string
Version thanosVersion
Version v1.ThanosVersion
}{
Birth: q.birth,
CWD: q.cwd,
Version: thanosVersion{
Version: version.Version,
Revision: version.Revision,
Branch: version.Branch,
BuildUser: version.BuildUser,
BuildDate: version.BuildDate,
GoVersion: version.GoVersion,
},
Birth: q.birth,
CWD: q.cwd,
Version: q.version,
})
}

Expand Down
1 change: 0 additions & 1 deletion pkg/ui/react-app/src/pages/status/Status.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ const Status: FC<RouteComponentProps & PathPrefixProps> = ({ pathPrefix = '' })
{[
{ fetchResult: useFetch<Record<string, string>>(`${path}/status/runtimeinfo`), title: 'Runtime Information' },
{ fetchResult: useFetch<Record<string, string>>(`${path}/status/buildinfo`), title: 'Build Information' },
{ fetchResult: useFetch<Record<string, string>>(`${path}/alertmanagers`), title: 'Alertmanagers' },
].map(({ fetchResult, title }) => {
const { response, isLoading, error } = fetchResult;
return (
Expand Down
8 changes: 7 additions & 1 deletion pkg/ui/react-app/src/thanos/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ const navConfig: { [component: string]: (NavConfig | NavDropDown)[] } = {
query: [
{ name: 'Graph', uri: '/new/graph' },
{ name: 'Stores', uri: '/new/stores' },
{ name: 'Status', children: [{ name: 'Command-Line Flags', uri: '/new/flags' }] },
{
name: 'Status',
children: [
{ name: 'Runtime & Build Information', uri: '/new/status' },
{ name: 'Command-Line Flags', uri: '/new/flags' },
],
},
],
};

Expand Down