skylight 0.3.14 → 0.3.17

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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/lib/skylight/config.rb +7 -1
  4. data/lib/skylight/messages/trace.rb +6 -6
  5. data/lib/skylight/normalizers.rb +8 -7
  6. data/lib/skylight/normalizers/action_controller/process_action.rb +35 -0
  7. data/lib/skylight/normalizers/action_controller/send_file.rb +76 -0
  8. data/lib/skylight/normalizers/action_view/render_collection.rb +18 -0
  9. data/lib/skylight/normalizers/action_view/render_partial.rb +18 -0
  10. data/lib/skylight/normalizers/action_view/render_template.rb +18 -0
  11. data/lib/skylight/normalizers/active_record/sql.rb +81 -0
  12. data/lib/skylight/normalizers/active_support/cache.rb +50 -0
  13. data/lib/skylight/normalizers/active_support/cache_clear.rb +16 -0
  14. data/lib/skylight/normalizers/active_support/cache_decrement.rb +16 -0
  15. data/lib/skylight/normalizers/active_support/cache_delete.rb +16 -0
  16. data/lib/skylight/normalizers/active_support/cache_exist.rb +16 -0
  17. data/lib/skylight/normalizers/active_support/cache_fetch_hit.rb +16 -0
  18. data/lib/skylight/normalizers/active_support/cache_generate.rb +16 -0
  19. data/lib/skylight/normalizers/active_support/cache_increment.rb +16 -0
  20. data/lib/skylight/normalizers/active_support/cache_read.rb +16 -0
  21. data/lib/skylight/normalizers/active_support/cache_read_multi.rb +16 -0
  22. data/lib/skylight/normalizers/active_support/cache_write.rb +16 -0
  23. data/lib/skylight/normalizers/moped/query.rb +141 -0
  24. data/lib/skylight/version.rb +1 -1
  25. data/lib/skylight/worker/standalone.rb +3 -3
  26. metadata +37 -26
  27. data/lib/skylight/normalizers/moped.rb +0 -139
  28. data/lib/skylight/normalizers/process_action.rb +0 -34
  29. data/lib/skylight/normalizers/render_collection.rb +0 -16
  30. data/lib/skylight/normalizers/render_partial.rb +0 -16
  31. data/lib/skylight/normalizers/render_template.rb +0 -16
  32. data/lib/skylight/normalizers/send_file.rb +0 -74
  33. data/lib/skylight/normalizers/sql.rb +0 -79
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5620862e4260060cc2887d5fa2e902eeb96af51a
4
- data.tar.gz: 8e664fcdf47316d921921b96286c8b336f6c0892
3
+ metadata.gz: 0fe30001ff54231d9fc09691d32cfbe734b6511e
4
+ data.tar.gz: ba257edb4e82c556e5b86a4e93023d19e9d1fa9f
5
5
  SHA512:
6
- metadata.gz: 0ad66490a91813115f262f0c1640a0a50839bd82f0a81fb32952cd03fede4a742ed220db5d14491b1fda95b0217a5ff3ec48e3ddff6d77a9f4674f4dbf45bae1
7
- data.tar.gz: 122849003b5c4d135c8244d37e65ca1505a8cb421ff874c7d6e1af180e8fe122026155c734645ccf10a7527ad1182fe19cf64d9bab3ad2f0b13a1aa44b103c5b
6
+ metadata.gz: 4862132100ec976e3c8a9a0ba48df3df9323f0b70c4bad5816fb89f6a955c831b2ba07db354437410f00091d53b90d1f1fd517ff5944a7c5b4e14f6a79c692f3
7
+ data.tar.gz: e4a853e6647f09e4f717909e747ccce70b609f08748c1ff268f87aa5eceea4ebc8cfb04cb39ede0d8000de07ca0792c81f37735973f2bf9cbb5ae4bb79db0a2b
@@ -1,3 +1,18 @@
1
+ ## 0.3.17 (July 1, 2014)
2
+
3
+ * Fix warning for Cache.instrument overwrite
4
+
5
+ ## 0.3.16 (July 1, 2014) [YANKED]
6
+
7
+ * Fixed ActiveSupport::Cache monkeypatch
8
+
9
+ ## 0.3.15 (June 30, 2014) [YANKED]
10
+
11
+ * Basic instrumentation for ActiveSupport::Cache
12
+ * Fix incompatibility with old version of rack-mini-profiler
13
+ * Better error messages when config/skylight.yml is invalid
14
+ * Better error messages for non-writeable lock/sockfile path
15
+
1
16
  ## 0.3.14 (June 3, 2014)
2
17
 
3
18
  * Do not build C extension if dependencies (libraries/headers) are
@@ -29,6 +29,7 @@ module Skylight
29
29
  'SKIP_VALIDATION' => :'skip_validation',
