@cryptotaxi247 / netdata-1 / commits / 2d4c5d1a0

go.d/varnish: add docker support (#18512)

Ilya Mashchenko committed Sep 10, 2024 at 17:36 UTC 2d4c5d1a09a4c346b16d3b854f7bea15ff7c6839
9 files changed +68 -12
src/go/plugin/go.d/config/go.d/sd/docker.conf
+7
@@ -82,6 +82,8 @@ classify:
82 expr: '{{ and (eq .PrivatePort "9051") (match "sp" .Image "*/tor */tor:*") }}'
83 - tags: "tomcat"
84 expr: '{{ match "sp" .Image "tomcat tomcat:* */tomcat */tomcat:*" }}'
85 + - tags: "varnish"
86 + expr: '{{ match "sp" .Image "varnish varnish:*" }}'
87 - tags: "vernemq"
88 expr: '{{ match "sp" .Image "*/vernemq */vernemq:*" }}'
89 - tags: "zookeeper"
@@ -257,6 +259,11 @@ compose:
259 module: tor
260 name: docker_{{.Name}}
261 address: {{.Address}}
262 + - selector: "varnish"
263 + template: |
264 + module: varnish
265 + name: docker_{{.Name}}
266 + docker_container: {{.Name}}
267 - selector: "vernemq"
268 template: |
269 module: vernemq
src/go/plugin/go.d/modules/varnish/config_schema.json
+5
@@ -22,6 +22,11 @@
22 "title": "Instance name",
23 "description": "Specifies the name of the Varnish instance to collect metrics from.",
24 "type": "string"
25 + },
26 + "docker_container": {
27 + "title": "Docker container name",
28 + "description": "Specifies the name of the Docker container where the Varnish instance is running. If set, the `varnishstat` command will be executed within this container.",
29 + "type": "string"
30 }
31 },
32 "required": [],
src/go/plugin/go.d/modules/varnish/exec.go
+34 -1
@@ -6,16 +6,18 @@ import (
6 "context"
7 "fmt"
8 "os/exec"
9 + "strconv"
10 "time"
11
12 "github.com/netdata/netdata/go/plugins/logger"
13 + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/dockerhost"
14 )
15
16 type varnishstatBinary interface {
17 statistics() ([]byte, error)
18 }
19
18 -func newVarnishstatBinary(binPath string, cfg Config, log *logger.Logger) varnishstatBinary {
20 +func newVarnishstatExecBinary(binPath string, cfg Config, log *logger.Logger) varnishstatBinary {
21 return &varnishstatExec{
22 Logger: log,
23 binPath: binPath,
@@ -46,3 +48,34 @@ func (e *varnishstatExec) statistics() ([]byte, error) {
48
49 return bs, nil
50 }
51 +
52 +func newVarnishstatDockerExecBinary(cfg Config, log *logger.Logger) varnishstatBinary {
53 + return &varnishstatDockerExec{
54 + Logger: log,
55 + timeout: cfg.Timeout.Duration(),
56 + instanceName: cfg.InstanceName,
57 + container: cfg.DockerContainer,
58 + }
59 +}
60 +
61 +type varnishstatDockerExec struct {
62 + *logger.Logger
63 +
64 + timeout time.Duration
65 + instanceName string
66 + container string
67 +}
68 +
69 +func (e *varnishstatDockerExec) statistics() ([]byte, error) {
70 + ctx, cancel := context.WithTimeout(context.Background(), e.timeout)
71 + defer cancel()
72 +
73 + timeS := strconv.Itoa(max(int(e.timeout.Seconds()), 1))
74 +
75 + args := []string{"-1", "-t", timeS}
76 + if e.instanceName != "" {
77 + args = append(args, "-n", e.instanceName)
78 + }
79 +
80 + return dockerhost.Exec(ctx, e.container, "varnishstat", args...)
81 +}
src/go/plugin/go.d/modules/varnish/init.go
+5 -1
@@ -11,6 +11,10 @@ import (
11 )
12
13 func (v *Varnish) initVarnishstatBinary() (varnishstatBinary, error) {
14 + if v.Config.DockerContainer != "" {
15 + return newVarnishstatDockerExecBinary(v.Config, v.Logger), nil
16 + }
17 +
18 ndsudoPath := filepath.Join(executable.Directory, "ndsudo")
19
20 if _, err := os.Stat(ndsudoPath); err != nil {
@@ -18,7 +22,7 @@ func (v *Varnish) initVarnishstatBinary() (varnishstatBinary, error) {
22
23 }
24
21 - varnishstat := newVarnishstatBinary(ndsudoPath, v.Config, v.Logger)
25 + varnishstat := newVarnishstatExecBinary(ndsudoPath, v.Config, v.Logger)
26
27 return varnishstat, nil
28 }
src/go/plugin/go.d/modules/varnish/metadata.yaml
+4
@@ -71,6 +71,10 @@ modules:
71 description: "Specifies the name of the Varnish instance to collect metrics from. This corresponds to the `-n` argument used with the [varnishstat](https://varnish-cache.org/docs/trunk/reference/varnishstat.html) command."
72 default_value: ""
73 required: false
74 + - name: docker_container
75 + description: "Specifies the name of the Docker container where the Varnish instance is running. If set, the `varnishstat` command will be executed within this container."
76 + default_value: ""
77 + required: false
78 examples:
79 folding:
80 title: ""
src/go/plugin/go.d/modules/varnish/testdata/config.json
+2 -1
@@ -1,5 +1,6 @@
1 {
2 "update_every": 123,
3 "timeout": 123.123,
4 - "instance_name": "ok"
4 + "instance_name": "ok",
5 + "docker_container": "ok"
6 }
src/go/plugin/go.d/modules/varnish/testdata/config.yaml
+1
@@ -1,3 +1,4 @@
1 update_every: 123
2 timeout: 123.123
3 instance_name: "ok"
4 +docker_container: "ok"
src/go/plugin/go.d/modules/varnish/varnish.go
+4 -3
@@ -39,9 +39,10 @@ func New() *Varnish {
39 }
40
41 type Config struct {
42 - UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
43 - Timeout web.Duration `yaml:"timeout,omitempty" json:"timeout"`
44 - InstanceName string `yaml:"instance_name,omitempty" json:"instance_name,omitempty"`
42 + UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
43 + Timeout web.Duration `yaml:"timeout,omitempty" json:"timeout"`
44 + InstanceName string `yaml:"instance_name,omitempty" json:"instance_name,omitempty"`
45 + DockerContainer string `yaml:"docker_container,omitempty" json:"docker_container,omitempty"`
46 }
47
48 type Varnish struct {
src/go/plugin/go.d/pkg/dockerhost/dockerhost.go
+6 -6
@@ -28,7 +28,7 @@ func FromEnv() string {
28 return fmt.Sprintf("tcp://%s", addr)
29 }
30
31 -func Exec(ctx context.Context, containerId string, cmd string, args ...string) ([]byte, error) {
31 +func Exec(ctx context.Context, container string, cmd string, args ...string) ([]byte, error) {
32 // based on https://github.com/moby/moby/blob/8e610b2b55bfd1bfa9436ab110d311f5e8a74dcb/integration/internal/container/exec.go#L38
33
34 addr := docker.DefaultDockerHost
@@ -51,14 +51,14 @@ func Exec(ctx context.Context, containerId string, cmd string, args ...string) (
51 Cmd: append([]string{cmd}, args...),
52 }
53
54 - createResp, err := cli.ContainerExecCreate(ctx, containerId, execCreateConfig)
54 + createResp, err := cli.ContainerExecCreate(ctx, container, execCreateConfig)
55 if err != nil {
56 - return nil, fmt.Errorf("failed to container exec create ('%s'): %v", containerId, err)
56 + return nil, fmt.Errorf("failed to container exec create ('%s'): %v", container, err)
57 }
58
59 attachResp, err := cli.ContainerExecAttach(ctx, createResp.ID, typesContainer.ExecAttachOptions{})
60 if err != nil {
61 - return nil, fmt.Errorf("failed to container exec attach ('%s'): %v", containerId, err)
61 + return nil, fmt.Errorf("failed to container exec attach ('%s'): %v", container, err)
62 }
63 defer attachResp.Close()
64
@@ -78,7 +78,7 @@ func Exec(ctx context.Context, containerId string, cmd string, args ...string) (
78 select {
79 case err := <-done:
80 if err != nil {
81 - return nil, fmt.Errorf("failed to read response from container ('%s'): %v", containerId, err)
81 + return nil, fmt.Errorf("failed to read response from container ('%s'): %v", container, err)
82 }
83 case <-ctx.Done():
84 return nil, fmt.Errorf("timed out reading response")
@@ -86,7 +86,7 @@ func Exec(ctx context.Context, containerId string, cmd string, args ...string) (
86
87 inspResp, err := cli.ContainerExecInspect(ctx, createResp.ID)
88 if err != nil {
89 - return nil, fmt.Errorf("failed to container exec inspect ('%s'): %v", containerId, err)
89 + return nil, fmt.Errorf("failed to container exec inspect ('%s'): %v", container, err)
90 }
91
92 if inspResp.ExitCode != 0 {