skylight 0.8.0.beta.1 → 0.8.0.beta.3
Sign up to get free protection for your applications and to get access to all the features.
- 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