30
30
  'AGENT_INTERVAL' => :'agent.interval',
31
31
  'AGENT_KEEPALIVE' => :'agent.keepalive',
32
+ 'AGENT_LOCKFILE' => :'agent.lockfile',
32
33
  'AGENT_SAMPLE_SIZE' => :'agent.sample',
33
34
  'AGENT_SOCKFILE_PATH' => :'agent.sockfile_path',
34
35
  'AGENT_STRATEGY' => :'agent.strategy',
@@ -91,12 +92,17 @@ module Skylight
91
92
  version = nil
92
93
 
93
94
  if path
95
+ error = nil
94
96
  begin
95
97
  attrs = YAML.load_file(path)
98
+ error = "empty file" unless attrs
99
+ error = "invalid format" if attrs && !attrs.is_a?(Hash)
96
100
  rescue Exception => e
97
- raise ConfigError, "could not load config file; msg=#{e.message}"
101
+ error = e.message
98
102
  end
99
103
 
104
+ raise ConfigError, "could not load config file; msg=#{error}" if error
105
+
100
106
  version = File.mtime(path).to_i
101
107
  end
102
108
 
@@ -9,7 +9,7 @@ module Skylight
9
9
  attr_reader :endpoint, :spans, :notifications
10
10
 
11
11
  def endpoint=(value)
12
- @endpoint = value.freeze
12
+ @endpoint = value.is_a?(String) ? value.freeze : value
13
13
  @native_builder.native_set_name(value)
14
14
  end
15
15
 
@@ -22,7 +22,7 @@ module Skylight
22
22
  @native_builder.native_set_name(endpoint)
23
23
 
24
24
  @instrumenter = instrumenter
25
- @endpoint = endpoint.freeze
25
+ @endpoint = endpoint
26
26
  @submitted = false
27
27
  @start = start
28
28
 
@@ -63,8 +63,8 @@ module Skylight
63
63
  desc = nil
64
64
  end
65
65
 
66
- title.freeze
67
- desc.freeze
66
+ title.freeze if title.is_a?(String)
67
+ desc.freeze if desc.is_a?(String)
68
68
 
69
69
  desc = @instrumenter.limited_description(desc)
70
70
 
@@ -86,8 +86,8 @@ module Skylight
86
86
  desc = nil
87
87
  end
88
88
 
89
- title.freeze
90
- desc.freeze
89
+ title.freeze if title.is_a?(String)
90
+ desc.freeze if desc.is_a?(String)
91
91
 
92
92
  original_desc = desc
93
93
  now = Util::Clock.nanos
@@ -120,13 +120,14 @@ module Skylight
120
120
  end
121
121
  end
122
122
 
123
- %w( moped
124
- process_action
125
- render_collection
126
- render_partial
127
- render_template
128
- send_file
129
- sql).each do |file|
123
+ %w( action_controller/process_action
124
+ action_controller/send_file
125
+ action_view/render_collection
126
+ action_view/render_partial
127
+ action_view/render_template
128
+ active_record/sql
129
+ active_support/cache
130
+ moped/query).each do |file|
130
131
  require "skylight/normalizers/#{file}"
131
132
  end
132
133
  end
