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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/lib/skylight/config.rb +2 -1
  4. data/lib/skylight/core.rb +5 -4
  5. data/lib/skylight/formatters/http.rb +1 -8
  6. data/lib/skylight/instrumenter.rb +4 -4
  7. data/lib/skylight/normalizers.rb +10 -6
  8. data/lib/skylight/normalizers/action_controller/process_action.rb +1 -13
  9. data/lib/skylight/normalizers/action_controller/send_file.rb +1 -27
  10. data/lib/skylight/normalizers/action_view/render_collection.rb +1 -4
  11. data/lib/skylight/normalizers/action_view/render_partial.rb +1 -4
  12. data/lib/skylight/normalizers/action_view/render_template.rb +1 -4
  13. data/lib/skylight/normalizers/active_record/sql.rb +5 -39
  14. data/lib/skylight/normalizers/active_support/cache_clear.rb +2 -2
  15. data/lib/skylight/normalizers/active_support/cache_decrement.rb +2 -2
  16. data/lib/skylight/normalizers/active_support/cache_delete.rb +2 -2
  17. data/lib/skylight/normalizers/active_support/cache_exist.rb +2 -2
  18. data/lib/skylight/normalizers/active_support/cache_fetch_hit.rb +2 -2
  19. data/lib/skylight/normalizers/active_support/cache_generate.rb +2 -2
  20. data/lib/skylight/normalizers/active_support/cache_increment.rb +2 -2
  21. data/lib/skylight/normalizers/active_support/cache_read.rb +2 -2
  22. data/lib/skylight/normalizers/active_support/cache_read_multi.rb +2 -2
  23. data/lib/skylight/normalizers/active_support/cache_write.rb +2 -2
  24. data/lib/skylight/normalizers/default.rb +2 -4
  25. data/lib/skylight/normalizers/grape/endpoint.rb +30 -0
  26. data/lib/skylight/normalizers/grape/endpoint_render.rb +26 -0
  27. data/lib/skylight/normalizers/grape/endpoint_run.rb +33 -0
  28. data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +23 -0
  29. data/lib/skylight/normalizers/moped/query.rb +12 -58
  30. data/lib/skylight/probes/grape.rb +29 -61
  31. data/lib/skylight/railtie.rb +3 -3
  32. data/lib/skylight/subscriber.rb +13 -4
  33. data/lib/skylight/trace.rb +14 -42
  34. data/lib/skylight/version.rb +1 -1
  35. metadata +6 -3
  36. data/lib/skylight/grape.rb +0 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b0e3fa37632ad3220389279e789146f96720de4d
4
- data.tar.gz: 6a338bac5dfcaaafa26e1737da491f6281bc5470
3
+ metadata.gz: 0993e8d64b2871c815490a9f891733c1a6beaf7d
4
+ data.tar.gz: c003faa733b2421b9cca0843ee188333556a045e
5
5
  SHA512:
