yabeda-datadog 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76499b2fc49b319aba467fc5ae335b8eb7a8e978cfb2ab1a5b659ba47d7b1dfa
4
- data.tar.gz: 43c14e0c4f9db28ddb299049cf5c06aeeac5a97ccdb1e3411f71edeb98f2456e
3
+ metadata.gz: a61ee9350adf2ceab80125e940127a919d1fcef9ce84444a41644d689182df0e
4
+ data.tar.gz: 9f941017b4fa519c18a3ed0c4351c76990464a7b9098ab6031fc7f008da8537d
5
5
  SHA512:
6
- metadata.gz: fd582c08f725d7e158119e54ac5b3d6d7edb3d3434725c7652c76d86dec305e09d419bb26bc26392a4e2cf4ec3d9b5987a25b69e5fc330853a22c29910923ad2
7
- data.tar.gz: dcd61b99c6cf2dcec3ba6aa09678b839cb445315a83351a9744840650a4b4d6993ead2521d72736ac89812e01436a44d45eeb009f57e157dfce3f45e15ef098a
6
+ metadata.gz: 97ba2ef03616154f4ae5ff48bad10cda63e8625bd25bc706babd3ab63d26d0b733cdbc831ea5b0ab84c06ea073571e468faab8a7ff2933ebb9188a27ba4709f6
7
+ data.tar.gz: 63cf3ba1a667d8b044fd69004397d7e7579a4a31fd2fff247ef8cb781e0de091928c55660426fe611754b809a48005784e52269a2a7092149fe1ccfcf0f654b3
data/.gitignore CHANGED
@@ -9,3 +9,6 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+
13
+ # environment files
14
+ .datadog-agent.env
data/Gemfile.lock CHANGED
@@ -3,16 +3,18 @@ PATH
3
3
  specs:
4
4
  yabeda-datadog (0.1.0)
5
5
  dogapi
6
+ dogstatsd-ruby
6
7
  yabeda
7
8
 
8
9
  GEM
9
10
  remote: https://rubygems.org/
10
11
  specs:
11
12
  coderay (1.1.2)
12
- concurrent-ruby (1.1.3)
13
+ concurrent-ruby (1.1.4)
13
14
  diff-lcs (1.3)
14
15
  dogapi (1.32.0)
15
16
  multi_json
17
+ dogstatsd-ruby (4.0.0)
16
18
  dry-initializer (2.5.0)
17
19
  method_source (0.9.2)
18
20
  multi_json (1.13.1)
@@ -33,7 +35,7 @@ GEM
33
35
  diff-lcs (>= 1.2.0, < 2.0)
34
36
  rspec-support (~> 3.8.0)
35
37
  rspec-support (3.8.0)
36
- yabeda (0.1.2)
38
+ yabeda (0.1.3)
37
39
  concurrent-ruby
38
40
  dry-initializer
39
41
 
@@ -48,4 +50,4 @@ DEPENDENCIES
48
50
  yabeda-datadog!
49
51
 
50
52
  BUNDLED WITH
51
- 1.17.1
53
+ 1.17.2
data/README.md CHANGED
@@ -2,12 +2,13 @@
2
2
 
