skylight 0.8.0.beta.1 → 0.8.0.beta.3
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 +4 -4
- data/CHANGELOG.md +14 -0
- data/lib/skylight/config.rb +2 -1
- data/lib/skylight/core.rb +5 -4
- data/lib/skylight/formatters/http.rb +1 -8
- data/lib/skylight/instrumenter.rb +4 -4
- data/lib/skylight/normalizers.rb +10 -6
- data/lib/skylight/normalizers/action_controller/process_action.rb +1 -13
- data/lib/skylight/normalizers/action_controller/send_file.rb +1 -27
- data/lib/skylight/normalizers/action_view/render_collection.rb +1 -4
- data/lib/skylight/normalizers/action_view/render_partial.rb +1 -4
- data/lib/skylight/normalizers/action_view/render_template.rb +1 -4
- data/lib/skylight/normalizers/active_record/sql.rb +5 -39
- data/lib/skylight/normalizers/active_support/cache_clear.rb +2 -2
- data/lib/skylight/normalizers/active_support/cache_decrement.rb +2 -2
- data/lib/skylight/normalizers/active_support/cache_delete.rb +2 -2
- data/lib/skylight/normalizers/active_support/cache_exist.rb +2 -2
- data/lib/skylight/normalizers/active_support/cache_fetch_hit.rb +2 -2
- data/lib/skylight/normalizers/active_support/cache_generate.rb +2 -2
- data/lib/skylight/normalizers/active_support/cache_increment.rb +2 -2
- data/lib/skylight/normalizers/active_support/cache_read.rb +2 -2
- data/lib/skylight/normalizers/active_support/cache_read_multi.rb +2 -2
- data/lib/skylight/normalizers/active_support/cache_write.rb +2 -2
- data/lib/skylight/normalizers/default.rb +2 -4
- data/lib/skylight/normalizers/grape/endpoint.rb +30 -0
- data/lib/skylight/normalizers/grape/endpoint_render.rb +26 -0
- data/lib/skylight/normalizers/grape/endpoint_run.rb +33 -0
- data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +23 -0
- data/lib/skylight/normalizers/moped/query.rb +12 -58
- data/lib/skylight/probes/grape.rb +29 -61
- data/lib/skylight/railtie.rb +3 -3
- data/lib/skylight/subscriber.rb +13 -4
- data/lib/skylight/trace.rb +14 -42
- data/lib/skylight/version.rb +1 -1
- metadata +6 -3
- data/lib/skylight/grape.rb +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0993e8d64b2871c815490a9f891733c1a6beaf7d
|
4
|
+
data.tar.gz: c003faa733b2421b9cca0843ee188333556a045e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5da96227e2f82d8f035f71647d8a3bbbcbd65655c16bf3bc5a1ec244a30cf95dd50747b047919c7d6931d8982e51bae69edb68e84ad6da2e6efaeb0c6babd2c5
|
7
|
+
data.tar.gz: ff421edd707482cbf4e750d86b9977925448d1159bce989a72fd58852dec1197f8ef1066dea0b70046f76aed7afbf2f10896d6590ccb10b8b2356f0f3950997d
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 0.8.0-beta.3 (August 10, 2015)
|
2
|
+
|
3
|
+
* [BUGFIX] Fix require issue in Grape probe
|
4
|
+
|
5
|
+
## 0.8.0-beta.2 (August 10, 2015) [YANKED]
|
6
|
+
|
7
|
+
* [FEATURE] Process ERB in config/skylight.yml
|
8
|
+
* [IMPROVEMENT] Switch Grape instrumentation to use ActiveSupport::Notifications hooks provided by future Grape versions.
|
9
|
+
* [IMPROVEMENT] Internal cleanup
|
10
|
+
|
1
11
|
## 0.8.0-beta.1 (August 4, 2015)
|
2
12
|
|
3
13
|
* [FEATURE] Add Grape instumentation
|
@@ -60,6 +70,10 @@
|
|
60
70
|
* Featherweight Agent: lowered CPU and memory overhead
|
61
71
|
* [IMPROVEMENT] Add support for ignoring an endpoint by name
|
62
72
|
|
73
|
+
## 0.3.21 (October 8, 2014)
|
74
|
+
|
75
|
+
* [BUGFIX] Skylight crashing on start won't crash entire app
|
76
|
+
|
63
77
|
## 0.3.20 (September 3, 2014)
|
64
78
|
|
65
79
|
* [BUGFIX] Fix app name fetching on Windows for `skylight setup`
|
data/lib/skylight/config.rb
CHANGED
@@ -3,6 +3,7 @@ require 'yaml'
|
|
3
3
|
require 'fileutils'
|
4
4
|
require 'thread'
|
5
5
|
require 'openssl'
|
6
|
+
require 'erb'
|
6
7
|
require 'skylight/util/hostname'
|
7
8
|
require 'skylight/util/logging'
|
8
9
|
require 'skylight/util/platform'
|
@@ -181,7 +182,7 @@ module Skylight
|
|
181
182
|
if path
|
182
183
|
error = nil
|
183
184
|
begin
|
184
|
-
attrs = YAML.
|
185
|
+
attrs = YAML.load(ERB.new(File.read(path)).result)
|
185
186
|
error = "empty file" unless attrs
|
186
187
|
error = "invalid format" if attrs && !attrs.is_a?(Hash)
|
187
188
|
rescue Exception => e
|
data/lib/skylight/core.rb
CHANGED
@@ -95,18 +95,19 @@ module Skylight
|
|
95
95
|
category = opts[:category] || DEFAULT_CATEGORY
|
96
96
|
title = opts[:title]
|
97
97
|
desc = opts[:description]
|
98
|
-
|
98
|
+
if opts.key?(:annotations)
|
99
|
+
warn "call to #instrument included deprecated annotations"
|
100
|
+
end
|
99
101
|
else
|
100
102
|
category = DEFAULT_CATEGORY
|
101
103
|
title = opts.to_s
|
102
104
|
desc = nil
|
103
|
-
annotations = nil
|
104
105
|
end
|
105
106
|
|
106
107
|
if block_given?
|
107
|
-
inst.instrument(category, title, desc
|
108
|
+
inst.instrument(category, title, desc) { yield }
|
108
109
|
else
|
109
|
-
inst.instrument(category, title, desc
|
110
|
+
inst.instrument(category, title, desc)
|
110
111
|
end
|
111
112
|
end
|
112
113
|
|
@@ -3,14 +3,7 @@ module Skylight
|
|
3
3
|
module HTTP
|
4
4
|
def self.build_opts(method, scheme, host, port, path, query)
|
5
5
|
{ category: "api.http.#{method.downcase}",
|
6
|
-
title: "#{method.upcase} #{host}"
|
7
|
-
annotations: {
|
8
|
-
method: method.upcase,
|
9
|
-
scheme: scheme,
|
10
|
-
host: host,
|
11
|
-
port: port ? port.to_i : nil,
|
12
|
-
path: path,
|
13
|
-
query: query }}
|
6
|
+
title: "#{method.upcase} #{host}" }
|
14
7
|
end
|
15
8
|
end
|
16
9
|
end
|
@@ -138,7 +138,7 @@ module Skylight
|
|
138
138
|
native_stop
|
139
139
|
end
|
140
140
|
|
141
|
-
def trace(endpoint, cat, title=nil, desc=nil
|
141
|
+
def trace(endpoint, cat, title=nil, desc=nil)
|
142
142
|
# If a trace is already in progress, continue with that one
|
143
143
|
if trace = @trace_info.current
|
144
144
|
return yield(trace) if block_given?
|
@@ -146,7 +146,7 @@ module Skylight
|
|
146
146
|
end
|
147
147
|
|
148
148
|
begin
|
149
|
-
trace = Trace.new(self, endpoint, Util::Clock.nanos, cat, title, desc
|
149
|
+
trace = Trace.new(self, endpoint, Util::Clock.nanos, cat, title, desc)
|
150
150
|
rescue Exception => e
|
151
151
|
log_error e.message
|
152
152
|
t { e.backtrace.join("\n") }
|
@@ -192,7 +192,7 @@ module Skylight
|
|
192
192
|
trace.done(span)
|
193
193
|
end
|
194
194
|
|
195
|
-
def instrument(cat, title=nil, desc=nil
|
195
|
+
def instrument(cat, title=nil, desc=nil)
|
196
196
|
raise ArgumentError, 'cat is required' unless cat
|
197
197
|
|
198
198
|
unless trace = @trace_info.current
|
@@ -210,7 +210,7 @@ module Skylight
|
|
210
210
|
|
211
211
|
cat = "other.#{cat}" unless match?(cat, TIER_REGEX)
|
212
212
|
|
213
|
-
unless sp = trace.instrument(cat, title, desc
|
213
|
+
unless sp = trace.instrument(cat, title, desc)
|
214
214
|
return yield if block_given?
|
215
215
|
return
|
216
216
|
end
|
data/lib/skylight/normalizers.rb
CHANGED
@@ -47,16 +47,16 @@ module Skylight
|
|
47
47
|
@paths = config['normalizers.render.view_paths'] || []
|
48
48
|
end
|
49
49
|
|
50
|
-
def normalize_render(category, payload
|
50
|
+
def normalize_render(category, payload)
|
51
51
|
if path = payload[:identifier]
|
52
|
-
title = relative_path(path
|
52
|
+
title = relative_path(path)
|
53
53
|
path = nil if path == title
|
54
54
|
end
|
55
55
|
|
56
|
-
[ category, title, nil
|
56
|
+
[ category, title, nil ]
|
57
57
|
end
|
58
58
|
|
59
|
-
def relative_path(path
|
59
|
+
def relative_path(path)
|
60
60
|
return path if relative_path?(path)
|
61
61
|
|
62
62
|
root = array_find(@paths) { |p| path.start_with?(p) }
|
@@ -114,8 +114,11 @@ module Skylight
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def normalize(trace, name, payload)
|
117
|
-
|
118
|
-
|
117
|
+
normalizer_for(name).normalize(trace, name, payload)
|
118
|
+
end
|
119
|
+
|
120
|
+
def normalizer_for(name)
|
121
|
+
@normalizers[name] || DEFAULT
|
119
122
|
end
|
120
123
|
end
|
121
124
|
|
@@ -126,6 +129,7 @@ module Skylight
|
|
126
129
|
action_view/render_template
|
127
130
|
active_record/sql
|
128
131
|
active_support/cache
|
132
|
+
grape/endpoint
|
129
133
|
moped/query).each do |file|
|
130
134
|
require "skylight/normalizers/#{file}"
|
131
135
|
end
|
@@ -9,7 +9,7 @@ module Skylight
|
|
9
9
|
|
10
10
|
def normalize(trace, name, payload)
|
11
11
|
trace.endpoint = controller_action(payload)
|
12
|
-
[ CAT, trace.endpoint, nil
|
12
|
+
[ CAT, trace.endpoint, nil ]
|
13
13
|
end
|
14
14
|
|
15
15
|
private
|
@@ -17,18 +17,6 @@ module Skylight
|
|
17
17
|
def controller_action(payload)
|
18
18
|
"#{payload[:controller]}##{payload[:action]}"
|
19
19
|
end
|
20
|
-
|
21
|
-
def normalize_payload(payload)
|
22
|
-
normalized = {}
|
23
|
-
|
24
|
-
PAYLOAD_KEYS.each do |key|
|
25
|
-
val = payload[key]
|
26
|
-
val = val.inspect unless val.is_a?(String) || val.is_a?(Numeric)
|
27
|
-
normalized[key] = val
|
28
|
-
end
|
29
|
-
|
30
|
-
normalized
|
31
|
-
end
|
32
20
|
end
|
33
21
|
end
|
34
22
|
end
|
@@ -17,13 +17,6 @@ module Skylight
|
|
17
17
|
def normalize(trace, name, payload)
|
18
18
|
path = payload[:path]
|
19
19
|
|
20
|
-
annotations = {
|
21
|
-
path: path,
|
22
|
-
filename: payload[:filename],
|
23
|
-
type: normalize_type(payload),
|
24
|
-
disposition: normalize_disposition(payload),
|
25
|
-
status: normalize_status(payload) }
|
26
|
-
|
27
20
|
title = TITLE
|
28
21
|
|
29
22
|
# depending on normalization, we probably want this to eventually
|
@@ -31,7 +24,7 @@ module Skylight
|
|
31
24
|
# deduping strategy first.
|
32
25
|
desc = nil
|
33
26
|
|
34
|
-
[ CAT, title, desc
|
27
|
+
[ CAT, title, desc ]
|
35
28
|
end
|
36
29
|
|
37
30
|
private
|
@@ -47,25 +40,6 @@ module Skylight
|
|
47
40
|
hash
|
48
41
|
end
|
49
42
|
end
|
50
|
-
|
51
|
-
def normalize_type(payload)
|
52
|
-
type = payload[:type] || OCTET_STREAM
|
53
|
-
type = @mimes[type] if type.is_a?(Symbol)
|
54
|
-
type
|
55
|
-
end
|
56
|
-
|
57
|
-
def mime_for(type)
|
58
|
-
@mimes[type] ||= Mime[type].to_s.freeze
|
59
|
-
end
|
60
|
-
|
61
|
-
def normalize_status(payload)
|
62
|
-
status = payload[:status] || 200
|
63
|
-
Rack::Utils.status_code(status)
|
64
|
-
end
|
65
|
-
|
66
|
-
def normalize_disposition(payload)
|
67
|
-
payload[:disposition] || ATTACHMENT
|
68
|
-
end
|
69
43
|
end
|
70
44
|
|
71
45
|
rescue LoadError
|
@@ -26,52 +26,18 @@ module Skylight
|
|
26
26
|
binds = binds.map { |col, val| val.inspect }
|
27
27
|
end
|
28
28
|
|
29
|
-
extracted_title, sql, binds
|
29
|
+
extracted_title, sql, binds = extract_binds(payload, binds)
|
30
30
|
title = extracted_title if extracted_title
|
31
31
|
|
32
|
-
|
33
|
-
annotations = {
|
34
|
-
sql: sql,
|
35
|
-
binds: binds,
|
36
|
-
}
|
37
|
-
end
|
38
|
-
|
39
|
-
[ name, title, sql, annotations ]
|
32
|
+
[ name, title, sql ]
|
40
33
|
end
|
41
34
|
|
42
35
|
private
|
43
36
|
def extract_binds(payload, precalculated)
|
44
|
-
|
45
|
-
[ title, sql, binds, nil ]
|
37
|
+
SqlLexer::Lexer.bindify(payload[:sql], precalculated, true)
|
46
38
|
rescue => e
|
47
|
-
|
48
|
-
|
49
|
-
details = encode(backtrace: e.backtrace,
|
50
|
-
original_exception: {
|
51
|
-
class_name: e.class.name,
|
52
|
-
message: e.message
|
53
|
-
},
|
54
|
-
payload: payload,
|
55
|
-
precalculated: precalculated)
|
56
|
-
|
57
|
-
error = [group, description, details]
|
58
|
-
[ nil, nil, nil, error ]
|
59
|
-
end
|
60
|
-
|
61
|
-
# While operating in place would save memory, some of these passed in items are re-used elsewhere
|
62
|
-
# and, as such, should not be modified.
|
63
|
-
def encode(body)
|
64
|
-
if body.is_a?(Hash)
|
65
|
-
hash = {}
|
66
|
-
body.each{|k,v| hash[k] = encode(v) }
|
67
|
-
hash
|
68
|
-
elsif body.is_a?(Array)
|
69
|
-
body.map{|v| encode(v) }
|
70
|
-
elsif body.respond_to?(:encoding) && (body.encoding == Encoding::BINARY || !body.valid_encoding?)
|
71
|
-
Base64.encode64(body)
|
72
|
-
else
|
73
|
-
body
|
74
|
-
end
|
39
|
+
# TODO: log
|
40
|
+
[ nil, nil, nil ]
|
75
41
|
end
|
76
42
|
end
|
77
43
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Skylight
|
2
|
+
module Normalizers
|
3
|
+
module Grape
|
4
|
+
class Endpoint < Normalizer
|
5
|
+
%w(run
|
6
|
+
render
|
7
|
+
run_filters).each do |type|
|
8
|
+
require "skylight/normalizers/grape/endpoint_#{type}"
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def get_method(endpoint)
|
14
|
+
method = endpoint.options[:method].first
|
15
|
+
method << "..." if endpoint.options[:method].length > 1
|
16
|
+
method
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_path(endpoint)
|
20
|
+
endpoint.options[:path].join("/")
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_namespace(endpoint)
|
24
|
+
::Grape::Namespace.joined_space(endpoint.namespace_stackable(:namespace))
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Skylight
|
2
|
+
module Normalizers
|
3
|
+
module Grape
|
4
|
+
class EndpointRender < Endpoint
|
5
|
+
register "endpoint_render.grape"
|
6
|
+
|
7
|
+
CAT = "app.grape.endpoint".freeze
|
8
|
+
|
9
|
+
def normalize(trace, name, payload)
|
10
|
+
if endpoint = payload[:endpoint]
|
11
|
+
path = get_path(endpoint)
|
12
|
+
namespace = get_namespace(endpoint)
|
13
|
+
method = get_method(endpoint)
|
14
|
+
|
15
|
+
title = [method, namespace, path].join(' ').gsub(/\s+/, ' ')
|
16
|
+
|
17
|
+
[CAT, title, nil]
|
18
|
+
else
|
19
|
+
:skip
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Skylight
|
2
|
+
module Normalizers
|
3
|
+
module Grape
|
4
|
+
class EndpointRun < Endpoint
|
5
|
+
register "endpoint_run.grape"
|
6
|
+
|
7
|
+
def normalize(trace, name, payload)
|
8
|
+
trace.endpoint = get_endpoint_name(payload[:endpoint]) if payload[:endpoint]
|
9
|
+
|
10
|
+
# We don't necessarily want this to be all instrumented since it's fairly internal.
|
11
|
+
# However, it is a good place to get the endpoint name.
|
12
|
+
:skip
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def get_endpoint_name(endpoint)
|
18
|
+
method = get_method(endpoint)
|
19
|
+
path = get_path(endpoint)
|
20
|
+
namespace = get_namespace(endpoint)
|
21
|
+
|
22
|
+
if namespace && !namespace.empty?
|
23
|
+
path = "/#{path}" if path[0] != '/'
|
24
|
+
path = "#{namespace}#{path}"
|
25
|
+
end
|
26
|
+
|
27
|
+
"#{endpoint.options[:for]} [#{method}] #{path}"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Skylight
|
2
|
+
module Normalizers
|
3
|
+
module Grape
|
4
|
+
class EndpointRunFilters < Endpoint
|
5
|
+
register "endpoint_run_filters.grape"
|
6
|
+
|
7
|
+
CAT = "app.grape.filters".freeze
|
8
|
+
|
9
|
+
def normalize(trace, name, payload)
|
10
|
+
filters = payload[:filters]
|
11
|
+
type = payload[:type]
|
12
|
+
|
13
|
+
if (!filters || filters.empty?) || !type
|
14
|
+
return :skip
|
15
|
+
end
|
16
|
+
|
17
|
+
[CAT, "#{type.to_s.capitalize} Filters", nil]
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -29,106 +29,60 @@ module Skylight
|
|
29
29
|
def normalize_query(operation)
|
30
30
|
title = normalize_title("QUERY", operation)
|
31
31
|
|
32
|
-
hash
|
32
|
+
hash = extract_binds(operation.selector)
|
33
33
|
description = hash.to_json
|
34
34
|
|
35
|
-
|
36
|
-
annotations[:skip] = operation.skip
|
37
|
-
if operation.fields
|
38
|
-
annotations[:fields] = operation.fields.select{|k,v| v == 1 }.keys.map(&:to_s)
|
39
|
-
end
|
40
|
-
annotations[:binds] = binds unless binds.empty?
|
41
|
-
|
42
|
-
[CAT, title, description, annotations]
|
35
|
+
[CAT, title, description]
|
43
36
|
end
|
44
37
|
|
45
38
|
def normalize_get_more(operation)
|
46
39
|
title = normalize_title("GET_MORE", operation)
|
47
40
|
|
48
|
-
|
49
|
-
annotations[:limit] = operation.limit
|
50
|
-
|
51
|
-
[CAT, title, nil, annotations]
|
41
|
+
[CAT, title, nil]
|
52
42
|
end
|
53
43
|
|
54
44
|
def normalize_insert(operation)
|
55
45
|
title = normalize_title("INSERT", operation)
|
56
46
|
|
57
|
-
|
58
|
-
annotations[:count] = operation.documents.count
|
59
|
-
|
60
|
-
[CAT, title, nil, annotations]
|
47
|
+
[CAT, title, nil]
|
61
48
|
end
|
62
49
|
|
63
50
|
def normalize_update(operation)
|
64
51
|
title = normalize_title("UPDATE", operation)
|
65
52
|
|
66
|
-
selector_hash
|
67
|
-
update_hash
|
53
|
+
selector_hash = extract_binds(operation.selector)
|
54
|
+
update_hash = extract_binds(operation.update)
|
68
55
|
|
69
56
|
description = { selector: selector_hash, update: update_hash }.to_json
|
70
57
|
|
71
|
-
|
72
|
-
|
73
|
-
binds = {}
|
74
|
-
binds[:selector] = selector_binds unless selector_binds.empty?
|
75
|
-
binds[:update] = update_binds unless update_binds.empty?
|
76
|
-
annotations[:binds] = binds unless binds.empty?
|
77
|
-
|
78
|
-
[CAT, title, description, annotations]
|
58
|
+
[CAT, title, description]
|
79
59
|
end
|
80
60
|
|
81
61
|
def normalize_delete(operation)
|
82
62
|
title = normalize_title("DELETE", operation)
|
83
63
|
|
84
|
-
hash
|
64
|
+
hash = extract_binds(operation.selector)
|
85
65
|
description = hash.to_json
|
86
66
|
|
87
|
-
|
88
|
-
annotations[:binds] = binds unless binds.empty?
|
89
|
-
|
90
|
-
[CAT, title, description, annotations]
|
67
|
+
[CAT, title, description]
|
91
68
|
end
|
92
69
|
|
93
70
|
def normalize_title(type, operation)
|
94
71
|
"#{type} #{operation.collection}"
|
95
72
|
end
|
96
73
|
|
97
|
-
def
|
98
|
-
annotations = {}
|
99
|
-
|
100
|
-
if operation.respond_to?(:flags)
|
101
|
-
flags = operation.flags.map{|f| flag_name(f) }
|
102
|
-
annotations[:flags] = flags unless flags.empty?
|
103
|
-
end
|
104
|
-
|
105
|
-
annotations
|
106
|
-
end
|
107
|
-
|
108
|
-
# Some flags used by Moped don't map directly to the Mongo docs
|
109
|
-
# See http://docs.mongodb.org/meta-driver/latest/legacy/mongodb-wire-protocol/
|
110
|
-
FLAG_MAP = {
|
111
|
-
tailable: "TailableCursor",
|
112
|
-
multi: "MultiUpdate"
|
113
|
-
}
|
114
|
-
|
115
|
-
def flag_name(flag)
|
116
|
-
FLAG_MAP[flag] || flag.to_s.sub(/^[a-z\d]*/) { $&.capitalize }.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }
|
117
|
-
end
|
118
|
-
|
119
|
-
def extract_binds(hash, binds=[])
|
74
|
+
def extract_binds(hash)
|
120
75
|
ret = {}
|
121
76
|
|
122
77
|
hash.each do |k,v|
|
123
78
|
if v.is_a?(Hash)
|
124
|
-
ret[k] = extract_binds(v
|
79
|
+
ret[k] = extract_binds(v)
|
125
80
|
else
|
126
|
-
binds << stringify(hash[k])
|
127
81
|
ret[k] = '?'
|
128
82
|
end
|
129
83
|
end
|
130
84
|
|
131
|
-
|
85
|
+
ret
|
132
86
|
end
|
133
87
|
|
134
88
|
def stringify(value)
|
@@ -3,8 +3,14 @@ module Skylight
|
|
3
3
|
module Grape
|
4
4
|
class Probe
|
5
5
|
def install
|
6
|
-
version = ::Grape::VERSION
|
7
|
-
|
6
|
+
version = Gem::Version.new(::Grape::VERSION)
|
7
|
+
|
8
|
+
if version > Gem::Version.new("0.12.1")
|
9
|
+
# AS::N is built in to newer versions
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
if version < Gem::Version.new("0.10.0")
|
8
14
|
# Using $stderr here isn't great, but we don't have a logger accessible
|
9
15
|
$stderr.puts "[SKYLIGHT] [#{Skylight::VERSION}] The Grape probe only works with version 0.10.0+ " \
|
10
16
|
"and will be disabled."
|
@@ -28,13 +34,8 @@ module Skylight
|
|
28
34
|
# modified block. However, Grape does some odd stuff with the block binding
|
29
35
|
# that makes this difficult to reason about.
|
30
36
|
if original_block = @block
|
31
|
-
opts = {
|
32
|
-
category: "app.grape.endpoint",
|
33
|
-
title: method_name.gsub(/\s+/, ' ')
|
34
|
-
}
|
35
|
-
|
36
37
|
@block = lambda do |endpoint_instance|
|
37
|
-
|
38
|
+
ActiveSupport::Notifications.instrument('endpoint_render.grape', endpoint: endpoint_instance) do
|
38
39
|
original_block.call(endpoint_instance)
|
39
40
|
end
|
40
41
|
end
|
@@ -43,68 +44,35 @@ module Skylight
|
|
43
44
|
|
44
45
|
alias run_without_sk run
|
45
46
|
def run(*args)
|
46
|
-
|
47
|
-
|
48
|
-
run_without_sk(*args)
|
49
|
-
ensure
|
50
|
-
if instrumenter = Skylight::Instrumenter.instance
|
51
|
-
if trace = instrumenter.current_trace
|
52
|
-
# FIXME: How do we handle endpoints with multiple methods?
|
53
|
-
# Currently we'll see things like "PUT POST DELETE PATCH HEAD"
|
54
|
-
|
55
|
-
# OPTION A: GET /prefix/name [v1]
|
56
|
-
# # FIXME: Ideally we wouldn't have to do this, but I don't know
|
57
|
-
# # of a better way
|
58
|
-
# info = route.instance_variable_get :@options
|
59
|
-
|
60
|
-
# # FIXME: Consider whether we should include the module name
|
61
|
-
# name = "#{info[:method]} #{info[:path]}"
|
62
|
-
# name << " [#{info[:version]}]" if info[:version]
|
63
|
-
|
64
|
-
|
65
|
-
# OPTION B: Module::Class GET /name
|
66
|
-
http_method = options[:method].first
|
67
|
-
http_method << "..." if options[:method].length > 1
|
68
|
-
|
69
|
-
path = options[:path].join("/")
|
70
|
-
namespace = ::Grape::Namespace.joined_space(namespace_stackable(:namespace))
|
71
|
-
|
72
|
-
if namespace && !namespace.empty?
|
73
|
-
path = "/#{path}" if path[0] != '/'
|
74
|
-
path = "#{namespace}#{path}"
|
75
|
-
end
|
76
|
-
|
77
|
-
name = "#{options[:for]} [#{http_method}] #{path}"
|
78
|
-
|
79
|
-
trace.endpoint = name
|
80
|
-
end
|
47
|
+
ActiveSupport::Notifications.instrument('endpoint_run.grape', endpoint: self) do
|
48
|
+
run_without_sk(*args)
|
81
49
|
end
|
82
50
|
end
|
83
51
|
|
84
52
|
alias run_filters_without_sk run_filters
|
85
53
|
def run_filters(filters)
|
86
|
-
|
87
|
-
|
88
|
-
|
54
|
+
# Unfortunately, the type isn't provided to the method so we have
|
55
|
+
# to try to guess it by looking at the contents. This is only reliable
|
56
|
+
# if the filters aren't empty.
|
57
|
+
if filters && !filters.empty?
|
58
|
+
type = case filters
|
59
|
+
when befores then :before
|
60
|
+
when before_validations then :before_validation
|
61
|
+
when after_validations then :after_validation
|
62
|
+
when afters then :after
|
63
|
+
else :other
|
64
|
+
end
|
65
|
+
else
|
66
|
+
type = :unknown
|
89
67
|
end
|
90
68
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
when befores then "Before"
|
96
|
-
when before_validations then "Before Validation"
|
97
|
-
when after_validations then "After Validation"
|
98
|
-
when afters then "After"
|
99
|
-
else "Other"
|
100
|
-
end
|
101
|
-
|
102
|
-
opts = {
|
103
|
-
category: "app.grape.filters",
|
104
|
-
title: "#{type} Filters"
|
69
|
+
payload = {
|
70
|
+
endpoint: self,
|
71
|
+
filters: filters,
|
72
|
+
type: type
|
105
73
|
}
|
106
74
|
|
107
|
-
|
75
|
+
ActiveSupport::Notifications.instrument('endpoint_run_filters.grape', payload) do
|
108
76
|
run_filters_without_sk(filters)
|
109
77
|
end
|
110
78
|
end
|
data/lib/skylight/railtie.rb
CHANGED
@@ -13,9 +13,9 @@ module Skylight
|
|
13
13
|
config.skylight.config_path = "config/skylight.yml"
|
14
14
|
|
15
15
|
# The probes to load
|
16
|
-
# net_http and
|
17
|
-
# Also available: excon, redis
|
18
|
-
config.skylight.probes = ['net_http', 'action_view']
|
16
|
+
# net_http, action_view, and grape are on by default
|
17
|
+
# Also available: excon, redis, sinatra, tilt, sequel
|
18
|
+
config.skylight.probes = ['net_http', 'action_view', 'grape']
|
19
19
|
|
20
20
|
initializer 'skylight.configure' do |app|
|
21
21
|
# Load probes even when agent is inactive to catch probe related bugs sooner
|
data/lib/skylight/subscriber.rb
CHANGED
@@ -40,10 +40,20 @@ module Skylight
|
|
40
40
|
return if @instrumenter.disabled?
|
41
41
|
return unless trace = @instrumenter.current_trace
|
42
42
|
|
43
|
-
|
43
|
+
result = normalize(trace, name, payload)
|
44
|
+
|
45
|
+
unless result == :skip
|
46
|
+
case result.size
|
47
|
+
when 4
|
48
|
+
error "old style normalizer; name=#{name.inspect}; normalizer=#{@normalizers.normalizer_for(name).class}"
|
49
|
+
cat, title, desc, _ = result
|
50
|
+
when 3
|
51
|
+
cat, title, desc = result
|
52
|
+
else
|
53
|
+
raise "Invalid normalizer result: #{result.inspect}"
|
54
|
+
end
|
44
55
|
|
45
|
-
|
46
|
-
span = trace.instrument(cat, title, desc, annot)
|
56
|
+
span = trace.instrument(cat, title, desc)
|
47
57
|
end
|
48
58
|
|
49
59
|
trace.notifications << Notification.new(name, span)
|
@@ -53,7 +63,6 @@ module Skylight
|
|
53
63
|
debug "in: name=%s", name.inspect
|
54
64
|
debug "in: payload=%s", payload.inspect
|
55
65
|
debug "out: cat=%s, title=%s, desc=%s", cat.inspect, name.inspect, desc.inspect
|
56
|
-
debug "out: annot=%s", annot.inspect
|
57
66
|
t { e.backtrace.join("\n") }
|
58
67
|
nil
|
59
68
|
end
|
data/lib/skylight/trace.rb
CHANGED
@@ -6,9 +6,9 @@ module Skylight
|
|
6
6
|
|
7
7
|
attr_reader :endpoint, :notifications
|
8
8
|
|
9
|
-
def self.new(instrumenter, endpoint, start, cat, title = nil, desc = nil
|
9
|
+
def self.new(instrumenter, endpoint, start, cat, title = nil, desc = nil)
|
10
10
|
inst = native_new(normalize_time(start), "TODO", endpoint)
|
11
|
-
inst.send(:initialize, instrumenter, cat, title, desc
|
11
|
+
inst.send(:initialize, instrumenter, cat, title, desc)
|
12
12
|
inst.endpoint = endpoint
|
13
13
|
inst
|
14
14
|
end
|
@@ -20,7 +20,7 @@ module Skylight
|
|
20
20
|
(time.to_i / 100_000).to_i
|
21
21
|
end
|
22
22
|
|
23
|
-
def initialize(instrumenter, cat, title, desc
|
23
|
+
def initialize(instrumenter, cat, title, desc)
|
24
24
|
raise ArgumentError, 'instrumenter is required' unless instrumenter
|
25
25
|
|
26
26
|
@instrumenter = instrumenter
|
@@ -29,14 +29,6 @@ module Skylight
|
|
29
29
|
|
30
30
|
@notifications = []
|
31
31
|
|
32
|
-
if Hash === title
|
33
|
-
annot = title
|
34
|
-
title = desc = nil
|
35
|
-
elsif Hash === desc
|
36
|
-
annot = desc
|
37
|
-
desc = nil
|
38
|
-
end
|
39
|
-
|
40
32
|
# create the root node
|
41
33
|
@root = native_start_span(native_get_started_at, cat)
|
42
34
|
native_span_set_title(@root, title) if title
|
@@ -55,16 +47,8 @@ module Skylight
|
|
55
47
|
@instrumenter.config
|
56
48
|
end
|
57
49
|
|
58
|
-
def record(cat, title=nil, desc=nil
|
59
|
-
|
60
|
-
|
61
|
-
if Hash === title
|
62
|
-
annot = title
|
63
|
-
title = desc = nil
|
64
|
-
elsif Hash === desc
|
65
|
-
annot = desc
|
66
|
-
desc = nil
|
67
|
-
end
|
50
|
+
def record(cat, title=nil, desc=nil)
|
51
|
+
return if @broken
|
68
52
|
|
69
53
|
title.freeze if title.is_a?(String)
|
70
54
|
desc.freeze if desc.is_a?(String)
|
@@ -82,18 +66,10 @@ module Skylight
|
|
82
66
|
nil
|
83
67
|
end
|
84
68
|
|
85
|
-
def instrument(cat, title=nil, desc=nil
|
69
|
+
def instrument(cat, title=nil, desc=nil)
|
86
70
|
return if @broken
|
87
71
|
t { "instrument: #{cat}, #{title}" }
|
88
72
|
|
89
|
-
if Hash === title
|
90
|
-
annot = title
|
91
|
-
title = desc = nil
|
92
|
-
elsif Hash === desc
|
93
|
-
annot = desc
|
94
|
-
desc = nil
|
95
|
-
end
|
96
|
-
|
97
73
|
title.freeze if title.is_a?(String)
|
98
74
|
desc.freeze if desc.is_a?(String)
|
99
75
|
|
@@ -104,10 +80,10 @@ module Skylight
|
|
104
80
|
if desc == Instrumenter::TOO_MANY_UNIQUES
|
105
81
|
debug "[SKYLIGHT] [#{Skylight::VERSION}] A payload description produced <too many uniques>"
|
106
82
|
debug "original desc=%s", original_desc
|
107
|
-
debug "cat=%s, title=%s, desc=%s
|
83
|
+
debug "cat=%s, title=%s, desc=%s", cat, title, desc
|
108
84
|
end
|
109
85
|
|
110
|
-
start(now - gc_time, cat, title, desc
|
86
|
+
start(now - gc_time, cat, title, desc)
|
111
87
|
rescue => e
|
112
88
|
error "failed to instrument span; msg=%s", e.message
|
113
89
|
@broken = true
|
@@ -135,7 +111,7 @@ module Skylight
|
|
135
111
|
|
136
112
|
if time > 0
|
137
113
|
t { fmt "tracking GC time; duration=%d", time }
|
138
|
-
stop(start(now - time, GC_CAT, nil, nil
|
114
|
+
stop(start(now - time, GC_CAT, nil, nil), now)
|
139
115
|
end
|
140
116
|
|
141
117
|
stop(@root, now)
|
@@ -164,8 +140,11 @@ module Skylight
|
|
164
140
|
|
165
141
|
private
|
166
142
|
|
167
|
-
def start(time, cat, title, desc
|
168
|
-
|
143
|
+
def start(time, cat, title, desc)
|
144
|
+
sp = native_start_span(self.class.normalize_time(time), cat.to_s)
|
145
|
+
native_span_set_title(sp, title.to_s) if title
|
146
|
+
native_span_set_description(sp, desc.to_s) if desc
|
147
|
+
sp
|
169
148
|
end
|
170
149
|
|
171
150
|
def stop(span, time)
|
@@ -173,13 +152,6 @@ module Skylight
|
|
173
152
|
nil
|
174
153
|
end
|
175
154
|
|
176
|
-
def span(time, cat, title=nil, desc=nil, annot=nil)
|
177
|
-
sp = native_start_span(time, cat.to_s)
|
178
|
-
native_span_set_title(sp, title.to_s) if title
|
179
|
-
native_span_set_description(sp, desc.to_s) if desc
|
180
|
-
sp
|
181
|
-
end
|
182
|
-
|
183
155
|
def gc_time
|
184
156
|
return 0 unless @gc
|
185
157
|
@gc.update
|
data/lib/skylight/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skylight
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.0.beta.
|
4
|
+
version: 0.8.0.beta.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tilde, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -53,7 +53,6 @@ files:
|
|
53
53
|
- lib/skylight/data/cacert.pem
|
54
54
|
- lib/skylight/formatters/http.rb
|
55
55
|
- lib/skylight/gc.rb
|
56
|
-
- lib/skylight/grape.rb
|
57
56
|
- lib/skylight/helpers.rb
|
58
57
|
- lib/skylight/instrumenter.rb
|
59
58
|
- lib/skylight/middleware.rb
|
@@ -77,6 +76,10 @@ files:
|
|
77
76
|
- lib/skylight/normalizers/active_support/cache_read_multi.rb
|
78
77
|
- lib/skylight/normalizers/active_support/cache_write.rb
|
79
78
|
- lib/skylight/normalizers/default.rb
|
79
|
+
- lib/skylight/normalizers/grape/endpoint.rb
|
80
|
+
- lib/skylight/normalizers/grape/endpoint_render.rb
|
81
|
+
- lib/skylight/normalizers/grape/endpoint_run.rb
|
82
|
+
- lib/skylight/normalizers/grape/endpoint_run_filters.rb
|
80
83
|
- lib/skylight/normalizers/moped/query.rb
|
81
84
|
- lib/skylight/probes.rb
|
82
85
|
- lib/skylight/probes/action_view.rb
|
data/lib/skylight/grape.rb
DELETED