Giter Club home page Giter Club logo

puma-plugin-statsd's Introduction

Puma Statsd Plugin

Puma integration with statsd for easy tracking of key metrics that puma can provide:

Gauges:

  • puma.workers - The number of distinct process running. In single mode this will be 1, in cluster mode the number of worker processes
  • puma.old_workers - The number of worker processes that are about to be shut down as part of a phased restart. Will normally be 0
  • puma.booted_workers - The number of worker processes that are in a booted state
  • puma.running - The number of worker threads currently running. In quiet times, idle threads may be shutdown, but they'll start back up again when traffic arrives
  • puma.backlog - The number of requests that have made it to a worker but are yet to be processed. This will normally be zero, as requests queue on the tcp/unix socket in front of the master puma process, not in the worker thread pool
  • puma.pool_capacity - The number of idle and unused worker threads. When this is low/zero, puma is running at full capacity and might need scaling up
  • puma.max_threads - The maximum number of worker threads that might run at one time
  • puma.percent_busy - The percentage of busy threads calculated as pool capacity relative to max threads
  • puma.requests_count - Total number of requests served by this puma since it started

Counters:

  • puma.requests - The number of requests served since the previous report

Installation

Add this gem to your Gemfile with puma and then bundle:

gem "puma"
gem "puma-plugin-statsd"

Add it to your puma config:

# config/puma.rb

bind "http://127.0.0.1:9292"

workers 1
threads 8, 16

plugin :statsd

Configuration

Statsd Connection

By default the plugin assumes statsd is available at 127.0.0.1. If that's true in your environment, just start puma like normal:

bundle exec puma

If statsd isn't on 127.0.0.1 or the UDP port is non-standard, you can configure them using optional environment variables:

STATSD_HOST=127.0.0.1 STATSD_PORT=9125 bundle exec puma

Some setups have statsd listening on a Unix socket rather than UDP. In that case, specify the socket path:

STATSD_SOCKET_PATH=/tmp/statsd.socket bundle exec puma

Interval

By default values will be reported to statsd every 2 seconds. To customise that internal, set the STATSD_INTERVAL_SECONDS environment variable.

STATSD_INTERVAL_SECONDS=1 bundle exec puma

Fractional seconds are supported. Here's how you'd opt into 500ms:

STATSD_INTERVAL_SECONDS="0.5" bundle exec puma

Prefix

In some environments you may want to prefix the metric names. To report foo.puma.pool_capacity instead of puma.pool_capacity:

STATSD_METRIC_PREFIX=foo bundle exec puma

Datadog Integration

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 environment variables.

DD_TAGS

DD_TAGS: Set this to a space-separated list of tags, using the datadog agent standard format.

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

DD_TAGS="env:test simple-tag-0 tag-key-1:tag-value-1" bundle exec puma

DD_ENV, DD_SERVICE, DD_VERSION, DD_ENTITY_ID

The env, service, version and dd.internal.entity_id tags have special meaning to datadog, and they can be set using the above environment variables. These are the conventional environment variables recommended by datadog, so they're likely to be set in many deployments.

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.

You can set it on your pods like this:

env:
  - name: MY_POD_NAME
    valueFrom:
      fieldRef:
        fieldPath: metadata.name

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 deployment might look something like:

env:
  - name: STATSD_GROUPING
    value: deployment-foo

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/yob/puma-plugin-statsd.

Testing the data being sent to statsd

Start a pretend statsd server that listens for UDP packets on port 8125.

If you've installed the gem in your app:

# only need to install the binstub once
bundle binstubs puma-plugin-statsd
./bin/statsd-to-stdout

If you are developing/testing this gem locally:

./bin/statsd-to-stdout

Start puma:

STATSD_HOST=127.0.0.1 bundle exec puma devtools/config.ru --config devtools/puma-config.rb

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/

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

Acknowledgements

This gem is a fork of the excellent puma-plugin-systemd by Samuel Cochran.

Other puma plugins that were helpful references:

The puma docs were also helpful.

License

The gem is available as open source under the terms of the MIT License.

puma-plugin-statsd's People

Contributors

annaswims avatar bdewater avatar cjlarose avatar danarnold avatar gottfrois avatar jacobat avatar jar349 avatar juanitofatas avatar kimvsparrow avatar mongey avatar naoty avatar olleolleolle avatar openbl avatar oskarpearson avatar radiantnode avatar rromanchuk avatar simonsanchez avatar sj26 avatar st-eugenekrivdyuk avatar thekidcoder avatar tjsousa avatar tricknotes avatar yob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

puma-plugin-statsd's Issues

Puma 6.0.0

Happy to contribute here, but noticed we have < 6 in our gemspec. Is there an expected issue with the Puma upgrade? What can I do to help?

Configure StatsD prefix

Hi @yob,

Thanks a lot for the plugin.

Would it be possible to add an option to select the StatsD prefix?

Currently all the metrics start with puma but we'd like to be able to pass a prefix to namespace it (by environment for example).

