dogapi-demo 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.tailor +106 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +157 -0
- data/Gemfile +16 -0
- data/LICENSE +25 -0
- data/README.rdoc +143 -0
- data/Rakefile +50 -0
- data/dogapi-demo.gemspec +32 -0
- data/examples/Capfile +19 -0
- data/examples/custom_event.rb +37 -0
- data/examples/custom_metric.rb +35 -0
- data/lib/capistrano/README.md +13 -0
- data/lib/capistrano/datadog.rb +125 -0
- data/lib/capistrano/datadog/v2.rb +74 -0
- data/lib/capistrano/datadog/v3.rb +64 -0
- data/lib/dogapi-demo.rb +5 -0
- data/lib/dogapi-demo/common.rb +168 -0
- data/lib/dogapi-demo/event.rb +129 -0
- data/lib/dogapi-demo/facade.rb +475 -0
- data/lib/dogapi-demo/metric.rb +34 -0
- data/lib/dogapi-demo/v1.rb +13 -0
- data/lib/dogapi-demo/v1/alert.rb +112 -0
- data/lib/dogapi-demo/v1/comment.rb +62 -0
- data/lib/dogapi-demo/v1/dash.rb +94 -0
- data/lib/dogapi-demo/v1/embed.rb +106 -0
- data/lib/dogapi-demo/v1/event.rb +101 -0
- data/lib/dogapi-demo/v1/metric.rb +118 -0
- data/lib/dogapi-demo/v1/monitor.rb +264 -0
- data/lib/dogapi-demo/v1/screenboard.rb +110 -0
- data/lib/dogapi-demo/v1/search.rb +27 -0
- data/lib/dogapi-demo/v1/service_check.rb +32 -0
- data/lib/dogapi-demo/v1/snapshot.rb +30 -0
- data/lib/dogapi-demo/v1/tag.rb +141 -0
- data/lib/dogapi-demo/v1/user.rb +113 -0
- data/lib/dogapi-demo/version.rb +3 -0
- data/spec/alerts_spec.rb +33 -0
- data/spec/common_spec.rb +37 -0
- data/spec/facade_spec.rb +166 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/cassettes/Alerts/create/returns_HTTP_code_200.yml +114 -0
- data/spec/support/cassettes/Alerts/create/returns_a_valid_event_ID.yml +114 -0
- data/spec/support/cassettes/Alerts/create/returns_the_same_query_as_sent.yml +114 -0
- data/spec/support/cassettes/Facade/Events/emits_aggregate_events.yml +193 -0
- data/spec/support/cassettes/Facade/Events/emits_events_and_retrieves_them.yml +100 -0
- data/spec/support/cassettes/Facade/Events/emits_events_with_specified_priority.yml +98 -0
- data/spec/support/cassettes/Facade/Tags/adds_updates_and_detaches_tags.yml +442 -0
- data/tests/test_alerts.rb +38 -0
- data/tests/test_base.rb +30 -0
- data/tests/test_client.rb +23 -0
- data/tests/test_comments.rb +39 -0
- data/tests/test_dashes.rb +85 -0
- data/tests/test_embed.rb +194 -0
- data/tests/test_monitors.rb +192 -0
- data/tests/test_screenboard.rb +90 -0
- data/tests/test_search.rb +20 -0
- data/tests/test_snapshot.rb +28 -0
- data/tests/test_users.rb +65 -0
- metadata +178 -0
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rdoc/task'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
default_tests = [:spec, :test]
|
7
|
+
|
8
|
+
case RbConfig::CONFIG['ruby_version']
|
9
|
+
when -> (version) { version.start_with?("2.3") }
|
10
|
+
# Not compatible with Ruby 2.3.x
|
11
|
+
else
|
12
|
+
require 'tailor/rake_task'
|
13
|
+
default_tests.unshift(:tailor)
|
14
|
+
|
15
|
+
Tailor::RakeTask.new do |task|
|
16
|
+
task.file_set 'lib/**/*.rb', :code do |style|
|
17
|
+
style.max_line_length 160, :level => :warn
|
18
|
+
style.max_code_lines_in_method 40, :level => :warn
|
19
|
+
end
|
20
|
+
task.file_set 'spec/**/*.rb', :tests do |style|
|
21
|
+
style.max_line_length 160, :level => :warn
|
22
|
+
style.max_code_lines_in_method 40, :level => :warn
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
task :default => default_tests
|
29
|
+
|
30
|
+
Rake::TestTask.new(:test) do |test|
|
31
|
+
test.libs.push 'lib'
|
32
|
+
test.libs.push 'tests'
|
33
|
+
test.test_files = FileList['tests/test_*.rb']
|
34
|
+
end
|
35
|
+
|
36
|
+
# Doc stuff
|
37
|
+
RDoc::Task.new do |rd|
|
38
|
+
rd.main = 'README.rdoc'
|
39
|
+
rd.rdoc_files.include('README.rdoc', 'lib/**/*.rb', 'CHANGELOG.md')
|
40
|
+
rd.options << '--line-numbers' << '--inline-source'
|
41
|
+
rd.rdoc_dir = 'doc'
|
42
|
+
rd.title = 'DogAPI -- DataDog Client'
|
43
|
+
end
|
44
|
+
|
45
|
+
RSpec::Core::RakeTask.new(:spec)
|
46
|
+
|
47
|
+
desc "Find notes in code"
|
48
|
+
task :notes do
|
49
|
+
puts `grep --exclude=Rakefile -r 'OPTIMIZE:\\|FIXME:\\|TODO:' .`
|
50
|
+
end
|
data/dogapi-demo.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dogapi-demo/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'dogapi-demo'
|
8
|
+
spec.version = DogapiDemo::VERSION
|
9
|
+
spec.authors = ['Datadog, Inc.']
|
10
|
+
spec.email = ['packages@datadoghq.com']
|
11
|
+
spec.description = 'Ruby bindings for Datadog\'s API'
|
12
|
+
spec.summary = spec.description
|
13
|
+
spec.homepage = 'http://datadoghq.com/'
|
14
|
+
spec.license = 'BSD'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($\)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.has_rdoc = true
|
22
|
+
spec.extra_rdoc_files = ['README.rdoc']
|
23
|
+
spec.rdoc_options << '--title' << 'DogAPI -- Datadog Client' <<
|
24
|
+
'--main' << 'README.rdoc' <<
|
25
|
+
'--line-numbers' << '--inline-source'
|
26
|
+
|
27
|
+
spec.add_dependency 'multi_json'
|
28
|
+
|
29
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
30
|
+
spec.add_development_dependency 'rake', '~> 10'
|
31
|
+
spec.add_development_dependency 'rdoc'
|
32
|
+
end
|
data/examples/Capfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'capistrano/setup'
|
2
|
+
require 'capistrano/datadog'
|
3
|
+
|
4
|
+
set :datadog_api_key, 'my_api_key'
|
5
|
+
set :stage, :test
|
6
|
+
# set :format, :pretty
|
7
|
+
# set :log_level, :info
|
8
|
+
# set :pty, true
|
9
|
+
|
10
|
+
server "host0", roles: ["thing"]
|
11
|
+
server "host1", roles: ["other_thing"]
|
12
|
+
|
13
|
+
desc "Hello world"
|
14
|
+
task :hello do
|
15
|
+
on roles(:all) do |host|
|
16
|
+
info capture('echo "$(date): Hello from $(whoami)@$(hostname) !"')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'dogapi'
|
3
|
+
|
4
|
+
# Create a simple client
|
5
|
+
# The host is optional here, it's a shortcut to tie event and metrics to a given host
|
6
|
+
#
|
7
|
+
# You typically want to do:
|
8
|
+
# Dogapi::Client.new(your_actual_api_key_as_a_string, ...)
|
9
|
+
# We are using ENV to let you experiment via an environment variable.
|
10
|
+
dog = Dogapi::Client.new(ENV['DATADOG_KEY'])
|
11
|
+
|
12
|
+
# Let's use tags and aggregation
|
13
|
+
# We will send 2 related events, one error and one success.
|
14
|
+
|
15
|
+
dog.emit_event(Dogapi::Event.new("Uh-oh, something bad happened",
|
16
|
+
:msg_title => "Alert! Alert!",
|
17
|
+
:aggregation_key => "job-123",
|
18
|
+
:alert_type => "error",
|
19
|
+
:tags => ["ruby", "dogapi"]
|
20
|
+
))
|
21
|
+
|
22
|
+
dog.emit_event(Dogapi::Event.new("Now that's better",
|
23
|
+
:msg_title => "All systems green",
|
24
|
+
:aggregation_key => "job-123",
|
25
|
+
:alert_type => "success",
|
26
|
+
:tags => ["ruby", "dogapi"]
|
27
|
+
))
|
28
|
+
|
29
|
+
# You should see something like this in your stream:
|
30
|
+
# screenshot: https://img.skitch.com/20120705-3s4icgxfc689x1jtrx1yr1m5k.png
|
31
|
+
|
32
|
+
# And if you graph a metric and want to overlay these events on the graphs
|
33
|
+
# You can use the following query: "tags:dogapi tags:ruby" in the graph editor
|
34
|
+
# screenshot: https://img.skitch.com/20120705-m4h6f4377cbm2d3rctnd6biej9.png
|
35
|
+
|
36
|
+
# Then you can see the events neatly overlaid on your graph
|
37
|
+
# screenshot: https://img.skitch.com/20120705-xybhimti31u4s4m42ac854568h.png
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'dogapi'
|
3
|
+
|
4
|
+
# Create a simple client
|
5
|
+
# The host is optional here, it's a shortcut to tie event and metrics to a given host
|
6
|
+
#
|
7
|
+
# You typically want to do:
|
8
|
+
# Dogapi::Client.new(your_actual_api_key_as_a_string, ...)
|
9
|
+
# We are using ENV to let you experiment via an environment variable.
|
10
|
+
dog = Dogapi::Client.new(ENV['DATADOG_KEY'])
|
11
|
+
|
12
|
+
# Emit points one by one, timestamp is omitted and is the time this call is made.
|
13
|
+
dog.emit_point('test.api.test_metric', 4.0)
|
14
|
+
|
15
|
+
sleep 1
|
16
|
+
|
17
|
+
dog.emit_point('test.api.test_metric', 5.0)
|
18
|
+
|
19
|
+
# Emit a list of points in one go as a list of (timestamp, value)
|
20
|
+
# here we pretend to send a point a minute for the past hour
|
21
|
+
now = Time.now
|
22
|
+
points = (0...60).map do |i|
|
23
|
+
i = 60 - i
|
24
|
+
t = now - (i*60)
|
25
|
+
[t, Math.cos(i) + 1.0]
|
26
|
+
end
|
27
|
+
|
28
|
+
# And emit the data in one call
|
29
|
+
dog.emit_points('test.api.test_metric', points)
|
30
|
+
|
31
|
+
# Emit differents metrics in a single request to be more efficient
|
32
|
+
dog.batch_metrics do
|
33
|
+
dog.emit_point('test.api.test_metric',10)
|
34
|
+
dog.emit_point('test.api.this_other_metric', 1, :type => 'counter')
|
35
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# capistrano/datadog
|
2
|
+
|
3
|
+
Instrument your [Capistrano](https://github.com/capistrano/capistrano) deploys, generating events in Datadog which you can correlate with metrics in order to figure out what caused production issues.
|
4
|
+
|
5
|
+
To set up your Capfile:
|
6
|
+
|
7
|
+
require "capistrano/datadog"
|
8
|
+
set :datadog_api_key, "my_api_key"
|
9
|
+
|
10
|
+
You can find your Datadog API key [here](https://app.datadoghq.com/account/settings#api). If you don't have a Datadog account, you can sign up for one [here](http://www.datadoghq.com/).
|
11
|
+
|
12
|
+
`capistrano/datadog` will capture each Capistrano task that that Capfile runs, including the roles that the task applies to and any logging output that it emits and submits them as events to Datadog at the end of the execution of all the tasks. If sending to Datadog fails for any reason, your scripts will still succeed.
|
13
|
+
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require "etc"
|
2
|
+
require "digest/md5"
|
3
|
+
require "timeout"
|
4
|
+
|
5
|
+
require "dogapi"
|
6
|
+
|
7
|
+
module Capistrano
|
8
|
+
module Datadog
|
9
|
+
# Singleton method for Reporter
|
10
|
+
def self.reporter()
|
11
|
+
@reporter || @reporter = Reporter.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.cap_version()
|
15
|
+
if @cap_version.nil? then
|
16
|
+
if Configuration.respond_to? :instance then
|
17
|
+
@cap_version = :v2
|
18
|
+
else
|
19
|
+
@cap_version = :v3
|
20
|
+
end
|
21
|
+
end
|
22
|
+
@cap_version
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.submit(api_key)
|
26
|
+
begin
|
27
|
+
if api_key
|
28
|
+
dog = Dogapi::Client.new(api_key)
|
29
|
+
reporter.report.each do |event|
|
30
|
+
dog.emit_event event
|
31
|
+
end
|
32
|
+
else
|
33
|
+
puts "No api key set, not submitting to Datadog"
|
34
|
+
end
|
35
|
+
rescue Timeout::Error => e
|
36
|
+
puts "Could not submit to Datadog, request timed out."
|
37
|
+
rescue => e
|
38
|
+
puts "Could not submit to Datadog: #{e.inspect}\n#{e.backtrace.join("\n")}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Collects info about the tasks that ran in order to submit to Datadog
|
43
|
+
class Reporter
|
44
|
+
attr_accessor :current_task
|
45
|
+
|
46
|
+
def initialize()
|
47
|
+
@tasks = []
|
48
|
+
@current_task = nil
|
49
|
+
@logging_output = {}
|
50
|
+
end
|
51
|
+
|
52
|
+
def record_task(task_name, timing, roles, stage=nil, application_name=nil)
|
53
|
+
@tasks << {
|
54
|
+
:name => task_name,
|
55
|
+
:timing => timing,
|
56
|
+
:roles => roles,
|
57
|
+
:stage => stage,
|
58
|
+
:application => application_name
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def record_log(message)
|
63
|
+
if not @logging_output[@current_task]
|
64
|
+
@logging_output[@current_task] = []
|
65
|
+
end
|
66
|
+
@logging_output[@current_task] << message
|
67
|
+
end
|
68
|
+
|
69
|
+
def report()
|
70
|
+
hostname = %x[hostname -f].strip
|
71
|
+
user = Etc.getlogin
|
72
|
+
|
73
|
+
# Lazy randomness
|
74
|
+
aggregation_key = Digest::MD5.hexdigest "#{Time.new}|#{rand}"
|
75
|
+
|
76
|
+
# Convert the tasks into Datadog events
|
77
|
+
@tasks.map do |task|
|
78
|
+
name = task[:name]
|
79
|
+
roles = Array(task[:roles]).map(&:to_s).sort
|
80
|
+
tags = ["#capistrano"] + (roles.map { |t| '#role:' + t })
|
81
|
+
if !task[:stage].nil? and !task[:stage].empty? then
|
82
|
+
tags << "#stage:#{task[:stage]}"
|
83
|
+
end
|
84
|
+
application = ''
|
85
|
+
if !task[:application].nil? and !task[:application].empty? then
|
86
|
+
application = ' for ' + task[:application]
|
87
|
+
end
|
88
|
+
title = "%s@%s ran %s%s on %s with capistrano in %.2f secs" % [user, hostname, name, application, roles.join(', '), task[:timing]]
|
89
|
+
type = "deploy"
|
90
|
+
alert_type = "success"
|
91
|
+
source_type = "capistrano"
|
92
|
+
message_content = (@logging_output[name] || []).join('')
|
93
|
+
message = if !message_content.empty? then
|
94
|
+
# Strip out color control characters
|
95
|
+
message_content = sanitize_encoding(message_content).gsub(/\e\[(\d+)m/, '')
|
96
|
+
"@@@\n#{message_content}@@@" else "" end
|
97
|
+
|
98
|
+
Dogapi::Event.new(message,
|
99
|
+
:msg_title => title,
|
100
|
+
:event_type => type,
|
101
|
+
:event_object => aggregation_key,
|
102
|
+
:alert_type => alert_type,
|
103
|
+
:source_type_name => source_type,
|
104
|
+
:tags => tags
|
105
|
+
)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def sanitize_encoding(string)
|
110
|
+
return string unless defined?(::Encoding) && string.encoding == Encoding::BINARY
|
111
|
+
string.encode(Encoding::UTF_8, Encoding::BINARY, invalid: :replace, undef: :replace, replace: '')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
case Capistrano::Datadog::cap_version
|
119
|
+
when :v2
|
120
|
+
require 'capistrano/datadog/v2'
|
121
|
+
when :v3
|
122
|
+
require 'capistrano/datadog/v3'
|
123
|
+
else
|
124
|
+
puts "Unknown version: #{Capistrano::Datadog::cap_version.inspect}"
|
125
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require "benchmark"
|
2
|
+
require "delegate"
|
3
|
+
|
4
|
+
# Capistrano v2
|
5
|
+
|
6
|
+
# Monkeypatch capistrano to collect data about the tasks that it's running
|
7
|
+
module Capistrano
|
8
|
+
class Configuration
|
9
|
+
module Execution
|
10
|
+
# Attempts to locate the task at the given fully-qualified path, and
|
11
|
+
# execute it. If no such task exists, a Capistrano::NoSuchTaskError
|
12
|
+
# will be raised.
|
13
|
+
# Also, capture the time the task took to execute, and the logs it
|
14
|
+
# outputted for submission to Datadog
|
15
|
+
def find_and_execute_task(path, hooks = {})
|
16
|
+
task = find_task(path) or raise NoSuchTaskError, "the task `#{path}' does not exist"
|
17
|
+
result = nil
|
18
|
+
reporter = Capistrano::Datadog.reporter
|
19
|
+
task_name = task.fully_qualified_name
|
20
|
+
timing = Benchmark.measure(task_name) do
|
21
|
+
# Set the current task so that the logger knows which task to
|
22
|
+
# associate the logs with
|
23
|
+
reporter.current_task = task_name
|
24
|
+
trigger(hooks[:before], task) if hooks[:before]
|
25
|
+
result = execute_task(task)
|
26
|
+
trigger(hooks[:after], task) if hooks[:after]
|
27
|
+
reporter.current_task = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# Record the task name, its timing and roles
|
31
|
+
roles = task.options[:roles]
|
32
|
+
if roles.is_a? Proc
|
33
|
+
roles = roles.call
|
34
|
+
end
|
35
|
+
reporter.record_task(task_name, timing.real, roles, task.namespace.variables[:stage], fetch(:application))
|
36
|
+
|
37
|
+
# Return the original result
|
38
|
+
result
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Logger
|
44
|
+
# Make the device attribute writeable so we can swap it out
|
45
|
+
# with something that captures logging out by task
|
46
|
+
attr_accessor :device
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
module Capistrano
|
52
|
+
module Datadog
|
53
|
+
class LogCapture < SimpleDelegator
|
54
|
+
def puts(message)
|
55
|
+
Capistrano::Datadog::reporter.record_log message
|
56
|
+
__getobj__.puts message
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
Configuration.instance(:must_exist).load do
|
61
|
+
# Wrap the existing logging target with the Datadog capture class
|
62
|
+
logger.device = Datadog::LogCapture.new logger.device
|
63
|
+
|
64
|
+
# Trigger the Datadog submission once all the tasks have run
|
65
|
+
on :exit, "datadog:submit"
|
66
|
+
namespace :datadog do
|
67
|
+
desc "Submit the tasks that have run to Datadog as events"
|
68
|
+
task :submit do |ns|
|
69
|
+
Capistrano::Datadog.submit variables[:datadog_api_key]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "benchmark"
|
2
|
+
require "sshkit/formatters/pretty"
|
3
|
+
require "sshkit/formatters/simple_text"
|
4
|
+
|
5
|
+
# Capistrano v3 uses Rake's DSL instead of its own
|
6
|
+
|
7
|
+
module Rake
|
8
|
+
class Task
|
9
|
+
alias old_invoke invoke
|
10
|
+
def invoke(*args)
|
11
|
+
result = nil
|
12
|
+
reporter = Capistrano::Datadog.reporter
|
13
|
+
task_name = name
|
14
|
+
reporter.current_task = task_name
|
15
|
+
timing = Benchmark.measure(task_name) do
|
16
|
+
result = old_invoke(*args)
|
17
|
+
end
|
18
|
+
reporter.record_task(task_name, timing.real, roles,
|
19
|
+
Capistrano::Configuration.env.fetch(:stage), Capistrano::Configuration.env.fetch(:application))
|
20
|
+
result
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module Capistrano
|
26
|
+
module Datadog
|
27
|
+
class CaptureIO
|
28
|
+
def initialize(wrapped)
|
29
|
+
@wrapped = wrapped
|
30
|
+
end
|
31
|
+
|
32
|
+
def write(*args)
|
33
|
+
@wrapped.write(*args)
|
34
|
+
args.each { |arg| Capistrano::Datadog.reporter.record_log(arg) }
|
35
|
+
end
|
36
|
+
alias :<< :write
|
37
|
+
|
38
|
+
def close
|
39
|
+
@wrapped.close
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module SSHKit
|
46
|
+
module Formatter
|
47
|
+
class Pretty
|
48
|
+
def initialize(oio)
|
49
|
+
super(Capistrano::Datadog::CaptureIO.new(oio))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class SimpleText
|
54
|
+
def initialize(oio)
|
55
|
+
super(Capistrano::Datadog::CaptureIO.new(oio))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
at_exit do
|
62
|
+
api_key = Capistrano::Configuration.env.fetch :datadog_api_key
|
63
|
+
Capistrano::Datadog.submit api_key
|
64
|
+
end
|