3
3
  [Yabeda](https://github.com/yabeda-rb/yabeda) adapter for easy exporting collected custom metrics from your application to the Datadog API.
4
4
 
5
+ ## Prerequisites
5
6
 
6
- ## Installation
7
+ Have an instance of Datadog agent and dogstats-d running. For other installation options of Datadog agent please refer to [Datadog agent documentation](https://docs.datadoghq.com/agent/).
7
8
 
8
- This adapter send metrics to [Datadog API](https://docs.datadoghq.com/api/?lang=ruby) and requires to have and Datadog account with API key. You can obtain your Datadog API key in [Datadog dashboard](https://app.datadoghq.com/account/settings#api). For more information refer to [API documentation](https://docs.datadoghq.com/api/?lang=ruby#authentication).
9
+ ## Installation
9
10
 
10
- Add line to your application's Gemfile:
11
+ Add to your application's Gemfile:
11
12
 
12
13
  ```ruby
13
14
  gem 'yabeda-datadog'
@@ -19,22 +20,38 @@ And then execute:
19
20
 
20
21
  ## Usage
21
22
 
22
- Require this adapter before Yabeda configuration:
23
+ Configure Yabeda metrics. Refer to [Yabeda documentation](https://github.com/yabeda-rb/yabeda) for instruction on how to configure and use Yabeda metrics.
23
24
 
24
- ```ruby
25
- require "yabeda/datadog"
26
- ```
27
-
28
- Refer to [Yabeda documentation](https://github.com/yabeda-rb/yabeda) for instruction how to configure and use Yabeda.
25
+ Please note when configuring Yabeda you have to use Datadog units. Refer to [Datadog unit for metrics documentation](https://docs.datadoghq.com/developers/metrics/#units).
26
+ If a unit of a metric is not supported by Datadog, this unit will not be automatically updated. But you always have the ability to update it manually in Datadog metrics dashboard or by calling API by yourself.
29
27
 
30
28
  Refer to [Datadog metrics documentation](https://docs.datadoghq.com/graphing/metrics/) for working with your metrics in Datadog dashboard.
31
29
 
32
- Please note that configuring Yabeda you have to use Datadog units. Refer to [Datadog unit for metrics documentation](https://docs.datadoghq.com/developers/metrics/#units).
30
+ Start your application. You have to set your `DATADOG_API_KEY` and `DATADOG_APP_KEY` as environment variables.
31
+ You can obtain your Datadog API keys in [Datadog dashboard](https://app.datadoghq.com/account/settings#api).
32
+
33
+ You may specify `DATADOG_AGENT_HOST` and/or `DATADOG_AGENT_PORT` environment variables if your Datadog agent is run not in the same host as an app/code that you collection metrics.
34
+
35
+ You may specify `YABEDA_DATADOG_COLLECT_INTERVAL` environment variable to change default interval to call Yabeda collect blocks (aka collectors).
36
+
37
+ ### Limitations
38
+
39
+ On the first run of your application no metrics metadata will be updated. This is happening because metrics have not yet been collected, thus not been created, and there is nothing to update.
40
+
41
+ ### Example
42
+
43
+ [yabeda-datadog-sidekiq-example](https://github.com/shvetsovdm/yabeda-datadog-sidekiq-example)
33
44
 
34
45
  ## Development
35
46
 
36
47
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
37
48
 
49
+ In can run a dogstats-d instance in a docker container with the following command:
50
+
51
+ $ bin/dev
52
+
53
+ Beware that the agent will collect metrics (a lot) from docker itself and all launched docker containers.
54
+
38
55
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
39
56
 
40
57
  ## Contributing
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
data/bin/dev ADDED
@@ -0,0 +1,11 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ docker run --rm \
6
+ --env-file .datadog-agent.env \
7
+ -v /var/run/docker.sock:/var/run/docker.sock:ro \
8
+ -v /proc/:/host/proc/:ro \
9
+ -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \
10
+ -p 8125:8125/udp \
11
+ datadog/agent:latest
data/examples/script.rb CHANGED
@@ -3,15 +3,15 @@
3
3
  require "bundler/setup"
4
4
  require "yabeda/datadog"
5
5
 
6
- # Put Datadog an API key in DATADOG_API_KEY env variable
7
- # and appliction key in DATADOG_APP_KEY env variable.
8
- # Refer to Datadog integrations dashboard for an API key
6
+ Thread.abort_on_exception = true
9
7
 
10
8
  # To Use this script execute it directly with ruby command.
9
+ # You have to provide DATADOG_API_KEY and DATADOG_APP_KEY
10
+ # environment variables.
11
11
  #
12
12
  # Example:
13
13
  #
14
- # DATADOG_API_KEY="your-datadog-api-key-here" ruby script.rb
14
+ # DATADOG_API_KEY=<your API key> DATADOG_APP_KEY=<your app key> ruby script.rb
15
15
  #
16
16
 
17
17
  Yabeda.configure do
@@ -21,6 +21,6 @@ Yabeda.configure do
21
21
  end
22
22
 
23
23
  start_time = Time.now
24
- Yabeda.yabeda_datadog_gem_examples_script_run_count.increment(device: "developent_computer")
24
+ Yabeda.yabeda_datadog_gem_examples_script_run_count.increment(host: "dev_machine")
25
25
  finish_time = Time.now
26
- Yabeda.yabeda_datadog_gem_examples_script_run_time.set({ device: "developent_computer" }, finish_time - start_time)
26
+ Yabeda.yabeda_datadog_gem_examples_script_run_time.set({ host: "dev_machine" }, finish_time - start_time)
@@ -1,84 +1,83 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dogapi"
3
+ require "yabeda/datadog/metric"
4
+ require "yabeda/datadog/tags"
4
5
  require "yabeda/base_adapter"
6
+ require "datadog/statsd"
7
+ require "dogapi"
5
8
 
6
9
  module Yabeda
7
10
  module Datadog
8
- # DataDog adapter. Sends yabeda metrics as custom metrics to DataDog API.
11
+ DEFAULT_AGENT_HOST = "localhost"
12
+ DEFAULT_AGENT_PORT = 8125
13
+
14
+ # = DataDog adapter.
15
+ #
16
+ # Sends yabeda metrics as custom metrics to DataDog API.
9
17
  # https://docs.datadoghq.com/integrations/ruby/
10
18
  class Adapter < BaseAdapter
11
19
  def register_counter!(counter)
12
- metric = AdapterMetric.new(counter, "counter")
13
- dog.update_metadata(metric.name, metric.metadata)
20
+ metric = Metric.new(counter, "counter")
21
+ Thread.new { metric.update(dogapi) }
14
22
  end
15
23
 
16
24
  def perform_counter_increment!(counter, tags, increment)
17
- metric = AdapterMetric.new(counter, "counter")
18
- tags[:type] = "counter"
19
- dog.emit_point(metric.name, increment, tags)
25
+ metric = Metric.new(counter, "counter")
26
+ dogstatsd.count(metric.name, increment, tags: Tags.build(tags))
20
27
  end
21
28
 
22
29
  def register_gauge!(gauge)
23
- metric = AdapterMetric.new(gauge, "gauge")
24
- dog.update_metadata(metric.name, metric.metadata)
30
+ metric = Metric.new(gauge, "gauge")
31
+ Thread.new { metric.update(dogapi) }
25
32
  end
26
33
 
27
34
  def perform_gauge_set!(gauge, tags, value)
28
- metric = AdapterMetric.new(gauge, "gauge")
29
- tags[:type] = "gauge"
30
- dog.emit_point(metric.name, value, tags)
35
+ metric = Metric.new(gauge, "gauge")
36
+ dogstatsd.gauge(metric.name, value, tags: Tags.build(tags))
31
37
  end
32
38
 
33
- private
34
-
35
- def dog
36
- ::Dogapi::Client.new(ENV["DATADOG_API_KEY"], ENV["DATADOG_APP_KEY"])
37
- end
38
-
39
- Yabeda.register_adapter(:datadog, new)
40
- end
41
-
42
- # Internal adapter representation of metrics
43
- class AdapterMetric
44
- def initialize(metric, type)
45
- @metric = metric
46
- @type = type
39
+ def register_histogram!(histogram)
40
+ # sending many requests in separate threads
41
+ # cause rejections by Datadog API
42
+ Thread.new do
43
+ histogram_metrics(histogram).map do |historgam_sub_metric|
44
+ historgam_sub_metric.update(dogapi)
45
+ end
46
+ end
47
47
  end
48
48
 
49
- attr_reader :type
50
-
51
- def metadata
52
- {
53
- type: type,
54
- description: description,
55
- short_name: name,
56
- unit: unit,
57
- per_unit: per_unit,
58
- }
49
+ def perform_histogram_measure!(historam, tags, value)
50
+ metric = Metric.new(historam, "histogram")
51
+ dogstatsd.histogram(metric.name, value, tags: Tags.build(tags))
59
52
  end
60
53
 
61
- def name
62
- parts = ""
63
- parts += "#{metric.group}." if metric.group
64
- parts + metric.name.to_s
65
- end
54
+ private
66
55
 
67
- def description
68
- metric.comment
56
+ def dogstatsd
57
+ # consider memoization here
58
+ ::Datadog::Statsd.new(
59
+ ENV.fetch("DATADOG_AGENT_HOST", DEFAULT_AGENT_HOST),
60
+ ENV.fetch("DATADOG_AGENT_PORT", DEFAULT_AGENT_PORT),
61
+ )
69
62
  end
70
63
 
71
- def unit
72
- metric.unit
64
+ def dogapi
65
+ # consider memoization here
66
+ ::Dogapi::Client.new(ENV["DATADOG_API_KEY"], ENV["DATADOG_APP_KEY"])
73
67
  end
74
68
 
75
- def per_unit
76
- metric.per
69
+ def histogram_metrics(historgram)
70
+ [
71
+ Metric.new(historgram, "gauge", name_sufix: "avg"),
72
+ Metric.new(historgram, "gauge", name_sufix: "max"),
73
+ Metric.new(historgram, "gauge", name_sufix: "min"),
74
+ Metric.new(historgram, "gauge", name_sufix: "median"),
75
+ Metric.new(historgram, "gauge", name_sufix: "95percentile", unit: nil, per_unit: nil),
76
+ Metric.new(historgram, "rate", name_sufix: "count", unit: nil, per_unit: nil),
77
+ ]
77
78
  end
78
79
 
79
- private
80
-
81
- attr_reader :metric
80
+ Yabeda.register_adapter(:datadog, new)
82
81
  end
83
82
  end
84
83
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yabeda/datadog/units"
4
+
5
+ module Yabeda
6
+ module Datadog
7
+ # = Internal adapter representation of metrics
8
+ class Metric
9
+ def initialize(metric, type, overides = {})
10
+ @metric = metric
11
+ @type = type
12
+ @overides = overides
13
+ end
14
+
15
+ # Datadog API argument
16
+ def metadata
17
+ {
18
+ type: type,
19
+ description: description,
20
+ short_name: name,
21
+ unit: unit,
22
+ per_unit: per_unit,
23
+ }
24
+ end
25
+
26
+ # Datadog API argument
27
+ def name
28
+ [metric.group, metric.name.to_s, overides[:name_sufix]].compact.join(".")
29
+ end
30
+
31
+ # Datadog API argument
32
+ def description
33
+ overides.fetch(:description, metric.comment)
34
+ end
35
+
36
+ # Datadog API argument
37
+ def unit
38
+ overides.fetch(:unit, Unit.find(metric.unit))
39
+ end
40
+
41
+ # Datadog API argument
42
+ def per_unit
43
+ overides.fetch(:per_unit, Unit.find(metric.per))
44
+ end
45
+
46
+ # Update metric metadata
47
+ def update(api)
48
+ api.update_metadata(name, metadata)
49
+ end
50
+
51
+ private
52
+
53
+ attr_reader :metric, :type, :overides
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yabeda
4
+ module Datadog
5
+ # = The logic of working with Datadog tags
6
+ class Tags
7
+ def self.build(tags)
8
+ tags.map { |key, value| "#{key}:#{value}" }
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yabeda
4
+ module Datadog
5
+ # = The logic of working with Datadog units
6
+ class Unit
7
+ # source: https://docs.datadoghq.com/developers/metrics/#units
8
+ AVAILABLE = ["bit", "byte", "kibibyte", "mebibyte", "gibibyte", "tebibyte",
9
+ "pebibyte", "exbibyte", "nanosecond", "microsecond", "millisecond",
10
+ "second", "minute", "hour", "day", "week", "percent_nano", "percent",
11
+ "apdex", "fraction", "connection", "request", "packet", "segment",
12
+ "response", "message", "payload", "timeout", "datagram", "route",
13
+ "session", "process", "thread", "host", "node", "fault", "service",
14
+ "instance", "cpu", "file", "inode", "sector", "block", "buffer",
15
+ "error", "read", "write", "occurrence", "event", "time", "unit",
16
+ "operation", "item", "task", "worker", "resource", "garbage collection",
17
+ "email", "sample", "stage", "monitor", "location", "check", "attempt",
18
+ "device", "update", "method", "job", "container", "execution",
19
+ "throttle", "invocation", "user", "success", "build", "prediction",
20
+ "table", "index", "lock", "transaction", "query", "row", "key",
21
+ "command", "offset", "record", "object", "cursor", "assertion", "scan",
22
+ "document", "shard", "flush", "merge", "refresh", "fetch", "column",
23
+ "commit", "wait", "ticket", "question", "hit", "miss", "eviction",
24
+ "get", "set", "dollar", "cent", "page", "split", "hertz", "kilohertz",
25
+ "megahertz", "gigahertz", "entry", "degree celsius", "degree fahrenheit",
26
+ "nanocore", "microcore", "millicore", "core", "kilocore", "megacore",
27
+ "gigacore", "teracore", "petacore", "exacore",].freeze
28
+
29
+ # Find valid unit
30
+ def self.find(unit)
31
+ unit if unit && AVAILABLE.include?(unit)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Yabeda
4
4
  module Datadog
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
@@ -5,7 +5,18 @@ require "yabeda/datadog/adapter"
5
5
  require "yabeda/datadog/version"
6
6
 
7
7
  module Yabeda
8
- # Namespace for DataDog adapter
8
+ # = Namespace for DataDog adapter
9
9
  module Datadog
10
+ SECOND = 1
11
+ DEFAULT_COLLECT_INTERVAL = 60 * SECOND
12
+
13
+ def self.start_exporter(collect_interval: DEFAULT_COLLECT_INTERVAL)
14
+ Thread.new do
15
+ loop do
16
+ Yabeda.collectors.each(&:call)
17
+ sleep(collect_interval)
18
+ end
19
+ end
20
+ end
10
21
  end
11
22
  end
@@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ["lib"]
29
29
 
30
30
  spec.add_dependency "dogapi"
31
+ spec.add_dependency "dogstatsd-ruby"
31
32
  spec.add_dependency "yabeda"
32
33
 
33
34
  spec.add_development_dependency "bundler", "~> 1.17"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yabeda-datadog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Shvetsov <@shvetsovdm>
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-10 00:00:00.000000000 Z
11
+ date: 2018-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dogapi
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: dogstatsd-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: yabeda
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -112,10 +126,14 @@ files:
112
126
  - README.md
113
127
  - Rakefile
114
128
  - bin/console
129
+ - bin/dev
115
130
  - bin/setup
116
131
  - examples/script.rb
117
132
  - lib/yabeda/datadog.rb
118
133
  - lib/yabeda/datadog/adapter.rb
134
+ - lib/yabeda/datadog/metric.rb
135
+ - lib/yabeda/datadog/tags.rb
136
+ - lib/yabeda/datadog/units.rb
119
137
  - lib/yabeda/datadog/version.rb
120
138
  - yabeda-datadog.gemspec
121
139
  homepage: https://github.com/shvetsovdm/yabeda-datadog