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 support for the DD_TAGS environment variable #18

Merged
merged 1 commit into from
Sep 29, 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
28 changes: 23 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ plugin :statsd

## Usage

Ensure you have an environment variable set that points to a statsd host, then boot your puma app as usual. Optionally you may specify a port (default is 8125).
Ensure you have an environment variable set that points to a statsd host, then boot your puma app as usual. Optionally you may specify a port (default is 8125).

```
STATSD_HOST=127.0.0.1 bundle exec puma
Expand All @@ -53,9 +53,25 @@ metric tags are a non-standard addition to the statsd protocol, supported by
the datadog "dogstatsd" server.

Should you be reporting the puma metrics to a dogstatsd server, you can set
tags via the following two environment variables.
tags via the following three environment variables.

`MY_POD_NAME` adds a `pod_name` tag to the metrics. The `MY_POD_NAME`

#### DD_TAGS

`DD_TAGS`: Set this to a space-separated list of tags, using the
[datadog agent standard format](https://docs.datadoghq.com/agent/docker/?tab=standard#global-options).

For example, you could set this environment variable to set three datadog tags,
and then you can filter by in the datadog interface:

```bash
export DD_TAGS="env:test simple-tag-0 tag-key-1:tag-value-1"
bundle exec rails server
```

#### MY_POD_NAME

`MY_POD_NAME`: Set a `pod_name` tag to the metrics. The `MY_POD_NAME`
environment variable is recommended in the datadog kubernetes setup
documentation, and for puma apps deployed to kubernetes it's very helpful to
have the option to report on specific pods.
Expand All @@ -70,7 +86,9 @@ env:
fieldPath: metadata.name
```

`STATSD_GROUPING` adds a `grouping` tag to the metrics, with a value equal to
#### STATSD_GROUPING

`STATSD_GROUPING`: add a `grouping` tag to the metrics, with a value equal to
the environment variable value. This is particularly helpful in a kubernetes
deployment where each pod has a unique name but you want the option to group
metrics across all pods in a deployment. Setting this on the pods in a
Expand Down Expand Up @@ -100,7 +118,7 @@ Start puma:
Throw some traffic at it, either with curl or a tool like ab:

curl http://127.0.0.1:9292/
ab -n 10000 -c 20 http://127.0.0.1:9292/
ab -n 10000 -c 20 http://127.0.0.1:9292/

Watch the output of the UDP server process - you should see statsd data printed to stdout.

Expand Down
43 changes: 33 additions & 10 deletions lib/puma/plugin/statsd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,9 @@ def enabled?
!!host
end

def send(metric_name:, value:, type:, tags: {})
def send(metric_name:, value:, type:, tags: nil)
data = "#{metric_name}:#{value}|#{STATSD_TYPES.fetch(type)}"
if tags.any?
tag_str = tags.map { |k,v| "#{k}:#{v}" }.join(",")
data = "#{data}|##{tag_str}"
end
data = "#{data}|##{tags}" unless tags.nil?

socket = UDPSocket.new
socket.send(data, 0, host, port)
Expand Down Expand Up @@ -123,15 +120,39 @@ def fetch_stats
end
end

def tags
tags = {}
def environment_variable_tags
# Tags are separated by spaces, and while they are normally a tag and
# value separated by a ':', they can also just be tagged without any
# associated value.
#
# Examples: simple-tag-0 tag-key-1:tag-value-1
#
tags = []

if ENV.has_key?("MY_POD_NAME")
tags[:pod_name] = ENV.fetch("MY_POD_NAME", "no_pod")
tags << "pod_name:#{ENV['MY_POD_NAME']}"
end

if ENV.has_key?("STATSD_GROUPING")
tags[:grouping] = ENV.fetch("STATSD_GROUPING", "no-group")
tags << "grouping:#{ENV['STATSD_GROUPING']}"
end
tags

# Standardised datadog tag attributes, so that we can share the metric
# tags with the application running
#
# https://docs.datadoghq.com/agent/docker/?tab=standard#global-options
#
if ENV.has_key?("DD_TAGS")
ENV["DD_TAGS"].split(/\s+/).each do |t|
tags << t
end
end

# Return nil if we have no environment variable tags. This way we don't
# send an unnecessary '|' on the end of each stat
return nil if tags.empty?

tags.join(",")
end

def prefixed_metric_name(puma_metric)
Expand All @@ -140,6 +161,8 @@ def prefixed_metric_name(puma_metric)

# Send data to statsd every few seconds
def stats_loop
tags = environment_variable_tags

sleep 5
loop do
@launcher.events.debug "statsd: notify statsd"
Expand Down