skylight 0.0.16 → 0.1.0.alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +3 -19
- data/bin/skylight +0 -2
- data/lib/skylight.rb +52 -42
- data/lib/skylight/api.rb +34 -0
- data/lib/skylight/cli.rb +68 -57
- data/lib/skylight/compat.rb +19 -5
- data/lib/skylight/config.rb +219 -98
- data/lib/skylight/gc.rb +109 -0
- data/lib/skylight/instrumenter.rb +53 -70
- data/lib/skylight/messages.rb +19 -0
- data/lib/skylight/messages/annotation.rb +13 -0
- data/lib/skylight/messages/base.rb +24 -0
- data/lib/skylight/messages/batch.rb +11 -0
- data/lib/skylight/messages/endpoint.rb +12 -0
- data/lib/skylight/messages/event.rb +12 -0
- data/lib/skylight/messages/hello.rb +53 -0
- data/lib/skylight/messages/span.rb +21 -0
- data/lib/skylight/messages/trace.rb +162 -0
- data/lib/skylight/middleware.rb +2 -4
- data/lib/skylight/normalizers.rb +89 -0
- data/lib/skylight/normalizers/default.rb +22 -0
- data/lib/skylight/normalizers/process_action.rb +19 -0
- data/lib/skylight/normalizers/render_collection.rb +14 -0
- data/lib/skylight/normalizers/render_partial.rb +14 -0
- data/lib/skylight/normalizers/render_template.rb +14 -0
- data/lib/skylight/{normalize → normalizers}/send_file.rb +15 -15
- data/lib/skylight/normalizers/sql.rb +25 -0
- data/lib/skylight/railtie.rb +21 -41
- data/lib/skylight/subscriber.rb +29 -19
- data/lib/skylight/util/clock.rb +8 -21
- data/lib/skylight/util/http.rb +93 -46
- data/lib/skylight/util/logging.rb +66 -0
- data/lib/skylight/util/queue.rb +7 -3
- data/lib/skylight/util/task.rb +154 -0
- data/lib/skylight/{compat → vendor/active_support}/notifications.rb +56 -24
- data/lib/skylight/{compat → vendor/active_support}/notifications/fanout.rb +19 -26
- data/lib/skylight/{compat → vendor/active_support}/notifications/instrumenter.rb +25 -18
- data/lib/skylight/vendor/active_support/per_thread_registry.rb +52 -0
- data/lib/skylight/vendor/beefcake.rb +256 -0
- data/lib/skylight/vendor/beefcake/buffer.rb +112 -0
- data/lib/skylight/vendor/beefcake/decode.rb +107 -0
- data/lib/skylight/vendor/beefcake/encode.rb +115 -0
- data/lib/skylight/vendor/{highline.rb → cli/highline.rb} +0 -0
- data/lib/skylight/vendor/{highline → cli/highline}/color_scheme.rb +0 -0
- data/lib/skylight/vendor/{highline → cli/highline}/compatibility.rb +0 -0
- data/lib/skylight/vendor/{highline → cli/highline}/import.rb +0 -0
- data/lib/skylight/vendor/{highline → cli/highline}/menu.rb +0 -0
- data/lib/skylight/vendor/{highline → cli/highline}/question.rb +0 -0
- data/lib/skylight/vendor/{highline → cli/highline}/simulate.rb +0 -0
- data/lib/skylight/vendor/{highline → cli/highline}/string_extensions.rb +0 -0
- data/lib/skylight/vendor/{highline → cli/highline}/style.rb +0 -0
- data/lib/skylight/vendor/{highline → cli/highline}/system_extensions.rb +0 -0
- data/lib/skylight/vendor/{thor.rb → cli/thor.rb} +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/actions.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/actions/create_file.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/actions/create_link.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/actions/directory.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/actions/empty_directory.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/actions/file_manipulation.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/actions/inject_into_file.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/base.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/command.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/core_ext/hash_with_indifferent_access.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/core_ext/io_binary_read.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/core_ext/ordered_hash.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/error.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/group.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/invocation.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/parser.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/parser/argument.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/parser/arguments.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/parser/option.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/parser/options.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/rake_compat.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/runner.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/shell.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/shell/basic.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/shell/color.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/shell/html.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/util.rb +0 -0
- data/lib/skylight/vendor/{thor → cli/thor}/version.rb +0 -0
- data/lib/skylight/vendor/thread_safe.rb +126 -0
- data/lib/skylight/vendor/thread_safe/non_concurrent_cache_backend.rb +133 -0
- data/lib/skylight/vendor/thread_safe/synchronized_cache_backend.rb +76 -0
- data/lib/skylight/version.rb +2 -1
- data/lib/skylight/worker.rb +12 -154
- data/lib/skylight/worker/builder.rb +72 -0
- data/lib/skylight/worker/collector.rb +124 -0
- data/lib/skylight/worker/connection.rb +77 -0
- data/lib/skylight/worker/embedded.rb +6 -0
- data/lib/skylight/worker/server.rb +307 -0
- data/lib/skylight/worker/standalone.rb +356 -0
- metadata +89 -77
- data/lib/skylight/connection.rb +0 -25
- data/lib/skylight/json_proto.rb +0 -88
- data/lib/skylight/normalize.rb +0 -63
- data/lib/skylight/normalize/default.rb +0 -17
- data/lib/skylight/normalize/process_action.rb +0 -17
- data/lib/skylight/normalize/render_collection.rb +0 -11
- data/lib/skylight/normalize/render_partial.rb +0 -14
- data/lib/skylight/normalize/render_template.rb +0 -13
- data/lib/skylight/normalize/sql.rb +0 -26
- data/lib/skylight/normalize/start_processing.rb +0 -12
- data/lib/skylight/sanity_checker.rb +0 -73
- data/lib/skylight/trace.rb +0 -160
- data/lib/skylight/util/atomic.rb +0 -73
- data/lib/skylight/util/bytes.rb +0 -40
- data/lib/skylight/util/ewma.rb +0 -32
- data/lib/skylight/util/uuid.rb +0 -33
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 82650226a057fc3b8b8595ac4fc760edaf56c656
|
|
4
|
+
data.tar.gz: f50d0c8f8e3d22d915664760f7eba80aece2fbae
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 99a7f5225e962df3c946c6440454a1892c1401d19feebee8cb3698a048c4f3a26980d2db77e99092f55023020ec6f85b88146ffd0aa799c03e4b3f1880c969c6
|
|
7
|
+
data.tar.gz: 0b40b0d1f2c08ee5872f6891f7b889900e96ec70beb6c938fe2016c35e07c8271e901f7b6d1e5c1919418a963698027fddbad7e2fe63d78ef2c13953da7b85d6
|
data/README.md
CHANGED
|
@@ -1,20 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Skylight Ruby Agent
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
## Traces
|
|
7
|
-
|
|
8
|
-
An conceptual overview of a trace.
|
|
9
|
-
|
|
10
|
-
* Trace ID (UUID)
|
|
11
|
-
* Tiers
|
|
12
|
-
* Name
|
|
13
|
-
* Spans (max 256 unique per tier)
|
|
14
|
-
* Category (multi-level, example: cache.redis)
|
|
15
|
-
* Description
|
|
16
|
-
* Annotations
|
|
17
|
-
|
|
18
|
-
## TODO
|
|
19
|
-
|
|
20
|
-
* Cap the max number of spans per trace (2048k?)
|
|
3
|
+
Instrument your ruby application and send the data to the Skylight
|
|
4
|
+
servers.
|
data/bin/skylight
CHANGED
data/lib/skylight.rb
CHANGED
|
@@ -1,11 +1,49 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'rbconfig'
|
|
2
2
|
require 'socket'
|
|
3
|
-
require '
|
|
4
|
-
require 'net/http'
|
|
5
|
-
require 'active_support/notifications'
|
|
3
|
+
require 'skylight/version'
|
|
6
4
|
|
|
7
5
|
module Skylight
|
|
8
|
-
|
|
6
|
+
TRACE_ENV_KEY = 'SK_ENABLE_TRACE_LOGS'.freeze
|
|
7
|
+
STANDALONE_ENV_KEY = 'SK_STANDALONE'.freeze
|
|
8
|
+
STANDALONE_ENV_VAL = 'server'.freeze
|
|
9
|
+
|
|
10
|
+
def self.daemon?
|
|
11
|
+
ENV[STANDALONE_ENV_KEY] == STANDALONE_ENV_VAL
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
unless daemon?
|
|
15
|
+
require 'active_support/notifications'
|
|
16
|
+
require 'skylight/compat' # Require after AS::N
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
autoload :Api, 'skylight/api'
|
|
20
|
+
autoload :CLI, 'skylight/cli'
|
|
21
|
+
autoload :Config, 'skylight/config'
|
|
22
|
+
autoload :GC, 'skylight/gc'
|
|
23
|
+
autoload :Instrumenter, 'skylight/instrumenter'
|
|
24
|
+
autoload :Messages, 'skylight/messages'
|
|
25
|
+
autoload :Normalizers, 'skylight/normalizers'
|
|
26
|
+
autoload :Subscriber, 'skylight/subscriber'
|
|
27
|
+
autoload :Worker, 'skylight/worker'
|
|
28
|
+
|
|
29
|
+
module Util
|
|
30
|
+
autoload :Clock, 'skylight/util/clock'
|
|
31
|
+
autoload :Gzip, 'skylight/util/gzip'
|
|
32
|
+
autoload :HTTP, 'skylight/util/http'
|
|
33
|
+
autoload :Logging, 'skylight/util/logging'
|
|
34
|
+
autoload :Queue, 'skylight/util/queue'
|
|
35
|
+
autoload :Task, 'skylight/util/task'
|
|
36
|
+
autoload :UniformSample, 'skylight/util/uniform_sample'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# ==== Vendor ====
|
|
40
|
+
autoload :Beefcake, 'skylight/vendor/beefcake'
|
|
41
|
+
|
|
42
|
+
# ==== Exceptions ====
|
|
43
|
+
class IpcProtoError < RuntimeError; end
|
|
44
|
+
class WorkerStateError < RuntimeError; end
|
|
45
|
+
class ConfigError < RuntimeError; end
|
|
46
|
+
class TraceError < RuntimeError; end
|
|
9
47
|
|
|
10
48
|
TIERS = %w(
|
|
11
49
|
app
|
|
@@ -14,42 +52,14 @@ module Skylight
|
|
|
14
52
|
noise
|
|
15
53
|
other)
|
|
16
54
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
require 'skylight/util/http'
|
|
24
|
-
require 'skylight/util/queue'
|
|
25
|
-
require 'skylight/util/uniform_sample'
|
|
26
|
-
require 'skylight/util/uuid'
|
|
27
|
-
|
|
28
|
-
# Then require the rest
|
|
29
|
-
require 'skylight/sanity_checker'
|
|
30
|
-
require 'skylight/compat'
|
|
31
|
-
require 'skylight/config'
|
|
32
|
-
require 'skylight/instrumenter'
|
|
33
|
-
require 'skylight/middleware'
|
|
34
|
-
require 'skylight/normalize'
|
|
35
|
-
require 'skylight/json_proto'
|
|
36
|
-
require 'skylight/subscriber'
|
|
37
|
-
require 'skylight/trace'
|
|
38
|
-
require 'skylight/worker'
|
|
39
|
-
|
|
40
|
-
# Some helper functions
|
|
41
|
-
def self.current_endpoint=(name)
|
|
42
|
-
if t = Trace.current
|
|
43
|
-
t.endpoint = name
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
name
|
|
47
|
-
rescue
|
|
48
|
-
nil
|
|
49
|
-
ensure
|
|
50
|
-
end
|
|
51
|
-
end
|
|
55
|
+
RUBYBIN = File.join(
|
|
56
|
+
RbConfig::CONFIG['bindir'],
|
|
57
|
+
"#{RbConfig::CONFIG['ruby_install_name']}#{RbConfig::CONFIG['EXEEXT']}")
|
|
58
|
+
|
|
59
|
+
# Called by the standalone agent
|
|
60
|
+
Worker::Server.boot if daemon?
|
|
52
61
|
|
|
53
|
-
if defined?(Rails)
|
|
54
|
-
|
|
62
|
+
if defined?(Rails)
|
|
63
|
+
require 'skylight/railtie'
|
|
64
|
+
end
|
|
55
65
|
end
|
data/lib/skylight/api.rb
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Skylight
|
|
2
|
+
class Api
|
|
3
|
+
include Util::Logging
|
|
4
|
+
|
|
5
|
+
attr_reader :config, :http
|
|
6
|
+
|
|
7
|
+
def initialize(config, service = :accounts)
|
|
8
|
+
@config = config
|
|
9
|
+
@http = Util::HTTP.new(config, service)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def authentication
|
|
13
|
+
@http.authentication
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def authentication=(token)
|
|
17
|
+
@http.authentication = token
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def login(email, password)
|
|
21
|
+
res = http.get('/me', 'X-Email' => email, 'X-Password' => password)
|
|
22
|
+
|
|
23
|
+
if res && res.success?
|
|
24
|
+
res.get('me.authentication_token')
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def create_app(name)
|
|
29
|
+
res = @http.post('/apps', { app: { name: name }})
|
|
30
|
+
res if res.success?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
data/lib/skylight/cli.rb
CHANGED
|
@@ -1,92 +1,103 @@
|
|
|
1
|
-
|
|
2
|
-
$:.unshift File.expand_path('../vendor', __FILE__)
|
|
1
|
+
$:.unshift File.expand_path('../vendor/cli', __FILE__)
|
|
3
2
|
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
3
|
+
require 'skylight'
|
|
4
|
+
require 'thor'
|
|
5
|
+
require 'yaml'
|
|
6
|
+
require 'highline'
|
|
7
|
+
require 'active_support/inflector'
|
|
8
8
|
|
|
9
9
|
module Skylight
|
|
10
10
|
class CLI < Thor
|
|
11
|
+
|
|
11
12
|
desc "setup", "Sets up a new app"
|
|
12
13
|
def setup
|
|
13
|
-
if
|
|
14
|
+
if File.exist?(config_path)
|
|
14
15
|
say "Your app is already on Skylight. http://www.skylight.io", :green
|
|
15
16
|
return
|
|
16
17
|
end
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
config = http_config
|
|
20
|
-
|
|
21
|
-
response = Util::HTTP.new(config).create_app(token, app_name)["app"]
|
|
22
|
-
|
|
23
|
-
config.app_id = response["id"]
|
|
24
|
-
config.authentication_token = response["token"]
|
|
19
|
+
api.authentication = load_credentials
|
|
25
20
|
|
|
26
|
-
|
|
21
|
+
unless res = api.create_app(app_name)
|
|
22
|
+
say "Could not create the application", :red
|
|
23
|
+
return
|
|
24
|
+
end
|
|
27
25
|
|
|
28
|
-
config.
|
|
26
|
+
config[:application] = res.get('app.id')
|
|
27
|
+
config[:authentication] = res.get('app.token')
|
|
28
|
+
config.write(config_path)
|
|
29
29
|
|
|
30
30
|
say "Congratulations. Your application is on Skylight! http://www.skylight.io", :green
|
|
31
|
+
rescue Interrupt
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
private
|
|
34
|
-
def user_settings
|
|
35
|
-
File.expand_path("~/.skylight")
|
|
36
|
-
end
|
|
37
35
|
|
|
38
|
-
def
|
|
39
|
-
@
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
def app_name
|
|
37
|
+
@app_name ||=
|
|
38
|
+
begin
|
|
39
|
+
if File.exist?("config/application.rb")
|
|
40
|
+
require "./config/application"
|
|
41
|
+
Rails.application.class.name.split("::").first.underscore.humanize
|
|
42
|
+
else
|
|
43
|
+
File.basename(File.expand_path('.')).humanize
|
|
44
|
+
end
|
|
45
|
+
end
|
|
45
46
|
end
|
|
46
47
|
|
|
47
48
|
def load_credentials
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
end
|
|
49
|
+
load_credentials_from_file || login
|
|
50
|
+
end
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
def login
|
|
53
|
+
10.times do
|
|
54
|
+
email = highline.ask("Email: ")
|
|
55
|
+
password = highline.ask("Password: ") { |q| q.echo = "*" }
|
|
53
56
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
if token = api.login(email, password)
|
|
58
|
+
# Write the token
|
|
59
|
+
FileUtils.mkdir_p(File.dirname(credentials_path))
|
|
60
|
+
File.open(credentials_path, 'w') do |f|
|
|
61
|
+
f.puts YAML.dump('token' => token)
|
|
62
|
+
end
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
if response["authenticated"] == false
|
|
61
|
-
say "Sorry. That email and password was invalid. Please try again", :red
|
|
62
|
-
puts
|
|
63
|
-
else
|
|
64
|
-
token = response["token"]
|
|
65
|
-
break
|
|
64
|
+
return token
|
|
66
65
|
end
|
|
67
|
-
end
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
say "Sorry. That email and password was invalid. Please try again", :red
|
|
68
|
+
puts
|
|
71
69
|
end
|
|
72
70
|
|
|
73
|
-
|
|
71
|
+
say "Could not login", :red
|
|
72
|
+
return
|
|
74
73
|
end
|
|
75
74
|
|
|
76
|
-
def
|
|
77
|
-
|
|
75
|
+
def load_credentials_from_file
|
|
76
|
+
return unless File.exist?(credentials_path)
|
|
77
|
+
return unless yaml = YAML.load_file(credentials_path)
|
|
78
|
+
yaml['token']
|
|
78
79
|
end
|
|
79
80
|
|
|
80
|
-
def
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
81
|
+
def config_path
|
|
82
|
+
File.expand_path('config/skylight.yml')
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def credentials_path
|
|
86
|
+
return nil unless ENV['HOME']
|
|
87
|
+
File.expand_path(".skylight", ENV['HOME'])
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def api
|
|
91
|
+
@api ||= Api.new(config)
|
|
90
92
|
end
|
|
93
|
+
|
|
94
|
+
def highline
|
|
95
|
+
@highline ||= HighLine.new
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def config
|
|
99
|
+
@config ||= Config.new
|
|
100
|
+
end
|
|
101
|
+
|
|
91
102
|
end
|
|
92
103
|
end
|
data/lib/skylight/compat.rb
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
module Skylight
|
|
2
|
-
#
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
# Ensure the version of AS:N being used is recent enough
|
|
3
|
+
begin
|
|
4
|
+
# Attempt to reference an internal class
|
|
5
|
+
ActiveSupport::Notifications::Fanout::Subscribers
|
|
6
|
+
rescue NameError
|
|
7
|
+
# If the class is missing, require our vendored AS::N
|
|
8
|
+
require 'skylight/vendor/active_support/notifications'
|
|
7
9
|
end
|
|
10
|
+
end
|
|
8
11
|
|
|
12
|
+
if defined?(ActiveSupport::Notifications::Fanout::Subscribers::Evented)
|
|
13
|
+
# Handle early RCs of rails 4.0
|
|
14
|
+
class ActiveSupport::Notifications::Fanout::Subscribers::Evented
|
|
15
|
+
unless method_defined?(:publish)
|
|
16
|
+
def publish(name, *args)
|
|
17
|
+
if @delegate.respond_to?(:publish)
|
|
18
|
+
@delegate.publish name, *args
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
9
23
|
end
|
data/lib/skylight/config.rb
CHANGED
|
@@ -1,147 +1,268 @@
|
|
|
1
1
|
require 'yaml'
|
|
2
|
-
require 'logger'
|
|
3
2
|
require 'fileutils'
|
|
3
|
+
require 'logger'
|
|
4
4
|
|
|
5
5
|
module Skylight
|
|
6
6
|
class Config
|
|
7
|
-
class Normalizer < Struct.new(:view_paths)
|
|
8
|
-
end
|
|
9
7
|
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
:
|
|
13
|
-
:
|
|
14
|
-
:
|
|
15
|
-
:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
8
|
+
# Map environment variable keys with Skylight configuration keys
|
|
9
|
+
ENV_TO_KEY = {
|
|
10
|
+
'SK_LOG' => :'log',
|
|
11
|
+
'SK_LOG_LEVEL' => :'log_level',
|
|
12
|
+
'SK_APPLICATION' => :'application',
|
|
13
|
+
'SK_AUTHENTICATION' => :'authentication',
|
|
14
|
+
'SK_AGENT_INTERVAL' => :'agent.interval',
|
|
15
|
+
'SK_AGENT_KEEPALIVE' => :'agent.keepalive',
|
|
16
|
+
'SK_AGENT_SAMPLE_SIZE' => :'agent.sample',
|
|
17
|
+
'SK_AGENT_SOCKFILE_PATH' => :'agent.sockfile_path',
|
|
18
|
+
'SK_REPORT_HOST' => :'report.host',
|
|
19
|
+
'SK_REPORT_PORT' => :'report.port',
|
|
20
|
+
'SK_REPORT_SSL' => :'report.ssl',
|
|
21
|
+
'SK_REPORT_DEFLATE' => :'report.deflate',
|
|
22
|
+
'SK_ACCOUNTS_HOST' => :'accounts.host',
|
|
23
|
+
'SK_ACCOUNTS_PORT' => :'accounts.port',
|
|
24
|
+
'SK_ACCOUNTS_SSL' => :'accounts.ssl',
|
|
25
|
+
'SK_ACCOUNTS_DEFLATE' => :'accounts.deflate' }
|
|
26
|
+
|
|
27
|
+
# Default values for Skylight configuration keys
|
|
28
|
+
DEFAULTS = {
|
|
29
|
+
:'log' => '-'.freeze,
|
|
30
|
+
:'log_level' => 'INFO'.freeze,
|
|
31
|
+
:'agent.keepalive' => 60,
|
|
32
|
+
:'agent.interval' => 5,
|
|
33
|
+
:'agent.sample' => 200,
|
|
34
|
+
:'report.host' => 'agent.skylight.io'.freeze,
|
|
35
|
+
:'report.port' => 443,
|
|
36
|
+
:'report.ssl' => true,
|
|
37
|
+
:'report.deflate' => true,
|
|
38
|
+
:'accounts.host' => 'www.skylight.io'.freeze,
|
|
39
|
+
:'accounts.port' => 443,
|
|
40
|
+
:'accounts.ssl' => true,
|
|
41
|
+
:'accounts.deflate' => false }.freeze
|
|
42
|
+
|
|
43
|
+
REQUIRED = {
|
|
44
|
+
:'authentication' => "authentication token",
|
|
45
|
+
:'report.host' => "skylight remote host",
|
|
46
|
+
:'report.port' => "skylight remote port" }
|
|
47
|
+
|
|
48
|
+
VALIDATORS = {
|
|
49
|
+
:'agent.interval' => lambda { |v, c| Integer === v && v > 0 }
|
|
50
|
+
}
|
|
26
51
|
|
|
27
|
-
|
|
52
|
+
def self.load(path = nil, environment = nil, env = ENV)
|
|
53
|
+
attrs = {}
|
|
54
|
+
version = nil
|
|
28
55
|
|
|
29
|
-
|
|
56
|
+
if path
|
|
57
|
+
begin
|
|
58
|
+
attrs = YAML.load_file(path)
|
|
59
|
+
rescue Exception => e
|
|
60
|
+
raise ConfigError, "could not load config file; msg=#{e.message}"
|
|
30
61
|
end
|
|
62
|
+
|
|
63
|
+
version = File.mtime(path).to_i
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
if env
|
|
67
|
+
attrs[:priority] = remap_env(env)
|
|
31
68
|
end
|
|
32
69
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
70
|
+
new(environment, attrs)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def self.load_from_env(env = ENV)
|
|
74
|
+
self.load(nil, nil, env)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def self.remap_env(env)
|
|
78
|
+
ret = {}
|
|
79
|
+
|
|
80
|
+
env.each do |k, val|
|
|
81
|
+
if key = ENV_TO_KEY[k]
|
|
82
|
+
ret[key] =
|
|
83
|
+
case val
|
|
84
|
+
when /^false$/i then false
|
|
85
|
+
when /^true$/i then true
|
|
86
|
+
when /^(nil|null)$/i then nil
|
|
87
|
+
when /^\d+$/ then val.to_i
|
|
88
|
+
when /^\d+\.\d+$/ then val.to_f
|
|
89
|
+
else val
|
|
90
|
+
end
|
|
36
91
|
end
|
|
92
|
+
end if env
|
|
93
|
+
|
|
94
|
+
ret
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
attr_reader :environment
|
|
98
|
+
|
|
99
|
+
def initialize(*args)
|
|
100
|
+
attrs = {}
|
|
101
|
+
|
|
102
|
+
if Hash === args.last
|
|
103
|
+
attrs = args.pop.dup
|
|
37
104
|
end
|
|
38
105
|
|
|
39
|
-
|
|
106
|
+
@values = {}
|
|
107
|
+
@priority = {}
|
|
108
|
+
@regexp = nil
|
|
109
|
+
|
|
110
|
+
p = attrs.delete(:priority)
|
|
40
111
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
112
|
+
if @environment = args[0]
|
|
113
|
+
@regexp = /^#{Regexp.escape(@environment)}\.(.+)$/
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
attrs.each do |k, v|
|
|
117
|
+
self[k] = v
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
if p
|
|
121
|
+
p.each do |k, v|
|
|
122
|
+
@priority[k.to_sym] = v
|
|
45
123
|
end
|
|
46
124
|
end
|
|
125
|
+
end
|
|
47
126
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
127
|
+
def validate!
|
|
128
|
+
REQUIRED.each do |k, v|
|
|
129
|
+
unless get(k)
|
|
130
|
+
raise ConfigError, "#{v} required"
|
|
131
|
+
end
|
|
51
132
|
end
|
|
52
133
|
|
|
53
|
-
|
|
54
|
-
|
|
134
|
+
true
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def get(key, default = nil, &blk)
|
|
138
|
+
key = key.to_sym
|
|
139
|
+
|
|
140
|
+
return @priority[key] if @priority.key?(key)
|
|
141
|
+
return @values[key] if @values.key?(key)
|
|
142
|
+
return DEFAULTS[key] if DEFAULTS.key?(key)
|
|
143
|
+
|
|
144
|
+
if default
|
|
145
|
+
return default
|
|
146
|
+
elsif blk
|
|
147
|
+
return blk.call(key)
|
|
55
148
|
end
|
|
149
|
+
|
|
150
|
+
nil
|
|
56
151
|
end
|
|
57
152
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
@interval = 5
|
|
65
|
-
@protocol = JsonProto.new(self)
|
|
66
|
-
@enable_gc_profiler = true
|
|
67
|
-
@max_pending_traces = 500
|
|
68
|
-
@samples_per_interval = 100
|
|
153
|
+
alias [] get
|
|
154
|
+
|
|
155
|
+
def set(key, val, scope = nil)
|
|
156
|
+
if scope
|
|
157
|
+
key = [scope, key].join('.')
|
|
158
|
+
end
|
|
69
159
|
|
|
70
|
-
|
|
71
|
-
|
|
160
|
+
if Hash === val
|
|
161
|
+
val.each do |k, v|
|
|
162
|
+
set(k, v, key)
|
|
163
|
+
end
|
|
164
|
+
else
|
|
165
|
+
k = key.to_sym
|
|
72
166
|
|
|
73
|
-
|
|
167
|
+
if validator = VALIDATORS[k]
|
|
168
|
+
unless validator.call(val, self)
|
|
169
|
+
raise ConfigError, "invalid value for #{k} (#{val})"
|
|
170
|
+
end
|
|
171
|
+
end
|
|
74
172
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
send("#{k}=", v)
|
|
173
|
+
if @regexp && key =~ @regexp
|
|
174
|
+
@priority[$1.to_sym] = val
|
|
78
175
|
end
|
|
176
|
+
|
|
177
|
+
@values[k] = val
|
|
79
178
|
end
|
|
179
|
+
end
|
|
80
180
|
|
|
81
|
-
|
|
181
|
+
alias []= set
|
|
82
182
|
|
|
83
|
-
|
|
183
|
+
def to_env
|
|
184
|
+
ret = {}
|
|
84
185
|
|
|
85
|
-
|
|
86
|
-
if
|
|
87
|
-
|
|
88
|
-
else
|
|
89
|
-
@gc_profiler = GC_PROFILER_STUB
|
|
186
|
+
ENV_TO_KEY.each do |k, v|
|
|
187
|
+
if (c = get(v)) != DEFAULTS[v]
|
|
188
|
+
ret[k] = cast_for_env(c)
|
|
90
189
|
end
|
|
91
190
|
end
|
|
191
|
+
|
|
192
|
+
ret
|
|
92
193
|
end
|
|
93
194
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
alias_method :deflate?, :deflate
|
|
113
|
-
|
|
114
|
-
def protocol=(val)
|
|
115
|
-
if val.is_a?(String) || val.is_a?(Symbol)
|
|
116
|
-
class_name = val.to_s.capitalize+"Proto"
|
|
117
|
-
val = Skylight.const_get(class_name).new(self)
|
|
195
|
+
#
|
|
196
|
+
#
|
|
197
|
+
# ===== Writing =====
|
|
198
|
+
#
|
|
199
|
+
#
|
|
200
|
+
|
|
201
|
+
def write(path)
|
|
202
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
203
|
+
|
|
204
|
+
File.open(path, 'w') do |f|
|
|
205
|
+
f.puts <<-YAML
|
|
206
|
+
---
|
|
207
|
+
# The Skylight ID for the application.
|
|
208
|
+
application: #{self[:application]}
|
|
209
|
+
|
|
210
|
+
# The authentication token for the application.
|
|
211
|
+
authentication: #{self[:authentication]}
|
|
212
|
+
YAML
|
|
118
213
|
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
#
|
|
217
|
+
#
|
|
218
|
+
# ===== Helpers =====
|
|
219
|
+
#
|
|
220
|
+
#
|
|
119
221
|
|
|
120
|
-
|
|
222
|
+
def worker
|
|
223
|
+
Worker::Builder.new(self)
|
|
121
224
|
end
|
|
122
225
|
|
|
123
|
-
def
|
|
124
|
-
|
|
226
|
+
def gc
|
|
227
|
+
GC.new(get('gc.profiler', ::GC::Profiler))
|
|
125
228
|
end
|
|
126
229
|
|
|
127
|
-
def
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
230
|
+
def logger
|
|
231
|
+
@logger ||=
|
|
232
|
+
begin
|
|
233
|
+
out = get(:'log')
|
|
234
|
+
out = STDOUT if out == '-'
|
|
235
|
+
|
|
236
|
+
unless IO === out
|
|
237
|
+
FileUtils.mkdir_p(File.dirname(out))
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
l = Logger.new(out)
|
|
241
|
+
l.level =
|
|
242
|
+
case get(:'log_level')
|
|
243
|
+
when /^debug$/i then Logger::DEBUG
|
|
244
|
+
when /^info$/i then Logger::INFO
|
|
245
|
+
when /^warn$/i then Logger::WARN
|
|
246
|
+
when /^error$/i then Logger::ERROR
|
|
247
|
+
end
|
|
248
|
+
l
|
|
131
249
|
end
|
|
132
|
-
logger.level = level
|
|
133
|
-
end
|
|
134
250
|
end
|
|
135
251
|
|
|
136
|
-
def
|
|
137
|
-
|
|
252
|
+
def logger=(logger)
|
|
253
|
+
@logger = logger
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
private
|
|
138
257
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
258
|
+
def cast_for_env(v)
|
|
259
|
+
case v
|
|
260
|
+
when true then 'true'
|
|
261
|
+
when false then 'false'
|
|
262
|
+
when nil then 'nil'
|
|
263
|
+
else v.to_s
|
|
144
264
|
end
|
|
145
265
|
end
|
|
266
|
+
|
|
146
267
|
end
|
|
147
268
|
end
|