@@ -0,0 +1,35 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionController
4
+ class ProcessAction < Normalizer
5
+ register "process_action.action_controller"
6
+
7
+ CAT = "app.controller.request".freeze
8
+ PAYLOAD_KEYS = %w[ controller action params format method path ].map(&:to_sym).freeze
9
+
10
+ def normalize(trace, name, payload)
11
+ trace.endpoint = controller_action(payload)
12
+ [ CAT, trace.endpoint, nil, normalize_payload(payload) ]
13
+ end
14
+
15
+ private
16
+
17
+ def controller_action(payload)
18
+ "#{payload[:controller]}##{payload[:action]}"
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
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,76 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionController
4
+
5
+ # Temporary hacks
6
+ begin
7
+ require "action_dispatch/http/mime_type"
8
+ require "action_dispatch/http/mime_types"
9
+ require "rack/utils"
10
+
11
+ class SendFile < Normalizer
12
+ register "send_file.action_controller"
13
+
14
+ CAT = "app.controller.send_file".freeze
15
+ TITLE = "send file".freeze
16
+
17
+ def normalize(trace, name, payload)
18
+ path = payload[:path]
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
+ title = TITLE
28
+
29
+ # depending on normalization, we probably want this to eventually
30
+ # include the full path, but we need to make sure we have a good
31
+ # deduping strategy first.
32
+ desc = nil
33
+
34
+ [ CAT, title, desc, annotations ]
35
+ end
36
+
37
+ private
38
+
39
+ OCTET_STREAM = "application/octet-stream".freeze
40
+ ATTACHMENT = "attachment".freeze
41
+
42
+ def initialize(*)
43
+ super
44
+
45
+ @mimes = Mime::SET.reduce({}) do |hash, mime|
46
+ hash[mime.symbol] = mime.to_s.dup.freeze
47
+ hash
48
+ end
49
+ 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
+ end
70
+
71
+ rescue LoadError
72
+ end
73
+
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,18 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionView
4
+ class RenderCollection < RenderNormalizer
5
+ register "render_collection.action_view"
6
+
7
+ CAT = "view.render.collection".freeze
8
+
9
+ def normalize(trace, name, payload)
10
+ normalize_render(
11
+ CAT,
12
+ payload,
13
+ count: payload[:count])
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionView
4
+ class RenderPartial < RenderNormalizer
5
+ register "render_partial.action_view"
6
+
7
+ CAT = "view.render.template".freeze
8
+
9
+ def normalize(trace, name, payload)
10
+ normalize_render(
11
+ CAT,
12
+ payload,
13
+ partial: 1)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionView
4
+ class RenderTemplate < RenderNormalizer
5
+ register "render_template.action_view"
6
+
7
+ CAT = "view.render.template".freeze
8
+
9
+ def normalize(trace, name, payload)
10
+ normalize_render(
11
+ CAT,
12
+ payload,
13
+ partial: 0)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,81 @@
1
+ require "sql_lexer"
2
+ require "json"
3
+
4
+ module Skylight
5
+ module Normalizers
6
+ module ActiveRecord
7
+ class SQL < Normalizer
8
+ register "sql.active_record"
9
+
10
+ CAT = "db.sql.query".freeze
11
+
12
+ def normalize(trace, name, payload)
13
+ case payload[:name]
14
+ when "SCHEMA", "CACHE"
15
+ return :skip
16
+ else
17
+ name = CAT
18
+ title = payload[:name] || "SQL"
19
+ end
20
+
21
+ binds = payload[:binds]
22
+
23
+ if binds && !binds.empty?
24
+ binds = binds.map { |col, val| val.inspect }
25
+ end
26
+
27
+ extracted_title, sql, binds, error = extract_binds(payload, binds)
28
+ title = extracted_title if extracted_title
29
+
30
+ if sql
31
+ annotations = {
32
+ sql: sql,
33
+ binds: binds,
34
+ }
35
+ else
36
+ annotations = {
37
+ skylight_error: error
38
+ }
39
+ end
40
+
41
+ [ name, title, sql, annotations ]
42
+ end
43
+
44
+ private
45
+ def extract_binds(payload, precalculated)
46
+ title, sql, binds = SqlLexer::Lexer.bindify(payload[:sql], precalculated)
47
+ [ title, sql, binds, nil ]
48
+ rescue => e
49
+ group = "sql_parse"
50
+ description = e.inspect
51
+ details = encode(backtrace: e.backtrace,
52
+ original_exception: {
53
+ class_name: e.class.name,
54
+ message: e.message
55
+ },
56
+ payload: payload,
57
+ precalculated: precalculated)
58
+
59
+ error = [group, description, details]
60
+ [ nil, nil, nil, error ]
61
+ end
62
+
63
+ # While operating in place would save memory, some of these passed in items are re-used elsewhere
64
+ # and, as such, should not be modified.
65
+ def encode(body)
66
+ if body.is_a?(Hash)
67
+ hash = {}
68
+ body.each{|k,v| hash[k] = encode(v) }
69
+ hash
70
+ elsif body.is_a?(Array)
71
+ body.map{|v| encode(v) }
72
+ elsif body.respond_to?(:encoding) && (body.encoding == Encoding::BINARY || !body.valid_encoding?)
73
+ Base64.encode64(body)
74
+ else
75
+ body
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,50 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ # NOTE: Instrumentation may not be turned on by default and is possibly buggy
5
+ # https://github.com/mperham/dalli/pull/284
6
+ class Cache < Normalizer
7
+ %w(clear
8
+ decrement
9
+ delete
10
+ exist
11
+ fetch_hit
12
+ generate
13
+ increment
14
+ read
15
+ read_multi
16
+ write).each do |type|
17
+ require "skylight/normalizers/active_support/cache_#{type}"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ # See https://github.com/rails/rails/pull/15943
25
+ if defined?(ActiveSupport::Cache::Store.instrument)
26
+ deprecated = false
27
+
28
+ # If it's deprecated, setting to false will cause a deprecation warning
29
+ # and the value will remain true
30
+ ActiveSupport::Deprecation.silence do
31
+ ActiveSupport::Cache::Store.instrument = false
32
+ deprecated = ActiveSupport::Cache::Store.instrument
33
+ end
34
+
35
+ unless deprecated
36
+ class ActiveSupport::Cache::Store
37
+ def self.instrument
38
+ true
39
+ end
40
+
41
+ def self.instrument=(val)
42
+ unless val
43
+ Rails.logger.warn "[WARNING] Skylight has patched ActiveSupport::Cache::Store.instrument to always be true. " \
44
+ "In future versions of Rails, this method will no longer be settable. " \
45
+ "See https://github.com/rails/rails/pull/15943 for more information."
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class CacheClear < Cache
5
+ register "cache_clear.active_support"
6
+
7
+ CAT = "app.cache.clear".freeze
8
+ TITLE = "cache clear".freeze
9
+
10
+ def normalize(trace, name, payload)
11
+ [ CAT, TITLE, nil, payload ]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class CacheDecrement < Cache
5
+ register "cache_decrement.active_support"
6
+
7
+ CAT = "app.cache.decrement".freeze
8
+ TITLE = "cache decrement"
9
+
10
+ def normalize(trace, name, payload)
11
+ [ CAT, TITLE, nil, payload ]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class CacheDelete < Cache
5
+ register "cache_delete.active_support"
6
+
7
+ CAT = "app.cache.delete".freeze
8
+ TITLE = "cache delete"
9
+
10
+ def normalize(trace, name, payload)
11
+ [ CAT, TITLE, nil, payload ]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class CacheExist < Cache
5
+ register "cache_exist?.active_support"
6
+
7
+ CAT = "app.cache.exist".freeze
8
+ TITLE = "cache exist?"
9
+
10
+ def normalize(trace, name, payload)
11
+ [ CAT, TITLE, nil, payload ]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class CacheFetchHit < Cache
5
+ register "cache_fetch_hit.active_support"
6
+
7
+ CAT = "app.cache.fetch_hit".freeze
8
+ TITLE = "cache fetch hit"
9
+
10
+ def normalize(trace, name, payload)
11
+ [ CAT, TITLE, nil, payload ]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class CacheGenerate < Cache
5
+ register "cache_generate.active_support"
6
+
7
+ CAT = "app.cache.generate".freeze
8
+ TITLE = "cache generate"
9
+
10
+ def normalize(trace, name, payload)
11
+ [ CAT, TITLE, nil, payload ]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class CacheIncrement < Cache
5
+ register "cache_increment.active_support"
6
+
7
+ CAT = "app.cache.increment".freeze
8
+ TITLE = "cache increment"
9
+
10
+ def normalize(trace, name, payload)
11
+ [ CAT, TITLE, nil, payload ]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class CacheRead < Cache
5
+ register "cache_read.active_support"
6
+
7
+ CAT = "app.cache.read".freeze
8
+ TITLE = "cache read"
9
+
10
+ def normalize(trace, name, payload)
11
+ [ CAT, TITLE, nil, payload ]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class CacheReadMulti < Cache
5
+ register "cache_read_multi.active_support"
6
+
7
+ CAT = "app.cache.read_multi".freeze
8
+ TITLE = "cache read multi"
9
+
10
+ def normalize(trace, name, payload)
11
+ [ CAT, TITLE, nil, payload ]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class CacheWrite < Cache
5
+ register "cache_write.active_support"
6
+
7
+ CAT = "app.cache.write".freeze
8
+ TITLE = "cache write"
9
+
10
+ def normalize(trace, name, payload)
11
+ [ CAT, TITLE, nil, payload ]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,141 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module Moped
4
+ class Query < Normalizer
5
+ register "query.moped"
6
+
7
+ CAT = "db.mongo.query".freeze
8
+
9
+ def normalize(trace, name, payload)
10
+ # payload: { prefix: " MOPED: #{address.resolved}", ops: operations }
11
+
12
+ # We can sometimes have multiple operations. However, it seems like this only happens when doing things
13
+ # like an insert, followed by a get last error, so we can probably ignore all but the first.
14
+ operation = payload[:ops] ? payload[:ops].first : nil
15
+ type = operation && operation.class.to_s =~ /^Moped::Protocol::(.+)$/ ? $1 : nil
16
+
17
+ case type
18
+ when "Query" then normalize_query(operation)
19
+ when "GetMore" then normalize_get_more(operation)
20
+ when "Insert" then normalize_insert(operation)
21
+ when "Update" then normalize_update(operation)
22
+ when "Delete" then normalize_delete(operation)
23
+ else :skip
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def normalize_query(operation)
30
+ title = normalize_title("QUERY", operation)
31
+
32
+ hash, binds = extract_binds(operation.selector)
33
+ description = hash.to_json
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]
43
+ end
44
+
45
+ def normalize_get_more(operation)
46
+ title = normalize_title("GET_MORE", operation)
47
+
48
+ annotations = build_annotations(operation)
49
+ annotations[:limit] = operation.limit
50
+
51
+ [CAT, title, nil, annotations]
52
+ end
53
+
54
+ def normalize_insert(operation)
55
+ title = normalize_title("INSERT", operation)
56
+
57
+ annotations = build_annotations(operation)
58
+ annotations[:count] = operation.documents.count
59
+
60
+ [CAT, title, nil, annotations]
61
+ end
62
+
63
+ def normalize_update(operation)
64
+ title = normalize_title("UPDATE", operation)
65
+
66
+ selector_hash, selector_binds = extract_binds(operation.selector)
67
+ update_hash, update_binds = extract_binds(operation.update)
68
+
69
+ description = { selector: selector_hash, update: update_hash }.to_json
70
+
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]
79
+ end
80
+
81
+ def normalize_delete(operation)
82
+ title = normalize_title("DELETE", operation)
83
+
84
+ hash, binds = extract_binds(operation.selector)
85
+ description = hash.to_json
86
+
87
+ annotations = build_annotations(operation)
88
+ annotations[:binds] = binds unless binds.empty?
89
+
90
+ [CAT, title, description, annotations]
91
+ end
92
+
93
+ def normalize_title(type, operation)
94
+ "#{type} #{operation.collection}"
95
+ end
96
+
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=[])
120
+ hash = hash.dup
121
+
122
+ hash.each do |k,v|
123
+ if v.is_a?(Hash)
124
+ hash[k] = extract_binds(v, binds)[0]
125
+ else
126
+ binds << stringify(hash[k])
127
+ hash[k] = '?'
128
+ end
129
+ end
130
+
131
+ [hash, binds]
132
+ end
133
+
134
+ def stringify(value)
135
+ value.is_a?(Regexp) ? value.inspect : value.to_s
136
+ end
137
+
138
+ end
139
+ end
140
+ end
141
+ end
@@ -1,4 +1,4 @@
1
1
  module Skylight
