mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
feat: add coder_build_info metric (#24365)
_Disclaimer: produced by Claude Opus 4.6_ Adds a `coder_build_info` metric which allows operators to see which versions of Coder are currently running. --------- Signed-off-by: Danny Kopping <danny@coder.com>
This commit is contained in:
@@ -48,7 +48,7 @@ const (
|
|||||||
// Use golang.org/x/mod/semver to compare versions.
|
// Use golang.org/x/mod/semver to compare versions.
|
||||||
func Version() string {
|
func Version() string {
|
||||||
readVersion.Do(func() {
|
readVersion.Do(func() {
|
||||||
revision, valid := revision()
|
revision, valid := Revision()
|
||||||
if valid {
|
if valid {
|
||||||
revision = "+" + revision[:7]
|
revision = "+" + revision[:7]
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ func IsBoringCrypto() bool {
|
|||||||
func ExternalURL() string {
|
func ExternalURL() string {
|
||||||
readExternalURL.Do(func() {
|
readExternalURL.Do(func() {
|
||||||
repo := "https://github.com/coder/coder"
|
repo := "https://github.com/coder/coder"
|
||||||
revision, valid := revision()
|
revision, valid := Revision()
|
||||||
if !valid {
|
if !valid {
|
||||||
externalURL = repo
|
externalURL = repo
|
||||||
return
|
return
|
||||||
@@ -147,8 +147,8 @@ func Time() (time.Time, bool) {
|
|||||||
return parsed, true
|
return parsed, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// revision returns the Git hash of the build.
|
// Revision returns the full Git hash of the build.
|
||||||
func revision() (string, bool) {
|
func Revision() (string, bool) {
|
||||||
return find("vcs.revision")
|
return find("vcs.revision")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1013,6 +1013,11 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
|
|||||||
if err = prometheusmetrics.Experiments(options.PrometheusRegistry, active); err != nil {
|
if err = prometheusmetrics.Experiments(options.PrometheusRegistry, active); err != nil {
|
||||||
return xerrors.Errorf("register experiments metric: %w", err)
|
return xerrors.Errorf("register experiments metric: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
revision, _ := buildinfo.Revision()
|
||||||
|
if err = prometheusmetrics.BuildInfo(options.PrometheusRegistry, buildinfo.Version(), revision); err != nil {
|
||||||
|
return xerrors.Errorf("register build info metric: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is helpful for tests, but can be silently ignored.
|
// This is helpful for tests, but can be silently ignored.
|
||||||
|
|||||||
@@ -710,6 +710,24 @@ func Experiments(registerer prometheus.Registerer, active codersdk.Experiments)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BuildInfo registers a gauge which is always set to 1, with labels
|
||||||
|
// describing the running server version. This follows the common
|
||||||
|
// pattern used by Prometheus itself and many Go services.
|
||||||
|
func BuildInfo(registerer prometheus.Registerer, version, revision string) error {
|
||||||
|
gauge := prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||||
|
Namespace: "coderd",
|
||||||
|
Name: "build_info",
|
||||||
|
Help: "Describes the current build/version of the Coder server. Value is always 1.",
|
||||||
|
}, []string{"version", "revision"})
|
||||||
|
if err := registerer.Register(gauge); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
gauge.WithLabelValues(version, revision).Set(1)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// filterAcceptableAgentLabels handles a slightly messy situation whereby `prometheus-aggregate-agent-stats-by` can control on
|
// filterAcceptableAgentLabels handles a slightly messy situation whereby `prometheus-aggregate-agent-stats-by` can control on
|
||||||
// which labels agent stats are aggregated, but for these specific metrics in this file there is no `template` label value,
|
// which labels agent stats are aggregated, but for these specific metrics in this file there is no `template` label value,
|
||||||
// and therefore we have to exclude it from the list of acceptable labels.
|
// and therefore we have to exclude it from the list of acceptable labels.
|
||||||
|
|||||||
@@ -906,6 +906,33 @@ func TestExperimentsMetric(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuildInfo(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
reg := prometheus.NewRegistry()
|
||||||
|
version := "v2.15.0+abc1234"
|
||||||
|
revision := "abc1234def5678"
|
||||||
|
|
||||||
|
require.NoError(t, prometheusmetrics.BuildInfo(reg, version, revision))
|
||||||
|
|
||||||
|
out, err := reg.Gather()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, out, 1)
|
||||||
|
require.Equal(t, "coderd_build_info", out[0].GetName())
|
||||||
|
|
||||||
|
metrics := out[0].GetMetric()
|
||||||
|
require.Len(t, metrics, 1)
|
||||||
|
|
||||||
|
// Labels are sorted alphabetically by Prometheus.
|
||||||
|
labels := metrics[0].GetLabel()
|
||||||
|
require.Len(t, labels, 2)
|
||||||
|
require.Equal(t, "revision", labels[0].GetName())
|
||||||
|
require.Equal(t, revision, labels[0].GetValue())
|
||||||
|
require.Equal(t, "version", labels[1].GetName())
|
||||||
|
require.Equal(t, version, labels[1].GetValue())
|
||||||
|
require.Equal(t, float64(1), metrics[0].GetGauge().GetValue())
|
||||||
|
}
|
||||||
|
|
||||||
func prepareWorkspaceAndAgent(ctx context.Context, t *testing.T, client *codersdk.Client, user codersdk.CreateFirstUserResponse, workspaceNum int) agentproto.DRPCAgentClient {
|
func prepareWorkspaceAndAgent(ctx context.Context, t *testing.T, client *codersdk.Client, user codersdk.CreateFirstUserResponse, workspaceNum int) agentproto.DRPCAgentClient {
|
||||||
authToken := uuid.NewString()
|
authToken := uuid.NewString()
|
||||||
|
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ deployment. They will always be available from the agent.
|
|||||||
| `coderd_api_workspace_latest_build` | gauge | The current number of workspace builds by status for all non-deleted workspaces. | `status` |
|
| `coderd_api_workspace_latest_build` | gauge | The current number of workspace builds by status for all non-deleted workspaces. | `status` |
|
||||||
| `coderd_authz_authorize_duration_seconds` | histogram | Duration of the 'Authorize' call in seconds. Only counts calls that succeed. | `allowed` |
|
| `coderd_authz_authorize_duration_seconds` | histogram | Duration of the 'Authorize' call in seconds. Only counts calls that succeed. | `allowed` |
|
||||||
| `coderd_authz_prepare_authorize_duration_seconds` | histogram | Duration of the 'PrepareAuthorize' call in seconds. | |
|
| `coderd_authz_prepare_authorize_duration_seconds` | histogram | Duration of the 'PrepareAuthorize' call in seconds. | |
|
||||||
|
| `coderd_build_info` | gauge | Describes the current build/version of the Coder server. Value is always 1. | `revision` `version` |
|
||||||
| `coderd_db_query_counts_total` | counter | Total number of queries labelled by HTTP route, method, and query name. | `method` `query` `route` |
|
| `coderd_db_query_counts_total` | counter | Total number of queries labelled by HTTP route, method, and query name. | `method` `query` `route` |
|
||||||
| `coderd_db_query_latencies_seconds` | histogram | Latency distribution of queries in seconds. | `query` |
|
| `coderd_db_query_latencies_seconds` | histogram | Latency distribution of queries in seconds. | `query` |
|
||||||
| `coderd_db_tx_duration_seconds` | histogram | Duration of transactions in seconds. | `success` `tx_id` |
|
| `coderd_db_tx_duration_seconds` | histogram | Duration of transactions in seconds. | `success` `tx_id` |
|
||||||
|
|||||||
@@ -223,6 +223,9 @@ coderd_authz_authorize_duration_seconds{allowed=""} 0
|
|||||||
# HELP coderd_authz_prepare_authorize_duration_seconds Duration of the 'PrepareAuthorize' call in seconds.
|
# HELP coderd_authz_prepare_authorize_duration_seconds Duration of the 'PrepareAuthorize' call in seconds.
|
||||||
# TYPE coderd_authz_prepare_authorize_duration_seconds histogram
|
# TYPE coderd_authz_prepare_authorize_duration_seconds histogram
|
||||||
coderd_authz_prepare_authorize_duration_seconds 0
|
coderd_authz_prepare_authorize_duration_seconds 0
|
||||||
|
# HELP coderd_build_info Describes the current build/version of the Coder server. Value is always 1.
|
||||||
|
# TYPE coderd_build_info gauge
|
||||||
|
coderd_build_info{version="",revision=""} 0
|
||||||
# HELP coderd_db_query_counts_total Total number of queries labelled by HTTP route, method, and query name.
|
# HELP coderd_db_query_counts_total Total number of queries labelled by HTTP route, method, and query name.
|
||||||
# TYPE coderd_db_query_counts_total counter
|
# TYPE coderd_db_query_counts_total counter
|
||||||
coderd_db_query_counts_total{route="",method="",query=""} 0
|
coderd_db_query_counts_total{route="",method="",query=""} 0
|
||||||
|
|||||||
Reference in New Issue
Block a user