Please let me know.

I should be able to create a PR as well, I'm just unsure on how to pass arguments, thinking something like this:

plugin :statsd(prefix = 'production.')

Help would be much appreciated ๐Ÿ™‡

I created a fork

Hey @yob,

A little message just to let you know that I created a fork from your plugin here: https://github.com/guizmaii/puma-plugin-dogstatsd

I want to thank you for your work. You helped me a lot :)

Initially, I wanted to push you a PR because I wanted to simplify your code and change how the statsd client is booted: no environment variables, just pass an instance of a statsd client to the plugin (which is what I'm doing in my fork).

But, because I removed a lot of things from your plugin, I finally prefered to fork.

Let me know if your interested to merge some of my work in your plugin.
To me, the ideal situation could be that we merge our works. So you keep your plugin, and I delete mine.

Jules ๐Ÿ™‚

Release a new tag

The latest version (v2.1.0) doesn't have the code from #38. Could you release a new tag so that we get these changes through this gem?

document what each metric means

  • pool_capacity the number of idle and unused worker threads. When this is low/zero, puma is running at full capacity and might need scaling up puma/puma#1579
  • backlog the number of requests that have made it to a worker but are yet to be processed. This will normally be zero, as requests queue on the tcp/unix socket in front of the master puma process, not in the worker thread pool puma/puma#1577
  • max_threads - the maximum number of worker threads that might run at one time.
  • running - the number of worker threads currently running. In quiet times, idle threads may be shutdown, but they'll start back up again when traffic arrives
  • requests_count - incrementing count of handled requests puma/puma#2106
  • workers - the number of worker processes
  • booted_workers
  • old_workers - puma/puma#860

Parent process dying when statsd plugin fails to lookup DNS

Hi there,

We've observed a weird behaviour in Production at a relatively frequent rate where Puma will stop responding to the readiness probe in a Kubernetes cluster from time to time.

When correlating these occurrences with logs we've been able to isolate it to a DNS lookup failure when sending the statsd metrics through UDP and the workers dying precisely 2 seconds after the error is logged (which is consistent with the plugin handling of the error). However, we can't tell how this is leading to the master process dying:

2021-06-14 11:06:23.873 +0000 [8] ERROR: ! statsd: notify stats failed:   getaddrinfo: Temporary failure in name resolution
/usr/local/bundle/gems/puma-plugin-statsd-1.2.1/lib/puma/plugin/statsd.rb:23:in `send'
/usr/local/bundle/gems/puma-plugin-statsd-1.2.1/lib/puma/plugin/statsd.rb:23:in `send'
/usr/local/bundle/gems/puma-plugin-statsd-1.2.1/lib/puma/plugin/statsd.rb:177:in `block in stats_loop'
/usr/local/bundle/gems/puma-plugin-statsd-1.2.1/lib/puma/plugin/statsd.rb:171:in `loop'
/usr/local/bundle/gems/puma-plugin-statsd-1.2.1/lib/puma/plugin/statsd.rb:171:in `stats_loop'
/usr/local/bundle/gems/puma-5.3.1/lib/puma/plugin.rb:68:in `block (2 levels) in fire_background'
2021-06-14 11:06:25.873 +0000 [19] ! Detected parent died, dying
2021-06-14 11:06:25.873 +0000 [16] ! Detected parent died, dying
2021-06-14 11:06:25.873 +0000 [11] ! Detected parent died, dying
2021-06-14 11:06:25.873 +0000 [13] ! Detected parent died, dying

Plugin should not fail if no statsd server is available

I am developing a service that uses puma and I wish to use this plugin to report statistics to our datadog service via dogstatsd.

Since dogstatsd is only available in our production network, the app cannot reach the server when running locally or in CI. This precludes me from using this plugin right now. In my opinion, it should be possible for this plugin to not crash when no statsd endpoint is available.

Luckily, you provide one! in devtools/statsd-to-stdout.rb, it's possible to run this local to the application. However, the source code of the repo is needed and I don't have it - or won't have it. Because I install this plugin as a gem. Bundler has a mechanism for this, which is the executables configuration in the gemspec. By making your statsd-to-stdout.rb an executable for which a binstub can be installed (bundle binstubs puma-plugins-statsd), the script will be available without needing the repo source code.

Here is how I imagine using that:

if [ -z "$DOGSTATSD_HOST" ]; then
  # since this is not set, we are running locally or in some other non-prod environment so start a local statsd
  nohup ./bin/statsd-to-stdout > statsd.log &
  echo $! > statsd-to-stdout.pid
  echo "A local statsd sink has been started and is logging to statsd.log"
  echo "To stop the local sink, run 'kill \$(cat statsd-to-stdout.pid)'"
else
  # for puma's statsd plugin to find the correct dogstatsd server
  # see: https://github.com/yob/puma-plugin-statsd#usage
  export STATSD_HOST="$DOGSTATSD_HOST"
  export STATSD_PORT="$DOGSTATSD_PORT"
fi

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.