2
- VERSION = '0.3.14'
2
+ VERSION = '0.3.17'
3
3
  end
4
4
 
@@ -380,16 +380,16 @@ module Skylight
380
380
 
381
381
  if File.exist?(lockfile)
382
382
  if !FileTest.writable?(lockfile)
383
- raise WorkerStateError, "`#{lockfile}` not writable"
383
+ raise WorkerStateError, "`#{lockfile}` not writable. Please set agent.lockfile or agent.sockfile_path in your config to a writable path."
384
384
  end
385
385
  else
386
386
  if !FileTest.writable?(lockfile_root)
387
- raise WorkerStateError, "`#{lockfile_root}` not writable"
387
+ raise WorkerStateError, "`#{lockfile_root}` not writable. Please set agent.lockfile or agent.sockfile_path in your config to a writable path."
388
388
  end
389
389
  end
390
390
 
391
391
  unless FileTest.writable?(sockfile_path)
392
- raise WorkerStateError, "`#{sockfile_path}` not writable"
392
+ raise WorkerStateError, "`#{sockfile_path}` not writable. Please set agent.sockfile_path in your config to a writable path."
393
393
  end
394
394
  end
395
395
 
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skylight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.14
4
+ version: 0.3.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tilde, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-03 00:00:00.000000000 Z
11
+ date: 2014-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 3.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.0.0
27
27
  description:
