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

Add metadata to User-Agent header #5774

Merged
merged 18 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from 14 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
1 change: 1 addition & 0 deletions cmd/grafana-agent/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ COPY cmd/grafana-agent/agent-local-config.yaml /etc/agent/agent.yaml


ENTRYPOINT ["/bin/grafana-agent"]
ENV AGENT_DEPLOY_MODE=docker
CMD ["--config.file=/etc/agent/agent.yaml", "--metrics.wal-directory=/etc/agent/data"]
4 changes: 2 additions & 2 deletions component/common/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (

"github.com/go-kit/log"
commoncfg "github.com/grafana/agent/component/common/config"
"github.com/grafana/agent/pkg/build"
"github.com/grafana/agent/internal/useragent"
"github.com/grafana/agent/pkg/flow/logging/level"
promconfig "github.com/prometheus/common/config"
"k8s.io/client-go/rest"
Expand Down Expand Up @@ -79,7 +79,7 @@ func (args *ClientArguments) BuildRESTConfig(l log.Logger) (*rest.Config, error)
}
}

cfg.UserAgent = fmt.Sprintf("GrafanaAgent/%s", build.Version)
cfg.UserAgent = useragent.Get()
cfg.ContentType = "application/vnd.kubernetes.protobuf"

return cfg, nil
Expand Down
6 changes: 3 additions & 3 deletions component/common/loki/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import (
"time"

"github.com/go-kit/log"
"github.com/grafana/agent/internal/useragent"
"github.com/grafana/agent/pkg/flow/logging/level"
"github.com/grafana/dskit/backoff"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/config"
"github.com/prometheus/common/model"

"github.com/grafana/agent/component/common/loki"
"github.com/grafana/agent/pkg/build"
"github.com/grafana/agent/pkg/util"
lokiutil "github.com/grafana/loki/pkg/util"
)
Expand All @@ -47,7 +47,7 @@ const (

var Reasons = []string{ReasonGeneric, ReasonRateLimited, ReasonStreamLimited, ReasonLineTooLong}

var UserAgent = fmt.Sprintf("GrafanaAgent/%s", build.Version)
var userAgent = useragent.Get()

type Metrics struct {
encodedBytes *prometheus.CounterVec
Expand Down Expand Up @@ -419,7 +419,7 @@ func (c *client) send(ctx context.Context, tenantID string, buf []byte) (int, er
}
req = req.WithContext(ctx)
req.Header.Set("Content-Type", contentType)
req.Header.Set("User-Agent", UserAgent)
req.Header.Set("User-Agent", userAgent)

// If the tenant ID is not empty promtail is running in multi-tenant mode, so
// we should send it to Loki
Expand Down
2 changes: 1 addition & 1 deletion component/common/loki/client/queue_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ func (c *queueClient) send(ctx context.Context, tenantID string, buf []byte) (in
}
req = req.WithContext(ctx)
req.Header.Set("Content-Type", contentType)
req.Header.Set("User-Agent", UserAgent)
req.Header.Set("User-Agent", userAgent)

// If the tenant ID is not empty promtail is running in multi-tenant mode, so
// we should send it to Loki
Expand Down
4 changes: 2 additions & 2 deletions component/loki/source/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
flow_relabel "github.com/grafana/agent/component/common/relabel"
"github.com/grafana/agent/component/discovery"
dt "github.com/grafana/agent/component/loki/source/docker/internal/dockertarget"
"github.com/grafana/agent/pkg/build"
"github.com/grafana/agent/internal/useragent"
"github.com/grafana/agent/pkg/flow/logging/level"
"github.com/prometheus/common/config"
"github.com/prometheus/common/model"
Expand All @@ -40,7 +40,7 @@ func init() {
})
}

var userAgent = fmt.Sprintf("GrafanaAgent/%s", build.Version)
var userAgent = useragent.Get()

const (
dockerLabel = model.MetaLabelPrefix + "docker_"
Expand Down
3 changes: 0 additions & 3 deletions component/loki/write/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/grafana/agent/component/common/loki/client"
"github.com/grafana/agent/component/common/loki/limit"
"github.com/grafana/agent/component/common/loki/wal"
"github.com/grafana/agent/pkg/build"
)

func init() {
Expand All @@ -25,8 +24,6 @@ func init() {
return New(opts, args.(Arguments))
},
})

client.UserAgent = fmt.Sprintf("GrafanaAgent/%s", build.Version)
}