6
- metadata.gz: 5b15f061ab93da78cbe138458d81b93c2019473c46040740c06bdd079179c781b2267f2261d16ef3325bc9c91fff2c459c1a78c731e782ff2bd95f9d4baa2c90
7
- data.tar.gz: 70bb2e9ea8f4effb5d3878a0e6159366ebbdf836f7111f65f004ac9244933420edf1121a9533989c2abb8891261e12a12cc70495c59898c2dcd60a708364fe62
6
+ metadata.gz: 5da96227e2f82d8f035f71647d8a3bbbcbd65655c16bf3bc5a1ec244a30cf95dd50747b047919c7d6931d8982e51bae69edb68e84ad6da2e6efaeb0c6babd2c5
7
+ data.tar.gz: ff421edd707482cbf4e750d86b9977925448d1159bce989a72fd58852dec1197f8ef1066dea0b70046f76aed7afbf2f10896d6590ccb10b8b2356f0f3950997d
@@ -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`
@@ -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.load_file(path)
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
@@ -95,18 +95,19 @@ module Skylight
95
95
  category = opts[:category] || DEFAULT_CATEGORY
96
96
  title = opts[:title]
97
97
  desc = opts[:description]
98
- annotations = opts[:annotations]
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, annotations) { yield }
108
+ inst.instrument(category, title, desc) { yield }
108
109
  else
109
- inst.instrument(category, title, desc, annotations)
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, annot=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, annot)
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, annot=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, annot)
213
+ unless sp = trace.instrument(cat, title, desc)
214
214
  return yield if block_given?
215
215
  return
216
216
  end
@@ -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, annotations)
50
+ def normalize_render(category, payload)
51
51
  if path = payload[:identifier]
52
- title = relative_path(path, annotations)
52
+ title = relative_path(path)
53
53
  path = nil if path == title
54
54
  end
55
55
 
56
- [ category, title, nil, annotations ]
56
+ [ category, title, nil ]
57
57
  end
58
58
 
59
- def relative_path(path, annotations)
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
- normalizer = @normalizers[name] || DEFAULT
118
- normalizer.normalize(trace, name, payload)
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, normalize_payload(payload) ]
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, annotations ]
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
@@ -7,10 +7,7 @@ module Skylight
7
7
  CAT = "view.render.collection".freeze
8
8
 
9
9
  def normalize(trace, name, payload)
10
- normalize_render(
11
- CAT,
12
- payload,
13
- count: payload[:count])
10
+ normalize_render(CAT, payload)
14
11
  end
15
12
  end
16
13
  end
@@ -7,10 +7,7 @@ module Skylight
7
7
  CAT = "view.render.template".freeze
8
8
 
9
9
  def normalize(trace, name, payload)
10
- normalize_render(
11
- CAT,
12
- payload,
13
- partial: 1)
10
+ normalize_render(CAT, payload)
14
11
  end
15
12
  end
16
13
  end
@@ -7,10 +7,7 @@ module Skylight
7
7
  CAT = "view.render.template".freeze
8
8
 
9
9
  def normalize(trace, name, payload)
10
- normalize_render(
11
- CAT,
12
- payload,
13
- partial: 0)
10
+ normalize_render(CAT, payload)
14
11
  end
15
12
  end
16
13
  end
@@ -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, _ = extract_binds(payload, binds)
29
+ extracted_title, sql, binds = extract_binds(payload, binds)
30
30
  title = extracted_title if extracted_title
31
31
 
32
- if sql
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
- title, sql, binds = SqlLexer::Lexer.bindify(payload[:sql], precalculated, true)
45
- [ title, sql, binds, nil ]
37
+ SqlLexer::Lexer.bindify(payload[:sql], precalculated, true)
46
38
  rescue => e
47
- group = "sql_parse"
48
- description = e.inspect
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
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache clear".freeze
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache decrement"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache delete"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache exist?"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache fetch hit"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache generate"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache increment"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache read"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache read multi"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache write"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -4,12 +4,10 @@ module Skylight
4
4
 
5
5
  def normalize(trace, name, payload)
6
6
  if name =~ TIER_REGEX
7
- annot = payload.dup
8
7
  [
9
8
  name,
10
- annot.delete(:title),
11
- annot.delete(:description),
12
- annot
9
+ payload[:title],
10
+ payload[:description]
13
11
  ]
14
12
  else
15
13
  :skip
@@ -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, binds = extract_binds(operation.selector)
32
+ hash = extract_binds(operation.selector)
33
33
  description = hash.to_json
34
34
 
35
- annotations = build_annotations(operation)
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
- annotations = build_annotations(operation)
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
- annotations = build_annotations(operation)
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, selector_binds = extract_binds(operation.selector)
67
- update_hash, update_binds = extract_binds(operation.update)
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
- annotations = build_annotations(operation)
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, binds = extract_binds(operation.selector)
64
+ hash = extract_binds(operation.selector)
85
65
  description = hash.to_json
86
66
 
87
- annotations = build_annotations(operation)
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 build_annotations(operation)
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, binds)[0]
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
- [ret, binds]
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.split('.')
7
- if version[0] == '0' && version[1].to_i < 10
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
- Skylight.instrument(opts) do
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
- # We run the original method first since it gives us access to more information
47
- # about the current state, including populating `route`.
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
- if !filters || filters.empty?
87
- # If there's no filters nothing should happen, but let Grape decide
88
- return run_filters_without_sk(filters)
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
- # Unfortunately, this method only gets passed an array of filters.
92
- # This means we have to compare to known lists to attempt to detect
93
- # the type.
94
- type = case filters
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
- Skylight.instrument(opts) do
75
+ ActiveSupport::Notifications.instrument('endpoint_run_filters.grape', payload) do
108
76
  run_filters_without_sk(filters)
109
77
  end
110
78
  end
@@ -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 action_view are on by default
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
@@ -40,10 +40,20 @@ module Skylight
40
40
  return if @instrumenter.disabled?
41
41
  return unless trace = @instrumenter.current_trace
42
42
 
43
- cat, title, desc, annot = normalize(trace, name, payload)
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
- unless cat == :skip
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
@@ -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, annot = 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, annot)
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, annot)
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, annot=nil)
59
- @return if @broken
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, annot=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, annot=%s", cat, title, desc, annot.inspect
83
+ debug "cat=%s, title=%s, desc=%s", cat, title, desc
108
84
  end
109
85
 
110
- start(now - gc_time, cat, title, desc, annot)
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, {}), now)
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, annot=nil)
168
- span(self.class.normalize_time(time), cat, title, desc, annot)
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
@@ -1,4 +1,4 @@
1
1
  module Skylight
2
- VERSION = '0.8.0-beta.1'
2
+ VERSION = '0.8.0-beta.3'
3
3
  end
4
4
 
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.1
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-04 00:00:00.000000000 Z
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
@@ -1,2 +0,0 @@
1
- require 'skylight'
2
- require 'skylight/probes/grape'