@@ -33,6 +33,18 @@ extensions:
33
33
  - ext/extconf.rb
34
34
  extra_rdoc_files: []
35
35
  files:
36
+ - CHANGELOG.md
37
+ - README.md
38
+ - bin/skylight
39
+ - ext/extconf.rb
40
+ - ext/libskylight.yml
41
+ - ext/rust_support/ruby.h
42
+ - ext/skylight.h
43
+ - ext/skylight.map
44
+ - ext/skylight_native.c
45
+ - ext/test/extconf.rb
46
+ - ext/test/skylight_native_test.c
47
+ - ext/test/skylight_test.h
36
48
  - lib/skylight.rb
37
49
  - lib/skylight/api.rb
38
50
  - lib/skylight/cli.rb
@@ -57,14 +69,25 @@ files:
57
69
  - lib/skylight/middleware.rb
58
70
  - lib/skylight/native.rb
59
71
  - lib/skylight/normalizers.rb
72
+ - lib/skylight/normalizers/action_controller/process_action.rb
73
+ - lib/skylight/normalizers/action_controller/send_file.rb
74
+ - lib/skylight/normalizers/action_view/render_collection.rb
75
+ - lib/skylight/normalizers/action_view/render_partial.rb
76
+ - lib/skylight/normalizers/action_view/render_template.rb
77
+ - lib/skylight/normalizers/active_record/sql.rb
78
+ - lib/skylight/normalizers/active_support/cache.rb
79
+ - lib/skylight/normalizers/active_support/cache_clear.rb
80
+ - lib/skylight/normalizers/active_support/cache_decrement.rb
81
+ - lib/skylight/normalizers/active_support/cache_delete.rb
82
+ - lib/skylight/normalizers/active_support/cache_exist.rb
83
+ - lib/skylight/normalizers/active_support/cache_fetch_hit.rb
84
+ - lib/skylight/normalizers/active_support/cache_generate.rb
85
+ - lib/skylight/normalizers/active_support/cache_increment.rb
86
+ - lib/skylight/normalizers/active_support/cache_read.rb
87
+ - lib/skylight/normalizers/active_support/cache_read_multi.rb
88
+ - lib/skylight/normalizers/active_support/cache_write.rb
60
89
  - lib/skylight/normalizers/default.rb