// Arguments holds values which are used to configure the loki.write component.
Expand Down
4 changes: 2 additions & 2 deletions component/prometheus/remotewrite/remote_write.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (

"github.com/go-kit/log"
"github.com/grafana/agent/component"
"github.com/grafana/agent/pkg/build"
"github.com/grafana/agent/internal/useragent"
"github.com/grafana/agent/pkg/flow/logging/level"
"github.com/grafana/agent/pkg/metrics/wal"
"github.com/prometheus/prometheus/model/timestamp"
Expand All @@ -35,7 +35,7 @@ import (
var remoteFlushDeadline = 1 * time.Minute

func init() {
remote.UserAgent = fmt.Sprintf("GrafanaAgent/%s", build.Version)
remote.UserAgent = useragent.Get()

component.Register(component.Registration{
Name: "prometheus.remote_write",
Expand Down
4 changes: 2 additions & 2 deletions component/prometheus/scrape/scrape.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
component_config "github.com/grafana/agent/component/common/config"
"github.com/grafana/agent/component/discovery"
"github.com/grafana/agent/component/prometheus"
"github.com/grafana/agent/pkg/build"
"github.com/grafana/agent/internal/useragent"
"github.com/grafana/agent/pkg/flow/logging/level"
"github.com/grafana/agent/service/cluster"
"github.com/grafana/agent/service/http"
Expand All @@ -27,7 +27,7 @@ import (
)

func init() {
scrape.UserAgent = fmt.Sprintf("GrafanaAgent/%s", build.Version)
scrape.UserAgent = useragent.Get()

component.Register(component.Registration{
Name: "prometheus.scrape",
Expand Down
5 changes: 2 additions & 3 deletions component/pyroscope/scrape/scrape_loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,17 @@ import (

"github.com/go-kit/log"
"github.com/grafana/agent/component/pyroscope"
"github.com/grafana/agent/internal/useragent"
"github.com/grafana/agent/pkg/flow/logging/level"
commonconfig "github.com/prometheus/common/config"
"github.com/prometheus/prometheus/discovery/targetgroup"
"github.com/prometheus/prometheus/util/pool"
"golang.org/x/net/context/ctxhttp"

"github.com/grafana/agent/pkg/build"
)

var (
payloadBuffers = pool.New(1e3, 1e6, 3, func(sz int) interface{} { return make([]byte, 0, sz) })
userAgentHeader = fmt.Sprintf("GrafanaAgent/%s", build.Version)
userAgentHeader = useragent.Get()
)

type scrapePool struct {
Expand Down
5 changes: 2 additions & 3 deletions component/pyroscope/write/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package write
import (
"context"
"errors"
"fmt"
"strings"
"time"

"github.com/bufbuild/connect-go"
"github.com/grafana/agent/component/pyroscope"
"github.com/grafana/agent/internal/useragent"
"github.com/grafana/agent/pkg/flow/logging/level"
"github.com/oklog/run"
commonconfig "github.com/prometheus/common/config"
Expand All @@ -18,15 +18,14 @@ import (

"github.com/grafana/agent/component"
"github.com/grafana/agent/component/common/config"
"github.com/grafana/agent/pkg/build"
"github.com/grafana/dskit/backoff"
pushv1 "github.com/grafana/pyroscope/api/gen/proto/go/push/v1"
"github.com/grafana/pyroscope/api/gen/proto/go/push/v1/pushv1connect"
typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1"
)

var (
userAgent = fmt.Sprintf("GrafanaAgent/%s", build.Version)
userAgent = useragent.Get()
DefaultArguments = func() Arguments {
return Arguments{}
}
Expand Down
4 changes: 2 additions & 2 deletions component/remote/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import (
"github.com/go-kit/log"
"github.com/grafana/agent/component"
common_config "github.com/grafana/agent/component/common/config"
"github.com/grafana/agent/pkg/build"
"github.com/grafana/agent/internal/useragent"
"github.com/grafana/agent/pkg/flow/logging/level"
"github.com/grafana/river/rivertypes"
prom_config "github.com/prometheus/common/config"
)

var userAgent = fmt.Sprintf("GrafanaAgent/%s", build.Version)
var userAgent = useragent.Get()

func init() {
component.Register(component.Registration{
Expand Down
60 changes: 60 additions & 0 deletions internal/useragent/useragent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// package useragent provides a consistent way to get a user agent for outbound http requests from Grafana Agent.
// The default User-Agent is `GrafanaAgent/$VERSION($MODE)`
// Where version is the build version of the agent and MODE is one of "static" or "flow".
package useragent

import (
"fmt"
"os"
"runtime"
"strings"

"github.com/grafana/agent/pkg/build"
)

const (
deployModeEnv = "AGENT_DEPLOY_MODE"
modeEnv = "AGENT_MODE"
)

// settable by tests
var goos = runtime.GOOS

func Get() string {
parenthesis := ""
metadata := []string{}
if mode := getRunMode(); mode != "" {
metadata = append(metadata, mode)
}
metadata = append(metadata, goos)
if op := getDeployMode(); op != "" {
metadata = append(metadata, op)
}
if len(metadata) > 0 {
parenthesis = fmt.Sprintf(" (%s)", strings.Join(metadata, "; "))
}
return fmt.Sprintf("GrafanaAgent/%s%s", build.Version, parenthesis)
}

// getRunMode attempts to get agent mode, using `unknown` for invalid values.
func getRunMode() string {
key := os.Getenv(modeEnv)
switch key {
case "flow":
return "flow"
case "static", "":
return "static"
default:
return "unknown"
}
}

func getDeployMode() string {
op := os.Getenv(deployModeEnv)
// only return known modes
switch op {
case "operator", "helm", "docker", "deb", "rpm", "brew":
return op
}
return ""
}
89 changes: 89 additions & 0 deletions internal/useragent/useragent_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package useragent

import (
"testing"

"github.com/grafana/agent/pkg/build"
"github.com/stretchr/testify/require"
)

func TestUserAgent(t *testing.T) {
build.Version = "v1.2.3"
tests := []struct {
Name string
Mode string
Expected string
DeployMode string
GOOS string
}{
{
Name: "basic",
Mode: "",
Expected: "GrafanaAgent/v1.2.3 (static; linux)",
GOOS: "linux",
},
{
Name: "flow",
Mode: "flow",
Expected: "GrafanaAgent/v1.2.3 (flow; windows)",
GOOS: "windows",
},
{
Name: "static",
Mode: "static",
Expected: "GrafanaAgent/v1.2.3 (static; darwin)",
GOOS: "darwin",
},
{
Name: "unknown",
Mode: "blahlahblah",
// unknown mode, should not happen. But we will substitute 'unknown' to avoid allowing arbitrary cardinality.
Expected: "GrafanaAgent/v1.2.3 (unknown; freebsd)",
GOOS: "freebsd",
},
{
Name: "operator",
Mode: "static",
DeployMode: "operator",
Expected: "GrafanaAgent/v1.2.3 (static; linux; operator)",
GOOS: "linux",
},
{
Name: "deb",
Mode: "flow",
DeployMode: "deb",
Expected: "GrafanaAgent/v1.2.3 (flow; linux; deb)",
GOOS: "linux",
},
{
Name: "rpm",
Mode: "static",
DeployMode: "rpm",
Expected: "GrafanaAgent/v1.2.3 (static; linux; rpm)",
GOOS: "linux",
},
{
Name: "docker",
Mode: "flow",
DeployMode: "docker",
Expected: "GrafanaAgent/v1.2.3 (flow; linux; docker)",
GOOS: "linux",
},
{
Name: "helm",
Mode: "flow",
DeployMode: "helm",
Expected: "GrafanaAgent/v1.2.3 (flow; linux; helm)",
GOOS: "linux",
},
}
for _, tst := range tests {
t.Run(tst.Name, func(t *testing.T) {
goos = tst.GOOS
t.Setenv(deployModeEnv, tst.DeployMode)
t.Setenv(modeEnv, tst.Mode)
actual := Get()
require.Equal(t, tst.Expected, actual)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
env:
- name: AGENT_MODE
value: {{ .Values.agent.mode }}
- name: AGENT_DEPLOY_MODE
value: "helm"
- name: HOSTNAME
valueFrom:
fieldRef:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ spec:
env:
- name: AGENT_MODE
value: flow
- name: AGENT_DEPLOY_MODE
value: "helm"
- name: HOSTNAME
valueFrom:
fieldRef:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ spec:
env:
- name: AGENT_MODE
value: flow
- name: AGENT_DEPLOY_MODE
value: "helm"
- name: HOSTNAME
valueFrom:
fieldRef:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ spec:
env:
- name: AGENT_MODE
value: flow
- name: AGENT_DEPLOY_MODE
value: "helm"
- name: HOSTNAME
valueFrom:
fieldRef:
Expand Down
Loading