skylight 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/skylight/cli.rb +10 -2
- data/lib/skylight/config.rb +10 -1
- data/lib/skylight/instrumenter.rb +40 -18
- data/lib/skylight/middleware.rb +8 -30
- data/lib/skylight/normalize/send_file.rb +43 -36
- data/lib/skylight/railtie.rb +32 -23
- data/lib/skylight/subscriber.rb +0 -2
- data/lib/skylight/trace.rb +8 -1
- data/lib/skylight/version.rb +1 -1
- metadata +16 -10
- checksums.yaml +0 -7
data/lib/skylight/cli.rb
CHANGED
@@ -4,6 +4,7 @@ $:.unshift File.expand_path('../vendor', __FILE__)
|
|
4
4
|
require "skylight"
|
5
5
|
require "thor"
|
6
6
|
require "highline"
|
7
|
+
require "active_support/inflector"
|
7
8
|
|
8
9
|
module Skylight
|
9
10
|
class CLI < Thor
|
@@ -77,8 +78,15 @@ module Skylight
|
|
77
78
|
end
|
78
79
|
|
79
80
|
def app_name
|
80
|
-
|
81
|
-
|
81
|
+
@app_name ||=
|
82
|
+
begin
|
83
|
+
if File.exist?("config/application.rb")
|
84
|
+
require "./config/application"
|
85
|
+
Rails.application.class.name.split("::").first.underscore.humanize
|
86
|
+
else
|
87
|
+
File.basename(File.expand_path('.')).humanize
|
88
|
+
end
|
89
|
+
end
|
82
90
|
end
|
83
91
|
end
|
84
92
|
end
|
data/lib/skylight/config.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
require 'logger'
|
3
|
+
require 'fileutils'
|
3
4
|
|
4
5
|
module Skylight
|
5
6
|
class Config
|
@@ -22,6 +23,7 @@ module Skylight
|
|
22
23
|
end
|
23
24
|
|
24
25
|
private
|
26
|
+
|
25
27
|
def apply_env(config, env)
|
26
28
|
env.each do |key, value|
|
27
29
|
name = normalize_env(key)
|
@@ -46,7 +48,7 @@ module Skylight
|
|
46
48
|
@port = 443
|
47
49
|
@interval = 5
|
48
50
|
@protocol = JsonProto.new(self)
|
49
|
-
@max_pending_traces
|
51
|
+
@max_pending_traces = 500
|
50
52
|
@samples_per_interval = 100
|
51
53
|
|
52
54
|
@logger = Logger.new(STDOUT)
|
@@ -60,6 +62,9 @@ module Skylight
|
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
65
|
+
@http ||= Util::HTTP.new(self)
|
66
|
+
@gc_profiler ||= GC::Profiler
|
67
|
+
|
63
68
|
yield self if block_given?
|
64
69
|
end
|
65
70
|
|
@@ -88,6 +93,7 @@ module Skylight
|
|
88
93
|
attr_reader :normalizer
|
89
94
|
|
90
95
|
attr_reader :protocol
|
96
|
+
|
91
97
|
def protocol=(val)
|
92
98
|
if val.is_a?(String) || val.is_a?(Symbol)
|
93
99
|
class_name = val.to_s.capitalize+"Proto"
|
@@ -114,10 +120,13 @@ module Skylight
|
|
114
120
|
attr_writer :gc_profiler
|
115
121
|
|
116
122
|
def gc_profiler
|
123
|
+
# TODO: Move this into tests
|
117
124
|
@gc_profiler ||= Struct.new(:enable, :disable, :clear, :total_time).new(nil, nil, nil, 0)
|
118
125
|
end
|
119
126
|
|
120
127
|
def save(filename=yaml_file)
|
128
|
+
FileUtils.mkdir_p File.dirname(filename)
|
129
|
+
|
121
130
|
File.open(filename, "w") do |file|
|
122
131
|
config = {}
|
123
132
|
config["authentication_token"] = authentication_token if authentication_token
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module Skylight
|
2
2
|
class Instrumenter
|
3
3
|
|
4
|
+
# Guards starting the instrumenter
|
5
|
+
LOCK = Mutex.new
|
6
|
+
|
4
7
|
# Maximum number of traces to sample for each interval
|
5
8
|
SAMPLE_SIZE = 100
|
6
9
|
|
@@ -8,44 +11,63 @@ module Skylight
|
|
8
11
|
INTERVAL = 5
|
9
12
|
|
10
13
|
def self.start!(config = Config.new)
|
11
|
-
# Convert a hash to a config object
|
12
|
-
if Hash === config
|
13
|
-
config = Config.new config
|
14
|
-
end
|
15
|
-
|
16
14
|
new(config).start!
|
17
15
|
end
|
18
16
|
|
19
17
|
attr_reader :config, :worker, :samples
|
20
18
|
|
21
19
|
def initialize(config)
|
22
|
-
|
20
|
+
# Convert a hash to a config object
|
21
|
+
if Hash === config
|
22
|
+
config = Config.new(config)
|
23
|
+
end
|
23
24
|
|
24
|
-
@
|
25
|
+
@config = config
|
26
|
+
@started = false
|
27
|
+
@worker = Worker.new(self)
|
25
28
|
end
|
26
29
|
|
27
30
|
def start!
|
28
|
-
|
29
|
-
|
31
|
+
# Quick check
|
32
|
+
return self if @started
|
33
|
+
|
34
|
+
LOCK.synchronize do
|
35
|
+
# Ensure that the instrumenter has not been started now that the lock
|
36
|
+
# as been acquired
|
37
|
+
return self if @started
|
38
|
+
|
39
|
+
@worker.start!
|
40
|
+
Subscriber.register!(config)
|
30
41
|
|
31
|
-
|
32
|
-
|
42
|
+
# Ensure properly configured
|
43
|
+
return unless config
|
33
44
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
45
|
+
# Ensure that there is an API token
|
46
|
+
unless config.authentication_token
|
47
|
+
if logger = config.logger
|
48
|
+
logger.warn "[SKYLIGHT] No authentication token provided; cannot start agent."
|
49
|
+
end
|
50
|
+
|
51
|
+
return
|
38
52
|
end
|
39
53
|
|
40
|
-
|
41
|
-
end
|
54
|
+
config.gc_profiler.enable
|
42
55
|
|
43
|
-
|
56
|
+
@started = true
|
57
|
+
end
|
44
58
|
|
45
59
|
self
|
60
|
+
|
61
|
+
rescue
|
62
|
+
nil
|
46
63
|
end
|
47
64
|
|
48
65
|
def trace(endpoint = nil)
|
66
|
+
# Ignore everything unless the instrumenter has been started
|
67
|
+
unless @started
|
68
|
+
return yield
|
69
|
+
end
|
70
|
+
|
49
71
|
# If there already is a trace going on, then just continue
|
50
72
|
if Thread.current[Trace::KEY]
|
51
73
|
return yield
|
data/lib/skylight/middleware.rb
CHANGED
@@ -1,46 +1,24 @@
|
|
1
1
|
module Skylight
|
2
2
|
class Middleware
|
3
|
-
|
4
|
-
|
3
|
+
|
4
|
+
def self.new(app, instrumenter, *)
|
5
|
+
return app unless instrumenter
|
5
6
|
super
|
6
7
|
end
|
7
8
|
|
8
|
-
def initialize(app,
|
9
|
+
def initialize(app, instrumenter)
|
9
10
|
@app = app
|
10
|
-
@
|
11
|
-
@config.gc_profiler = GC::Profiler
|
12
|
-
@instrumenter_class = instrumenter_class
|
11
|
+
@instrumenter = instrumenter
|
13
12
|
end
|
14
13
|
|
15
14
|
def call(env)
|
16
|
-
instrumenter.
|
15
|
+
@instrumenter.start!
|
16
|
+
|
17
|
+
@instrumenter.trace("Rack") do
|
17
18
|
ActiveSupport::Notifications.instrument("app.rack.request") do
|
18
19
|
@app.call(env)
|
19
20
|
end
|
20
21
|
end
|
21
22
|
end
|
22
|
-
|
23
|
-
private
|
24
|
-
LOCK = Mutex.new
|
25
|
-
|
26
|
-
def instrumenter
|
27
|
-
return @instrumenter if defined?(@instrumenter)
|
28
|
-
|
29
|
-
LOCK.synchronize do
|
30
|
-
return @instrumeter if defined?(@instrumenter)
|
31
|
-
@instrumenter = @instrumenter_class.start!(@config)
|
32
|
-
return @instrumenter
|
33
|
-
end
|
34
|
-
rescue Exception
|
35
|
-
@instrumenter = stub
|
36
|
-
end
|
37
|
-
|
38
|
-
def stub
|
39
|
-
Class.new do
|
40
|
-
def trace(*)
|
41
|
-
yield
|
42
|
-
end
|
43
|
-
end.new
|
44
|
-
end
|
45
23
|
end
|
46
24
|
end
|
@@ -1,44 +1,51 @@
|
|
1
|
-
require "action_dispatch/http/mime_type"
|
2
|
-
require "action_dispatch/http/mime_types"
|
3
|
-
require "rack/utils"
|
4
|
-
|
5
1
|
module Skylight
|
6
2
|
module Normalize
|
7
|
-
class SendFile < Normalizer
|
8
|
-
register "send_file.action_controller"
|
9
|
-
|
10
|
-
def normalize
|
11
|
-
path = @payload[:path]
|
12
|
-
|
13
|
-
annotations = {
|
14
|
-
path: path,
|
15
|
-
filename: @payload[:filename],
|
16
|
-
type: normalize_type,
|
17
|
-
disposition: normalize_disposition,
|
18
|
-
status: normalize_status
|
19
|
-
}
|
20
|
-
|
21
|
-
# These will eventually be different
|
22
|
-
title = desc = "send file: #{path}"
|
23
|
-
|
24
|
-
[ "app.controller.send_file", title, desc, annotations ]
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
def normalize_type
|
29
|
-
type = @payload[:type] || "application/octet-stream"
|
30
|
-
type = Mime[type].to_s if type.is_a?(Symbol)
|
31
|
-
type
|
32
|
-
end
|
33
3
|
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
+
def normalize
|
14
|
+
path = @payload[:path]
|
15
|
+
|
16
|
+
annotations = {
|
17
|
+
path: path,
|
18
|
+
filename: @payload[:filename],
|
19
|
+
type: normalize_type,
|
20
|
+
disposition: normalize_disposition,
|
21
|
+
status: normalize_status
|
22
|
+
}
|
23
|
+
|
24
|
+
# These will eventually be different
|
25
|
+
title = desc = "send file: #{path}"
|
26
|
+
|
27
|
+
[ "app.controller.send_file", title, desc, annotations ]
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def normalize_type
|
32
|
+
type = @payload[:type] || "application/octet-stream"
|
33
|
+
type = Mime[type].to_s if type.is_a?(Symbol)
|
34
|
+
type
|
35
|
+
end
|
36
|
+
|
37
|
+
def normalize_status
|
38
|
+
status = @payload[:status] || 200
|
39
|
+
Rack::Utils.status_code(status)
|
40
|
+
end
|
41
|
+
|
42
|
+
def normalize_disposition
|
43
|
+
@payload[:disposition] || "attachment"
|
44
|
+
end
|
37
45
|
end
|
38
46
|
|
39
|
-
|
40
|
-
@payload[:disposition] || "attachment"
|
41
|
-
end
|
47
|
+
rescue LoadError
|
42
48
|
end
|
49
|
+
|
43
50
|
end
|
44
51
|
end
|
data/lib/skylight/railtie.rb
CHANGED
@@ -13,52 +13,61 @@ module Skylight
|
|
13
13
|
|
14
14
|
attr_accessor :instrumenter
|
15
15
|
|
16
|
-
initializer "skylight.
|
17
|
-
|
18
|
-
@problems = checker.smoke_test(config_path(app)) || checker.sanity_check(load_config(app))
|
19
|
-
next unless @problems
|
16
|
+
initializer "skylight.configure" do |app|
|
17
|
+
config = load_config(app)
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
puts "[SKYLIGHT] PROBLEM: #{group} #{problem}"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
19
|
+
if good_to_go?(app, config)
|
20
|
+
@instrumenter = Instrumenter.new(config)
|
27
21
|
|
28
|
-
initializer "skylight.configure" do |app|
|
29
|
-
if @problems
|
30
|
-
puts "[SKYLIGHT] Skipping Skylight boot"
|
31
|
-
else
|
32
22
|
Rails.logger.debug "[SKYLIGHT] Installing middleware"
|
33
|
-
app.middleware.insert 0, Middleware,
|
23
|
+
app.middleware.insert 0, Middleware, @instrumenter
|
24
|
+
else
|
25
|
+
puts "[SKYLIGHT] Skipping Skylight boot"
|
34
26
|
end
|
35
27
|
end
|
36
28
|
|
37
29
|
private
|
38
30
|
|
39
|
-
def
|
40
|
-
|
31
|
+
def good_to_go?(app, config)
|
32
|
+
unless problems = check_for_problems(app, config)
|
33
|
+
return true
|
34
|
+
end
|
35
|
+
|
36
|
+
problems.each do |group, problem_list|
|
37
|
+
problem_list.each do |problem|
|
38
|
+
puts "[SKYLIGHT] PROBLEM: #{group} #{problem}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
false
|
41
43
|
end
|
42
44
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
45
|
+
def check_for_problems(app, config)
|
46
|
+
checker = SanityChecker.new
|
47
|
+
checker.smoke_test(config_path(app)) || checker.sanity_check(config)
|
46
48
|
end
|
47
49
|
|
48
50
|
def load_config(app)
|
49
|
-
@skylight_config ||= begin
|
50
51
|
config = Config.load_from_yaml(config_path(app), ENV).tap do |c|
|
51
52
|
c.logger = Rails.logger
|
52
53
|
end
|
53
54
|
|
54
55
|
config.normalizer.view_paths = app.config.paths["app/views"].existent
|
55
|
-
config.http = Util::HTTP.new(config)
|
56
56
|
config
|
57
|
-
end
|
58
57
|
rescue => e
|
59
58
|
raise
|
60
59
|
Rails.logger.error "[SKYLIGHT] #{e.message} (#{e.class}) - #{e.backtrace.first}"
|
61
60
|
end
|
62
61
|
|
62
|
+
def environments
|
63
|
+
Array(config.skylight.environments).map { |e| e && e.to_s }.compact
|
64
|
+
end
|
65
|
+
|
66
|
+
def config_path(app)
|
67
|
+
path = config.skylight.config_path
|
68
|
+
File.expand_path(path, app.root)
|
69
|
+
end
|
70
|
+
|
71
|
+
|
63
72
|
end
|
64
73
|
end
|
data/lib/skylight/subscriber.rb
CHANGED
data/lib/skylight/trace.rb
CHANGED
@@ -94,7 +94,14 @@ module Skylight
|
|
94
94
|
|
95
95
|
update_cumulative_gc
|
96
96
|
|
97
|
-
|
97
|
+
ended_at = now - @timestamp
|
98
|
+
|
99
|
+
# If it's not the root node
|
100
|
+
if span.parent
|
101
|
+
ended_at -= @cumulative_gc
|
102
|
+
end
|
103
|
+
|
104
|
+
span.ended_at = ended_at
|
98
105
|
|
99
106
|
# Update the parent
|
100
107
|
@parent = @spans[@parent].parent
|
data/lib/skylight/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skylight
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Tilde, Inc.
|
@@ -13,29 +14,33 @@ dependencies:
|
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: activesupport
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
|
-
- - '>='
|
19
|
+
- - ! '>='
|
18
20
|
- !ruby/object:Gem::Version
|
19
21
|
version: 3.0.0
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
|
-
- - '>='
|
27
|
+
- - ! '>='
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: 3.0.0
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: actionpack
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
|
-
- - '>='
|
35
|
+
- - ! '>='
|
32
36
|
- !ruby/object:Gem::Version
|
33
37
|
version: 3.0.0
|
34
38
|
type: :development
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
|
-
- - '>='
|
43
|
+
- - ! '>='
|
39
44
|
- !ruby/object:Gem::Version
|
40
45
|
version: 3.0.0
|
41
46
|
description: Currently in pre-alpha.
|
@@ -124,25 +129,26 @@ files:
|
|
124
129
|
- bin/skylight
|
125
130
|
homepage: http://www.skylight.io
|
126
131
|
licenses: []
|
127
|
-
metadata: {}
|
128
132
|
post_install_message:
|
129
133
|
rdoc_options: []
|
130
134
|
require_paths:
|
131
135
|
- lib
|
132
136
|
required_ruby_version: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
133
138
|
requirements:
|
134
|
-
- - '>='
|
139
|
+
- - ! '>='
|
135
140
|
- !ruby/object:Gem::Version
|
136
141
|
version: 1.9.2
|
137
142
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
138
144
|
requirements:
|
139
|
-
- - '>='
|
145
|
+
- - ! '>='
|
140
146
|
- !ruby/object:Gem::Version
|
141
147
|
version: '0'
|
142
148
|
requirements: []
|
143
149
|
rubyforge_project:
|
144
|
-
rubygems_version:
|
150
|
+
rubygems_version: 1.8.25
|
145
151
|
signing_key:
|
146
|
-
specification_version:
|
152
|
+
specification_version: 3
|
147
153
|
summary: Skylight is a ruby application monitoring tool.
|
148
154
|
test_files: []
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: addb4eed3d6a9b0f22eb5163115018211c5da90c
|
4
|
-
data.tar.gz: 513eb7a8391b46447744f602127b2e0e4fe84edc
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: cd3900fdbb47bc3adf7a81dda75a69277b72484d056a1f86c66b83b36335d0a2e01568830c0bb412bdcd76c82eb7ceec11fc2a5b8f73c1c129d725ab342e27b4
|
7
|
-
data.tar.gz: e94a2b3bf08c8151b1a23e666402a4530eaa3310087de8f6b43f109f57792c7556e17314711babfeff7cfaca3a3f8d1df41f18b36587bf356c5c12d2533f668a
|