61
- - lib/skylight/normalizers/moped.rb
62
- - lib/skylight/normalizers/process_action.rb
63
- - lib/skylight/normalizers/render_collection.rb
64
- - lib/skylight/normalizers/render_partial.rb
65
- - lib/skylight/normalizers/render_template.rb
66
- - lib/skylight/normalizers/send_file.rb
67
- - lib/skylight/normalizers/sql.rb
90
+ - lib/skylight/normalizers/moped/query.rb
68
91
  - lib/skylight/probes.rb
69
92
  - lib/skylight/probes/excon.rb
70
93
  - lib/skylight/probes/excon/middleware.rb
@@ -143,18 +166,6 @@ files:
143
166
  - lib/sql_lexer.rb
144
167
  - lib/sql_lexer/lexer.rb
145
168
  - lib/sql_lexer/version.rb
146
- - ext/rust_support/ruby.h
147
- - ext/skylight.h
148
- - ext/test/skylight_test.h
149
- - ext/skylight_native.c
150
- - ext/test/skylight_native_test.c
151
- - ext/skylight.map
152
- - ext/extconf.rb
153
- - ext/test/extconf.rb
154
- - ext/libskylight.yml
155
- - CHANGELOG.md
156
- - README.md
157
- - bin/skylight
158
169
  homepage: http://www.skylight.io
159
170
  licenses: []
160
171
  metadata: {}
@@ -164,17 +175,17 @@ require_paths:
164
175
  - lib
165
176
  required_ruby_version: !ruby/object:Gem::Requirement
166
177
  requirements:
167
- - - '>='
178
+ - - ">="
168
179
  - !ruby/object:Gem::Version
169
180
  version: 1.9.2
170
181
  required_rubygems_version: !ruby/object:Gem::Requirement
171
182
  requirements:
172
- - - '>='
183
+ - - ">="
173
184
  - !ruby/object:Gem::Version
174
185
  version: '0'
175
186
  requirements: []
176
187
  rubyforge_project:
177
- rubygems_version: 2.0.3
188
+ rubygems_version: 2.2.2
178
189
  signing_key:
179
190
  specification_version: 4
180
191
  summary: Skylight is a smart profiler for Rails apps
