oboe 1.3.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.
- data/LICENSE +4 -0
- data/ext/oboe_metal/extconf.rb +20 -0
- data/ext/oboe_metal/noop/noop.c +7 -0
- data/ext/oboe_metal/src/oboe.hpp +256 -0
- data/ext/oboe_metal/src/oboe_wrap.cxx +3599 -0
- data/init.rb +4 -0
- data/install.rb +1 -0
- data/lib/oboe.rb +13 -0
- data/lib/oboe/api.rb +20 -0
- data/lib/oboe/api/layerinit.rb +37 -0
- data/lib/oboe/api/logging.rb +145 -0
- data/lib/oboe/api/memcache.rb +29 -0
- data/lib/oboe/api/tracing.rb +146 -0
- data/lib/oboe/api/util.rb +37 -0
- data/lib/oboe/config.rb +39 -0
- data/lib/oboe/frameworks/rails/inst/action_controller.rb +86 -0
- data/lib/oboe/frameworks/rails/inst/active_record.rb +291 -0
- data/lib/oboe/frameworks/rails/inst/dalli.rb +45 -0
- data/lib/oboe/frameworks/rails/inst/http.rb +40 -0
- data/lib/oboe/frameworks/rails/inst/memcache.rb +40 -0
- data/lib/oboe/frameworks/rails/inst/memcached.rb +32 -0
- data/lib/oboe/frameworks/rails/inst/rack.rb +29 -0
- data/lib/oboe/frameworks/rails/rails.rb +55 -0
- data/lib/oboe/loading.rb +40 -0
- data/lib/oboe/version.rb +10 -0
- data/lib/oboe_fu.rb +4 -0
- data/lib/oboe_metal.rb +151 -0
- metadata +91 -0
data/init.rb
ADDED
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
#Install hooks here
|
data/lib/oboe.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Copyright (c) 2012 by Tracelytics, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'oboe_metal.so'
|
6
|
+
require 'rbconfig'
|
7
|
+
require 'oboe_metal'
|
8
|
+
require 'oboe/config'
|
9
|
+
require 'oboe/loading'
|
10
|
+
|
11
|
+
rescue LoadError
|
12
|
+
puts "Unsupported Tracelytics environment (no libs). Going No-op."
|
13
|
+
end
|
data/lib/oboe/api.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Copyright (c) 2012 by Tracelytics, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module Oboe
|
5
|
+
module API
|
6
|
+
def self.extend_with_tracing
|
7
|
+
extend Oboe::API::Logging
|
8
|
+
extend Oboe::API::Tracing
|
9
|
+
extend Oboe::API::LayerInit
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.extend_with_noop
|
13
|
+
extend Oboe::API::LoggingNoop
|
14
|
+
extend Oboe::API::TracingNoop
|
15
|
+
extend Oboe::API::LayerInitNoop
|
16
|
+
end
|
17
|
+
|
18
|
+
extend Oboe::API::Util
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Oboe
|
2
|
+
module API
|
3
|
+
module LayerInit
|
4
|
+
# Internal: Report that instrumentation for the given layer has been
|
5
|
+
# installed, as well as the version of instrumentation and version of
|
6
|
+
# layer.
|
7
|
+
#
|
8
|
+
def report_init(layer)
|
9
|
+
platform_info = { '__Init' => 1 }
|
10
|
+
platform_info['RubyVersion'] = RUBY_VERSION
|
11
|
+
platform_info['RailsVersion'] = Rails.version if defined?(Rails)
|
12
|
+
platform_info['OboeVersion'] = Gem.loaded_specs['oboe'].try(:version).to_s
|
13
|
+
|
14
|
+
force_trace do
|
15
|
+
start_trace(layer, nil, platform_info) { }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def force_trace
|
20
|
+
saved_mode = Oboe::Config[:tracing_mode]
|
21
|
+
Oboe::Config[:tracing_mode] = 'always'
|
22
|
+
yield
|
23
|
+
ensure
|
24
|
+
Oboe::Config[:tracing_mode] = saved_mode
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module LayerInitNoop
|
29
|
+
def report_init(layer)
|
30
|
+
end
|
31
|
+
|
32
|
+
def force_trace
|
33
|
+
yield
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# Copyright (c) 2012 by Tracelytics, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module Oboe
|
5
|
+
module API
|
6
|
+
module Logging
|
7
|
+
|
8
|
+
# Public: Report an event in an active trace.
|
9
|
+
#
|
10
|
+
# layer - The layer the reported event belongs to
|
11
|
+
# label - The label for the reported event. See API documentation for
|
12
|
+
# reserved labels and usage.
|
13
|
+
# opts - A hash containing key/value pairs that will be reported along
|
14
|
+
# with this event (optional).
|
15
|
+
#
|
16
|
+
# Example
|
17
|
+
#
|
18
|
+
# log('logical_layer', 'entry')
|
19
|
+
# log('logical_layer', 'info', { :list_length => 20 })
|
20
|
+
# log('logical_layer', 'exit')
|
21
|
+
#
|
22
|
+
# Returns nothing.
|
23
|
+
def log(layer, label, opts={})
|
24
|
+
log_event(layer, label, Oboe::Context.createEvent, opts)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: Report an exception.
|
28
|
+
#
|
29
|
+
# layer - The layer the reported event belongs to
|
30
|
+
# exn - The exception to report
|
31
|
+
#
|
32
|
+
# Example
|
33
|
+
#
|
34
|
+
# begin
|
35
|
+
# function_without_oboe()
|
36
|
+
# rescue Exception => e
|
37
|
+
# log_exception('rails', e)
|
38
|
+
# raise
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# Returns nothing.
|
42
|
+
def log_exception(layer, exn)
|
43
|
+
log(layer, 'error', {
|
44
|
+
:ErrorClass => exn.class.name,
|
45
|
+
:Message => exn.message,
|
46
|
+
:ErrorBacktrace => exn.backtrace.join("\r\n")
|
47
|
+
})
|
48
|
+
end
|
49
|
+
|
50
|
+
# Public: Decide whether or not to start a trace, and report an event
|
51
|
+
# appropriately.
|
52
|
+
#
|
53
|
+
# layer - The layer the reported event belongs to
|
54
|
+
# xtrace - An xtrace metadata string, or nil.
|
55
|
+
# opts - A hash containing key/value pairs that will be reported along
|
56
|
+
# with this event (optional).
|
57
|
+
#
|
58
|
+
# Returns nothing.
|
59
|
+
def log_start(layer, xtrace, opts={})
|
60
|
+
return if Oboe::Config.never?
|
61
|
+
|
62
|
+
if xtrace
|
63
|
+
Oboe::Context.fromString(xtrace)
|
64
|
+
end
|
65
|
+
|
66
|
+
if Oboe::Config.tracing?
|
67
|
+
log_entry(layer, opts)
|
68
|
+
elsif Oboe::Config.always? or Oboe::Config.sample?
|
69
|
+
log_event(layer, 'entry', Oboe::Context.startTrace, opts)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Public: Report an exit event.
|
74
|
+
#
|
75
|
+
# layer - The layer the reported event belongs to
|
76
|
+
#
|
77
|
+
# Returns an xtrace metadata string
|
78
|
+
def log_end(layer, opts={})
|
79
|
+
log_event(layer, 'exit', Oboe::Context.createEvent, opts)
|
80
|
+
xtrace = Oboe::Context.toString
|
81
|
+
Oboe::Context.clear
|
82
|
+
xtrace
|
83
|
+
end
|
84
|
+
|
85
|
+
def log_entry(layer, opts={})
|
86
|
+
log_event(layer, 'entry', Oboe::Context.createEvent, opts)
|
87
|
+
end
|
88
|
+
|
89
|
+
def log_exit(layer, opts={})
|
90
|
+
log_event(layer, 'exit', Oboe::Context.createEvent, opts)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Internal: Report an event.
|
94
|
+
#
|
95
|
+
# layer - The layer the reported event belongs to
|
96
|
+
# label - The label for the reported event. See API documentation for
|
97
|
+
# reserved labels and usage.
|
98
|
+
# opts - A hash containing key/value pairs that will be reported along
|
99
|
+
# with this event (optional).
|
100
|
+
#
|
101
|
+
# Examples
|
102
|
+
#
|
103
|
+
# entry = Oboe::Context.createEvent
|
104
|
+
# log_event('rails', 'entry', exit, { :controller => 'user', :action => 'index' })
|
105
|
+
# exit = Oboe::Context.createEvent
|
106
|
+
# exit.addEdge(entry.getMetadata)
|
107
|
+
# log_event('rails', 'exit', exit)
|
108
|
+
#
|
109
|
+
# Returns nothing.
|
110
|
+
def log_event(layer, label, event, opts={})
|
111
|
+
event.addInfo('Layer', layer.to_s)
|
112
|
+
event.addInfo('Label', label.to_s)
|
113
|
+
|
114
|
+
opts.each do |k, v|
|
115
|
+
event.addInfo(k.to_s, v.to_s) if valid_key? k
|
116
|
+
end if !opts.nil? and opts.any?
|
117
|
+
|
118
|
+
Oboe.reporter.sendReport(event)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
module LoggingNoop
|
123
|
+
def log(layer, label, opts={})
|
124
|
+
end
|
125
|
+
|
126
|
+
def log_exception(layer, exn)
|
127
|
+
end
|
128
|
+
|
129
|
+
def log_start(layer, xtrace, opts={})
|
130
|
+
end
|
131
|
+
|
132
|
+
def log_end(layer, opts={})
|
133
|
+
end
|
134
|
+
|
135
|
+
def log_entry(layer, opts={})
|
136
|
+
end
|
137
|
+
|
138
|
+
def log_exit(layer, opts={})
|
139
|
+
end
|
140
|
+
|
141
|
+
def log_event(layer, label, event, opts={})
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Copyright (c) 2012 by Tracelytics, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
module Oboe
|
5
|
+
module API
|
6
|
+
module Memcache
|
7
|
+
MEMCACHE_OPS = %w{add append cas decr decrement delete fetch get get_multi incr increment prepend replace set}
|
8
|
+
|
9
|
+
def memcache_hit?(result)
|
10
|
+
result.nil? ? 0 : 1
|
11
|
+
end
|
12
|
+
|
13
|
+
def remote_host(key)
|
14
|
+
return unless defined?(Lib.memcached_server_by_key)\
|
15
|
+
and defined?(@struct) and defined?(is_unix_socket?)
|
16
|
+
|
17
|
+
server_as_array = Lib.memcached_server_by_key(@struct, args[0].to_s)
|
18
|
+
if server_as_array.is_a?(Array)
|
19
|
+
server = server_as_array.first
|
20
|
+
if is_unix_socket?(server)
|
21
|
+
return "localhost"
|
22
|
+
elsif defined?(server.hostname)
|
23
|
+
return server.hostname
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# Copyright (c) 2012 by Tracelytics, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module Oboe
|
5
|
+
module API
|
6
|
+
module Tracing
|
7
|
+
|
8
|
+
# Public: Trace a given block of code. Detect any exceptions thrown by
|
9
|
+
# the block and report errors.
|
10
|
+
#
|
11
|
+
# layer - The layer the block of code belongs to.
|
12
|
+
# opts - A hash containing key/value pairs that will be reported along
|
13
|
+
# with the first event of this layer (optional).
|
14
|
+
#
|
15
|
+
# Example
|
16
|
+
#
|
17
|
+
# def computation(n)
|
18
|
+
# fib(n)
|
19
|
+
# raise Exception.new
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# def computation_with_oboe(n)
|
23
|
+
# trace('fib', { :number => n }) do
|
24
|
+
# computation(n)
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# result = computation_with_oboe(1000)
|
29
|
+
#
|
30
|
+
# Returns the result of the block.
|
31
|
+
def trace(layer, opts={})
|
32
|
+
log_entry(layer, opts)
|
33
|
+
begin
|
34
|
+
yield
|
35
|
+
rescue Exception => e
|
36
|
+
log_exception(layer, e)
|
37
|
+
raise
|
38
|
+
ensure
|
39
|
+
log_exit(layer)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Public: Trace a given block of code which can start a trace depending
|
44
|
+
# on configuration and probability. Detect any exceptions thrown by the
|
45
|
+
# block and report errors.
|
46
|
+
#
|
47
|
+
# When start_trace returns control to the calling context, the oboe
|
48
|
+
# context will be cleared.
|
49
|
+
#
|
50
|
+
# layer - The layer the block of code belongs to.
|
51
|
+
# opts - A hash containing key/value pairs that will be reported along
|
52
|
+
# with the first event of this layer (optional).
|
53
|
+
#
|
54
|
+
# Example
|
55
|
+
#
|
56
|
+
# def handle_request(request, response)
|
57
|
+
# # ... code that modifies request and response ...
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# def handle_request_with_oboe(request, response)
|
61
|
+
# result, xtrace = start_trace('rails', request['X-Trace']) do
|
62
|
+
# handle_request(request, response)
|
63
|
+
# end
|
64
|
+
# result
|
65
|
+
# rescue Exception => e
|
66
|
+
# xtrace = e.xtrace
|
67
|
+
# ensure
|
68
|
+
# response['X-trace'] = xtrace
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# Returns a list of length two, the first element of which is the result
|
72
|
+
# of the block, and the second element of which is the oboe context that
|
73
|
+
# was set when the block completed execution.
|
74
|
+
def start_trace(layer, xtrace, opts={})
|
75
|
+
log_start(layer, xtrace, opts)
|
76
|
+
begin
|
77
|
+
result = yield
|
78
|
+
rescue Exception => e
|
79
|
+
log_exception(layer, e)
|
80
|
+
e.instance_variable_set(:@xtrace, log_end(layer))
|
81
|
+
raise
|
82
|
+
end
|
83
|
+
xtrace = log_end(layer)
|
84
|
+
|
85
|
+
[result, xtrace]
|
86
|
+
end
|
87
|
+
|
88
|
+
# Public: Trace a given block of code which can start a trace depending
|
89
|
+
# on configuration and probability. Detect any exceptions thrown by the
|
90
|
+
# block and report errors. Insert the oboe metadata into the provided for
|
91
|
+
# later user.
|
92
|
+
#
|
93
|
+
# The motivating use case for this is HTTP streaming in rails3. We need
|
94
|
+
# access to the exit event's trace id so we can set the header before any
|
95
|
+
# work is done, and before any headers are sent back to the client.
|
96
|
+
#
|
97
|
+
# layer - The layer the block of code belongs to.
|
98
|
+
# target - The target object in which to place the oboe metadata.
|
99
|
+
# opts - A hash containing key/value pairs that will be reported along
|
100
|
+
# with the first event of this layer (optional).
|
101
|
+
#
|
102
|
+
# Example:
|
103
|
+
#
|
104
|
+
# def handle_request(request, response)
|
105
|
+
# # ... code that does something with request and response ...
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# def handle_request_with_oboe(request, response)
|
109
|
+
# start_trace_with_target('rails', request['X-Trace'], response) do
|
110
|
+
# handle_request(request, response)
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
# Returns the result of the block.
|
115
|
+
def start_trace_with_target(layer, xtrace, target, opts={})
|
116
|
+
log_start(layer, xtrace, opts)
|
117
|
+
exit_evt = Oboe::Context.createEvent
|
118
|
+
begin
|
119
|
+
target['X-Trace'] = exit_evt.metadataString() if Oboe::Config.tracing?
|
120
|
+
yield
|
121
|
+
rescue Exception => e
|
122
|
+
log_exception(layer, e)
|
123
|
+
raise
|
124
|
+
ensure
|
125
|
+
exit_evt.addEdge(Oboe::Context.get())
|
126
|
+
log_event(layer, 'exit', exit_evt)
|
127
|
+
Oboe::Context.clear
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
module TracingNoop
|
133
|
+
def trace(layer, opts={})
|
134
|
+
yield
|
135
|
+
end
|
136
|
+
|
137
|
+
def start_trace(layer, xtrace, opts={})
|
138
|
+
[yield, xtrace]
|
139
|
+
end
|
140
|
+
|
141
|
+
def start_trace_with_target(layer, xtrace, target, opts={})
|
142
|
+
yield
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Copyright (c) 2012 by Tracelytics, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module Oboe
|
5
|
+
module API
|
6
|
+
module Util
|
7
|
+
BACKTRACE_CUTOFF = 100
|
8
|
+
|
9
|
+
# Internal: Check whether the provided key is reserved or not. Reserved
|
10
|
+
# keys are either keys that are handled by liboboe calls or the oboe gem.
|
11
|
+
#
|
12
|
+
# key - the key to check.
|
13
|
+
#
|
14
|
+
# Return a boolean indicating whether or not key is reserved.
|
15
|
+
def valid_key?(key)
|
16
|
+
!%w[ Label Layer Edge Timestamp Timestamp_u ].include? key.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
# Internal: Get the current backtrace.
|
20
|
+
#
|
21
|
+
# ignore - Number of frames to ignore at the end of the backtrace. Use
|
22
|
+
# when you know how many layers deep in oboe the call is being
|
23
|
+
# made.
|
24
|
+
#
|
25
|
+
# Returns a string with each frame of the backtrace separated by '\r\n'.
|
26
|
+
def backtrace(ignore=1)
|
27
|
+
frames = Kernel.caller
|
28
|
+
frames_len = frames.size
|
29
|
+
if frames_len - ignore > BACKTRACE_CUTOFF
|
30
|
+
frames[ignore, BACKTRACE_CUTOFF + ignore].unshift("...")
|
31
|
+
else
|
32
|
+
frames.drop(ignore)
|
33
|
+
end.join("\r\n")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/oboe/config.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Copyright (c) 2012 by Tracelytics, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module Oboe
|
5
|
+
# The following is done for compatability with older versions of oboe and
|
6
|
+
# oboe_fu (0.2.x)
|
7
|
+
if not defined?(Oboe::Config)
|
8
|
+
Config = {
|
9
|
+
:tracing_mode => "through",
|
10
|
+
:reporter_host => "127.0.0.1",
|
11
|
+
:sample_rate => 3e5
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
class << Config
|
16
|
+
def always?
|
17
|
+
self[:tracing_mode].to_s == "always"
|
18
|
+
end
|
19
|
+
|
20
|
+
def never?
|
21
|
+
self[:tracing_mode].to_s == "never"
|
22
|
+
end
|
23
|
+
|
24
|
+
def tracing?
|
25
|
+
Oboe::Context.isValid and not never?
|
26
|
+
end
|
27
|
+
|
28
|
+
def start?
|
29
|
+
not Oboe::Context.isValid and always?
|
30
|
+
end
|
31
|
+
|
32
|
+
def sample?
|
33
|
+
# Note that this the only point in the code that currently does and
|
34
|
+
# should ever read the sample rate. When autopilot is released, modify
|
35
|
+
# the line below and that line only.
|
36
|
+
self[:sample_rate].to_i < rand(1e6)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|