@@ -1,139 +0,0 @@
1
- module Skylight
2
- module Normalizers
3
- class Moped < Normalizer
4
- register "query.moped"
5
-
6
- CAT = "db.mongo.query".freeze
7
-
8
- def normalize(trace, name, payload)
9
- # payload: { prefix: " MOPED: #{address.resolved}", ops: operations }
10
-
11
- # We can sometimes have multiple operations. However, it seems like this only happens when doing things
12
- # like an insert, followed by a get last error, so we can probably ignore all but the first.
13
- operation = payload[:ops] ? payload[:ops].first : nil
14
- type = operation && operation.class.to_s =~ /^Moped::Protocol::(.+)$/ ? $1 : nil
15
-
16
- case type
17
- when "Query" then normalize_query(operation)
18
- when "GetMore" then normalize_get_more(operation)
19
- when "Insert" then normalize_insert(operation)
20
- when "Update" then normalize_update(operation)
21
- when "Delete" then normalize_delete(operation)
22
- else :skip
23
- end
24
- end
25
-
26
- private
27
-
28
- def normalize_query(operation)
29
- title = normalize_title("QUERY", operation)
30
-
31
- hash, binds = extract_binds(operation.selector)
32
- description = hash.to_json
33
-
34
- annotations = build_annotations(operation)
35
- annotations[:skip] = operation.skip
36
- if operation.fields
37
- annotations[:fields] = operation.fields.select{|k,v| v == 1 }.keys.map(&:to_s)
38
- end
39
- annotations[:binds] = binds unless binds.empty?
40
-
41
- [CAT, title, description, annotations]
42
- end
43
-
44
- def normalize_get_more(operation)
45
- title = normalize_title("GET_MORE", operation)
46
-
47
- annotations = build_annotations(operation)
48
- annotations[:limit] = operation.limit
49
-
50
- [CAT, title, nil, annotations]
51
- end
52
-
53
- def normalize_insert(operation)
54
- title = normalize_title("INSERT", operation)
55
-
56
- annotations = build_annotations(operation)
57
- annotations[:count] = operation.documents.count
58
-
59
- [CAT, title, nil, annotations]
60
- end
61
-
62
- def normalize_update(operation)
63
- title = normalize_title("UPDATE", operation)
64
-
65
- selector_hash, selector_binds = extract_binds(operation.selector)
66
- update_hash, update_binds = extract_binds(operation.update)
67
-
68
- description = { selector: selector_hash, update: update_hash }.to_json
69
-
70
- annotations = build_annotations(operation)
71
-
72
- binds = {}
73
- binds[:selector] = selector_binds unless selector_binds.empty?
74
- binds[:update] = update_binds unless update_binds.empty?
75
- annotations[:binds] = binds unless binds.empty?
76
-
77
- [CAT, title, description, annotations]
78
- end
79
-
80
- def normalize_delete(operation)
81
- title = normalize_title("DELETE", operation)
82
-
83
- hash, binds = extract_binds(operation.selector)
84
- description = hash.to_json
85
-
86
- annotations = build_annotations(operation)
87
- annotations[:binds] = binds unless binds.empty?
88
-
89
- [CAT, title, description, annotations]
90
- end
91
-
92
- def normalize_title(type, operation)
93
- "#{type} #{operation.collection}"
94
- end
95
-
96
- def build_annotations(operation)
97
- annotations = {}
98
-
99
- if operation.respond_to?(:flags)
100
- flags = operation.flags.map{|f| flag_name(f) }
101
- annotations[:flags] = flags unless flags.empty?
102
- end
103
-
104
- annotations
105
- end
106
-
107
- # Some flags used by Moped don't map directly to the Mongo docs
108
- # See http://docs.mongodb.org/meta-driver/latest/legacy/mongodb-wire-protocol/
109
- FLAG_MAP = {
110
- tailable: "TailableCursor",
111
- multi: "MultiUpdate"
112
- }
113
-
114
- def flag_name(flag)
115
- FLAG_MAP[flag] || flag.to_s.sub(/^[a-z\d]*/) { $&.capitalize }.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }
116
- end
117
-
118
- def extract_binds(hash, binds=[])
119
- hash = hash.dup
120
-
121
- hash.each do |k,v|
122
- if v.is_a?(Hash)
123
- hash[k] = extract_binds(v, binds)[0]
124
- else
125
- binds << stringify(hash[k])
126
- hash[k] = '?'
127
- end
128
- end
129
-
130
- [hash, binds]
131
- end
132
-
133
- def stringify(value)
134
- value.is_a?(Regexp) ? value.inspect : value.to_s
135
- end
136
-
137
- end
138
- end
139
- end
@@ -1,34 +0,0 @@
1
- module Skylight
2
- module Normalizers
3
- class ProcessAction < Normalizer
4
- register "process_action.action_controller"
5
-
6
- CAT = "app.controller.request".freeze
7
- PAYLOAD_KEYS = %w[ controller action params format method path ].map(&:to_sym).freeze
8
-
9
- def normalize(trace, name, payload)
10
- trace.endpoint = controller_action(payload)
11
- [ CAT, trace.endpoint, nil, normalize_payload(payload) ]
12
- end
13
-
14
- private
15
-
16
- def controller_action(payload)
17
- "#{payload[:controller]}##{payload[:action]}"
18
- end
19
-
20
- def normalize_payload(payload)
21
- normalized = {}
22
-
23
- PAYLOAD_KEYS.each do |key|
24
- val = payload[key]
25
- val = val.inspect unless val.is_a?(String) || val.is_a?(Numeric)
26
- normalized[key] = val
27
- end
28
-
29
- normalized
30
- end
31
- end
32
- end
33
- end
34
-
@@ -1,16 +0,0 @@
1
- module Skylight
2
- module Normalizers
3
- class RenderCollection < RenderNormalizer
4
- register "render_collection.action_view"
5
-
6
- CAT = "view.render.collection".freeze
7
-
8
- def normalize(trace, name, payload)
9
- normalize_render(
10
- CAT,
11
- payload,
12
- count: payload[:count])
13
- end
14
- end
15
- end
16
- end
@@ -1,16 +0,0 @@
1
- module Skylight
2
- module Normalizers
3
- class RenderPartial < RenderNormalizer
4
- register "render_partial.action_view"
5
-
6
- CAT = "view.render.template".freeze
7
-
8
- def normalize(trace, name, payload)
9
- normalize_render(
10
- CAT,
11
- payload,
12
- partial: 1)
13
- end
14
- end
15
- end
16
- end
@@ -1,16 +0,0 @@
1
- module Skylight
2
- module Normalizers
3
- class RenderTemplate < RenderNormalizer
4
- register "render_template.action_view"
5
-
6
- CAT = "view.render.template".freeze
7
-
8
- def normalize(trace, name, payload)
9
- normalize_render(
10
- CAT,
11
- payload,
12
- partial: 0)
13
- end
14
- end
15
- end
16
- end
@@ -1,74 +0,0 @@
1
- module Skylight
2
- module Normalizers
3
-
4
- # Temporary hacks
5
- begin
6
- require "action_dispatch/http/mime_type"
7
- require "action_dispatch/http/mime_types"
8
- require "rack/utils"
9
-
10
- class SendFile < Normalizer
11
- register "send_file.action_controller"
12
-
13
- CAT = "app.controller.send_file".freeze
14
- TITLE = "send file".freeze
15
-
16
- def normalize(trace, name, payload)
17
- path = payload[:path]
18
-
19
- annotations = {
20
- path: path,
21
- filename: payload[:filename],
22
- type: normalize_type(payload),
23
- disposition: normalize_disposition(payload),
24
- status: normalize_status(payload) }
25
-
26
- title = TITLE
27
-
28
- # depending on normalization, we probably want this to eventually
29
- # include the full path, but we need to make sure we have a good
30
- # deduping strategy first.
31
- desc = nil
32
-
33
- [ CAT, title, desc, annotations ]
34
- end
35
-
36
- private
37
-
38
- OCTET_STREAM = "application/octet-stream".freeze
39
- ATTACHMENT = "attachment".freeze
40
-
41
- def initialize(*)
42
- super
43
-
44
- @mimes = Mime::SET.reduce({}) do |hash, mime|
45
- hash[mime.symbol] = mime.to_s.dup.freeze
46
- hash
47
- end
48
- end
49
-
50
- def normalize_type(payload)
51
- type = payload[:type] || OCTET_STREAM
52
- type = @mimes[type] if type.is_a?(Symbol)
53
- type
54
- end
55
-
56
- def mime_for(type)
57
- @mimes[type] ||= Mime[type].to_s.freeze
58
- end
59
-
60
- def normalize_status(payload)
61
- status = payload[:status] || 200
62
- Rack::Utils.status_code(status)
63
- end
64
-
65
- def normalize_disposition(payload)
66
- payload[:disposition] || ATTACHMENT
67
- end
68
- end
69
-
70
- rescue LoadError
71
- end
72
-
73
- end
74
- end
@@ -1,79 +0,0 @@
1
- require "sql_lexer"
2
- require "json"
3
-
4
- module Skylight
5
- module Normalizers
6
- class SQL < Normalizer
7
- register "sql.active_record"
8
-
9
- CAT = "db.sql.query".freeze
10
-
11
- def normalize(trace, name, payload)
12
- case payload[:name]
13
- when "SCHEMA", "CACHE"
14
- return :skip
15
- else
16
- name = CAT
17
- title = payload[:name] || "SQL"
18
- end
19
-
20
- binds = payload[:binds]
21
-
22
- if binds && !binds.empty?
23
- binds = binds.map { |col, val| val.inspect }
24
- end
25
-
26
- extracted_title, sql, binds, error = extract_binds(payload, binds)
27
- title = extracted_title if extracted_title
28
-
29
- if sql
30
- annotations = {
31
- sql: sql,
32
- binds: binds,
33
- }
34
- else
35
- annotations = {
36
- skylight_error: error
37
- }
38
- end
39
-
40
- [ name, title, sql, annotations ]
41
- end
42
-
43
- private
44
- def extract_binds(payload, precalculated)
45
- title, sql, binds = SqlLexer::Lexer.bindify(payload[:sql], precalculated)
46
- [ title, sql, binds, nil ]
47
- rescue => e
48
- group = "sql_parse"
49
- description = e.inspect
50
- details = encode(backtrace: e.backtrace,
51
- original_exception: {
52
- class_name: e.class.name,
53
- message: e.message
54
- },
55
- payload: payload,
56
- precalculated: precalculated)
57
-
58
- error = [group, description, details]
59
- [ nil, nil, nil, error ]
60
- end
61
-
62
- # While operating in place would save memory, some of these passed in items are re-used elsewhere
63
- # and, as such, should not be modified.
64
- def encode(body)
65
- if body.is_a?(Hash)
66
- hash = {}
67
- body.each{|k,v| hash[k] = encode(v) }
68
- hash
69
- elsif body.is_a?(Array)
70
- body.map{|v| encode(v) }
71
- elsif body.respond_to?(:encoding) && (body.encoding == Encoding::BINARY || !body.valid_encoding?)
72
- Base64.encode64(body)
73
- else
74
- body
75
- end
76
- end
77
- end
78
- end
79
- end