skylight 5.0.0.beta5 → 5.1.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +401 -369
- data/CLA.md +1 -1
- data/CONTRIBUTING.md +1 -1
- data/LICENSE.md +7 -17
- data/README.md +1 -1
- data/ext/extconf.rb +42 -54
- data/ext/libskylight.yml +9 -6
- data/lib/skylight.rb +20 -30
- data/lib/skylight/api.rb +22 -18
- data/lib/skylight/cli.rb +47 -46
- data/lib/skylight/cli/doctor.rb +50 -50
- data/lib/skylight/cli/helpers.rb +19 -19
- data/lib/skylight/cli/merger.rb +141 -139
- data/lib/skylight/config.rb +267 -310
- data/lib/skylight/deprecation.rb +4 -4
- data/lib/skylight/errors.rb +3 -4
- data/lib/skylight/extensions.rb +17 -29
- data/lib/skylight/extensions/source_location.rb +128 -128
- data/lib/skylight/formatters/http.rb +1 -3
- data/lib/skylight/gc.rb +30 -40
- data/lib/skylight/helpers.rb +46 -26
- data/lib/skylight/instrumenter.rb +25 -18
- data/lib/skylight/middleware.rb +31 -35
- data/lib/skylight/native.rb +8 -10
- data/lib/skylight/native_ext_fetcher.rb +10 -12
- data/lib/skylight/normalizers.rb +43 -39
- data/lib/skylight/normalizers/action_controller/process_action.rb +24 -25
- data/lib/skylight/normalizers/action_controller/send_file.rb +7 -6
- data/lib/skylight/normalizers/action_dispatch/route_set.rb +7 -7
- data/lib/skylight/normalizers/active_job/perform.rb +48 -44
- data/lib/skylight/normalizers/active_model_serializers/render.rb +7 -3
- data/lib/skylight/normalizers/active_storage.rb +11 -13
- data/lib/skylight/normalizers/active_support/cache.rb +1 -12
- data/lib/skylight/normalizers/coach/handler_finish.rb +1 -3
- data/lib/skylight/normalizers/default.rb +1 -9
- data/lib/skylight/normalizers/faraday/request.rb +1 -3
- data/lib/skylight/normalizers/grape/endpoint.rb +13 -19
- data/lib/skylight/normalizers/grape/endpoint_run.rb +16 -18
- data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +1 -3
- data/lib/skylight/normalizers/graphql/base.rb +23 -28
- data/lib/skylight/normalizers/render.rb +19 -21
- data/lib/skylight/normalizers/shrine.rb +15 -17
- data/lib/skylight/normalizers/sql.rb +4 -4
- data/lib/skylight/probes.rb +38 -46
- data/lib/skylight/probes/action_controller.rb +32 -28
- data/lib/skylight/probes/action_dispatch/request_id.rb +9 -5
- data/lib/skylight/probes/action_dispatch/routing/route_set.rb +7 -5
- data/lib/skylight/probes/action_view.rb +9 -10
- data/lib/skylight/probes/active_job_enqueue.rb +3 -9
- data/lib/skylight/probes/active_model_serializers.rb +8 -8
- data/lib/skylight/probes/delayed_job.rb +37 -42
- data/lib/skylight/probes/elasticsearch.rb +3 -5
- data/lib/skylight/probes/excon.rb +1 -1
- data/lib/skylight/probes/excon/middleware.rb +22 -23
- data/lib/skylight/probes/graphql.rb +2 -7
- data/lib/skylight/probes/middleware.rb +14 -5
- data/lib/skylight/probes/mongo.rb +83 -91
- data/lib/skylight/probes/net_http.rb +1 -1
- data/lib/skylight/probes/redis.rb +5 -17
- data/lib/skylight/probes/sequel.rb +7 -11
- data/lib/skylight/probes/sinatra.rb +8 -5
- data/lib/skylight/probes/tilt.rb +2 -4
- data/lib/skylight/railtie.rb +121 -135
- data/lib/skylight/sidekiq.rb +4 -5
- data/lib/skylight/subscriber.rb +31 -33
- data/lib/skylight/test.rb +89 -84
- data/lib/skylight/trace.rb +121 -115
- data/lib/skylight/user_config.rb +14 -17
- data/lib/skylight/util/clock.rb +1 -0
- data/lib/skylight/util/component.rb +18 -21
- data/lib/skylight/util/deploy.rb +11 -13
- data/lib/skylight/util/http.rb +104 -105
- data/lib/skylight/util/logging.rb +4 -6
- data/lib/skylight/util/lru_cache.rb +2 -6
- data/lib/skylight/util/platform.rb +2 -6
- data/lib/skylight/util/ssl.rb +1 -25
- data/lib/skylight/version.rb +1 -1
- data/lib/skylight/vm/gc.rb +1 -9
- metadata +19 -5
data/lib/skylight/config.rb
CHANGED
@@ -22,111 +22,96 @@ module Skylight
|
|
22
22
|
# Map environment variable keys with Skylight configuration keys
|
23
23
|
ENV_TO_KEY = {
|
24
24
|
# == Authentication ==
|
25
|
-
-"AUTHENTICATION"
|
26
|
-
|
25
|
+
-"AUTHENTICATION" => :authentication,
|
27
26
|
# == App settings ==
|
28
|
-
-"ROOT"
|
29
|
-
-"HOSTNAME"
|
30
|
-
-"SESSION_TOKEN"
|
31
|
-
|
27
|
+
-"ROOT" => :root,
|
28
|
+
-"HOSTNAME" => :hostname,
|
29
|
+
-"SESSION_TOKEN" => :session_token,
|
32
30
|
# == Component settings ==
|
33
|
-
-"ENV"
|
34
|
-
-"COMPONENT"
|
35
|
-
-"REPORT_RAILS_ENV"
|
36
|
-
|
31
|
+
-"ENV" => :env,
|
32
|
+
-"COMPONENT" => :component,
|
33
|
+
-"REPORT_RAILS_ENV" => :report_rails_env,
|
37
34
|
# == Deploy settings ==
|
38
|
-
-"DEPLOY_ID"
|
39
|
-
-"DEPLOY_GIT_SHA"
|
40
|
-
-"DEPLOY_DESCRIPTION"
|
41
|
-
|
35
|
+
-"DEPLOY_ID" => :'deploy.id',
|
36
|
+
-"DEPLOY_GIT_SHA" => :'deploy.git_sha',
|
37
|
+
-"DEPLOY_DESCRIPTION" => :'deploy.description',
|
42
38
|
# == Logging ==
|
43
|
-
-"LOG_FILE"
|
44
|
-
-"LOG_LEVEL"
|
45
|
-
-"ALERT_LOG_FILE"
|
46
|
-
-"NATIVE_LOG_FILE"
|
47
|
-
-"
|
48
|
-
|
39
|
+
-"LOG_FILE" => :log_file,
|
40
|
+
-"LOG_LEVEL" => :log_level,
|
41
|
+
-"ALERT_LOG_FILE" => :alert_log_file,
|
42
|
+
-"NATIVE_LOG_FILE" => :native_log_file,
|
43
|
+
-"NATIVE_LOG_LEVEL" => :native_log_level,
|
44
|
+
-"LOG_SQL_PARSE_ERRORS" => :log_sql_parse_errors,
|
49
45
|
# == Proxy ==
|
50
|
-
-"PROXY_URL"
|
51
|
-
|
46
|
+
-"PROXY_URL" => :proxy_url,
|
52
47
|
# == Instrumenter ==
|
53
|
-
-"ENABLE_SEGMENTS"
|
54
|
-
-"ENABLE_SIDEKIQ"
|
55
|
-
-"IGNORED_ENDPOINT"
|
56
|
-
-"IGNORED_ENDPOINTS"
|
57
|
-
-"SINATRA_ROUTE_PREFIXES"
|
58
|
-
-"ENABLE_SOURCE_LOCATIONS"
|
59
|
-
|
48
|
+
-"ENABLE_SEGMENTS" => :enable_segments,
|
49
|
+
-"ENABLE_SIDEKIQ" => :enable_sidekiq,
|
50
|
+
-"IGNORED_ENDPOINT" => :ignored_endpoint,
|
51
|
+
-"IGNORED_ENDPOINTS" => :ignored_endpoints,
|
52
|
+
-"SINATRA_ROUTE_PREFIXES" => :sinatra_route_prefixes,
|
53
|
+
-"ENABLE_SOURCE_LOCATIONS" => :enable_source_locations,
|
60
54
|
# == Max Span Handling ==
|
61
|
-
-"REPORT_MAX_SPANS_EXCEEDED"
|
62
|
-
-"PRUNE_LARGE_TRACES"
|
63
|
-
|
55
|
+
-"REPORT_MAX_SPANS_EXCEEDED" => :report_max_spans_exceeded,
|
56
|
+
-"PRUNE_LARGE_TRACES" => :prune_large_traces,
|
64
57
|
# == Skylight Remote ==
|
65
|
-
-"AUTH_URL"
|
66
|
-
-"APP_CREATE_URL"
|
67
|
-
-"MERGES_URL"
|
68
|
-
-"VALIDATION_URL"
|
69
|
-
-"AUTH_HTTP_DEFLATE"
|
70
|
-
-"AUTH_HTTP_CONNECT_TIMEOUT"
|
71
|
-
-"AUTH_HTTP_READ_TIMEOUT"
|
72
|
-
-"REPORT_URL"
|
73
|
-
-"REPORT_HTTP_DEFLATE"
|
74
|
-
-"REPORT_HTTP_CONNECT_TIMEOUT"
|
75
|
-
-"REPORT_HTTP_READ_TIMEOUT"
|
76
|
-
-"REPORT_HTTP_DISABLED"
|
77
|
-
|
58
|
+
-"AUTH_URL" => :auth_url,
|
59
|
+
-"APP_CREATE_URL" => :app_create_url,
|
60
|
+
-"MERGES_URL" => :merges_url,
|
61
|
+
-"VALIDATION_URL" => :validation_url,
|
62
|
+
-"AUTH_HTTP_DEFLATE" => :auth_http_deflate,
|
63
|
+
-"AUTH_HTTP_CONNECT_TIMEOUT" => :auth_http_connect_timeout,
|
64
|
+
-"AUTH_HTTP_READ_TIMEOUT" => :auth_http_read_timeout,
|
65
|
+
-"REPORT_URL" => :report_url,
|
66
|
+
-"REPORT_HTTP_DEFLATE" => :report_http_deflate,
|
67
|
+
-"REPORT_HTTP_CONNECT_TIMEOUT" => :report_http_connect_timeout,
|
68
|
+
-"REPORT_HTTP_READ_TIMEOUT" => :report_http_read_timeout,
|
69
|
+
-"REPORT_HTTP_DISABLED" => :report_http_disabled,
|
78
70
|
# == Native agent settings ==
|
79
71
|
#
|
80
|
-
-"LAZY_START"
|
81
|
-
-"DAEMON_EXEC_PATH"
|
82
|
-
-"DAEMON_LIB_PATH"
|
83
|
-
-"PIDFILE_PATH"
|
84
|
-
-"SOCKDIR_PATH"
|
85
|
-
-"BATCH_QUEUE_DEPTH"
|
86
|
-
-"BATCH_SAMPLE_SIZE"
|
87
|
-
-"BATCH_FLUSH_INTERVAL"
|
88
|
-
-"DAEMON_TICK_INTERVAL"
|
89
|
-
-"DAEMON_LOCK_CHECK_INTERVAL"
|
90
|
-
-"DAEMON_INACTIVITY_TIMEOUT"
|
91
|
-
-"CLIENT_MAX_TRIES"
|
92
|
-
-"CLIENT_CONN_TRY_WIN"
|
93
|
-
-"MAX_PRESPAWN_JITTER"
|
94
|
-
-"DAEMON_WAIT_TIMEOUT"
|
95
|
-
-"CLIENT_CHECK_INTERVAL"
|
96
|
-
-"CLIENT_QUEUE_DEPTH"
|
97
|
-
-"CLIENT_WRITE_TIMEOUT"
|
98
|
-
-"SSL_CERT_PATH"
|
99
|
-
-"
|
100
|
-
|
72
|
+
-"LAZY_START" => :'daemon.lazy_start',
|
73
|
+
-"DAEMON_EXEC_PATH" => :'daemon.exec_path',
|
74
|
+
-"DAEMON_LIB_PATH" => :'daemon.lib_path',
|
75
|
+
-"PIDFILE_PATH" => :'daemon.pidfile_path',
|
76
|
+
-"SOCKDIR_PATH" => :'daemon.sockdir_path',
|
77
|
+
-"BATCH_QUEUE_DEPTH" => :'daemon.batch_queue_depth',
|
78
|
+
-"BATCH_SAMPLE_SIZE" => :'daemon.batch_sample_size',
|
79
|
+
-"BATCH_FLUSH_INTERVAL" => :'daemon.batch_flush_interval',
|
80
|
+
-"DAEMON_TICK_INTERVAL" => :'daemon.tick_interval',
|
81
|
+
-"DAEMON_LOCK_CHECK_INTERVAL" => :'daemon.lock_check_interval',
|
82
|
+
-"DAEMON_INACTIVITY_TIMEOUT" => :'daemon.inactivity_timeout',
|
83
|
+
-"CLIENT_MAX_TRIES" => :'daemon.max_connect_tries',
|
84
|
+
-"CLIENT_CONN_TRY_WIN" => :'daemon.connect_try_window',
|
85
|
+
-"MAX_PRESPAWN_JITTER" => :'daemon.max_prespawn_jitter',
|
86
|
+
-"DAEMON_WAIT_TIMEOUT" => :'daemon.wait_timeout',
|
87
|
+
-"CLIENT_CHECK_INTERVAL" => :'daemon.client_check_interval',
|
88
|
+
-"CLIENT_QUEUE_DEPTH" => :'daemon.client_queue_depth',
|
89
|
+
-"CLIENT_WRITE_TIMEOUT" => :'daemon.client_write_timeout',
|
90
|
+
-"SSL_CERT_PATH" => :'daemon.ssl_cert_path',
|
91
|
+
-"ENABLE_TCP" => :'daemon.enable_tcp',
|
92
|
+
-"TCP_PORT" => :'daemon.tcp_port',
|
101
93
|
# == Legacy env vars ==
|
102
94
|
#
|
103
|
-
-"AGENT_LOCKFILE"
|
104
|
-
-"AGENT_SOCKFILE_PATH"
|
105
|
-
|
95
|
+
-"AGENT_LOCKFILE" => :'agent.lockfile',
|
96
|
+
-"AGENT_SOCKFILE_PATH" => :'agent.sockfile_path',
|
106
97
|
# == User config settings ==
|
107
|
-
-"USER_CONFIG_PATH"
|
108
|
-
|
98
|
+
-"USER_CONFIG_PATH" => :user_config_path,
|
109
99
|
# == Heroku settings ==
|
110
|
-
-"HEROKU_DYNO_INFO_PATH"
|
111
|
-
|
100
|
+
-"HEROKU_DYNO_INFO_PATH" => :'heroku.dyno_info_path',
|
112
101
|
# == Source Location ==
|
113
102
|
-"SOURCE_LOCATION_IGNORED_GEMS" => :source_location_ignored_gems,
|
114
|
-
-"SOURCE_LOCATION_CACHE_SIZE"
|
103
|
+
-"SOURCE_LOCATION_CACHE_SIZE" => :source_location_cache_size
|
115
104
|
}.freeze
|
116
105
|
|
117
106
|
KEY_TO_NATIVE_ENV = {
|
118
107
|
# We use different log files for native and Ruby, but the native code doesn't know this
|
119
|
-
native_log_file:
|
108
|
+
native_log_file: "LOG_FILE",
|
120
109
|
native_log_level: "LOG_LEVEL"
|
121
110
|
}.freeze
|
122
111
|
|
123
112
|
SERVER_VALIDATE = %i[].freeze
|
124
113
|
|
125
|
-
DEFAULT_IGNORED_SOURCE_LOCATION_GEMS = [
|
126
|
-
-"skylight",
|
127
|
-
-"activesupport",
|
128
|
-
-"activerecord"
|
129
|
-
].freeze
|
114
|
+
DEFAULT_IGNORED_SOURCE_LOCATION_GEMS = [-"skylight", -"activesupport", -"activerecord"].freeze
|
130
115
|
|
131
116
|
# Default values for Skylight configuration keys
|
132
117
|
def self.default_values
|
@@ -134,38 +119,32 @@ module Skylight
|
|
134
119
|
begin
|
135
120
|
ret = {
|
136
121
|
# URLs
|
137
|
-
auth_url:
|
138
|
-
app_create_url:
|
139
|
-
merges_url:
|
140
|
-
validation_url:
|
141
|
-
|
122
|
+
auth_url: -"https://auth.skylight.io/agent",
|
123
|
+
app_create_url: -"https://www.skylight.io/apps",
|
124
|
+
merges_url: -"https://www.skylight.io/merges",
|
125
|
+
validation_url: -"https://auth.skylight.io/agent/config",
|
142
126
|
# Logging
|
143
|
-
log_file:
|
144
|
-
log_level:
|
145
|
-
alert_log_file:
|
146
|
-
log_sql_parse_errors:
|
147
|
-
|
127
|
+
log_file: -"-",
|
128
|
+
log_level: -"INFO",
|
129
|
+
alert_log_file: -"-",
|
130
|
+
log_sql_parse_errors: true,
|
131
|
+
native_log_level: -"warn",
|
148
132
|
# Features
|
149
|
-
enable_segments:
|
150
|
-
enable_sidekiq:
|
151
|
-
sinatra_route_prefixes:
|
152
|
-
enable_source_locations:
|
153
|
-
|
133
|
+
enable_segments: true,
|
134
|
+
enable_sidekiq: false,
|
135
|
+
sinatra_route_prefixes: false,
|
136
|
+
enable_source_locations: true,
|
154
137
|
# Deploys
|
155
|
-
'heroku.dyno_info_path':
|
156
|
-
report_rails_env:
|
157
|
-
|
138
|
+
'heroku.dyno_info_path': -"/etc/heroku/dyno",
|
139
|
+
report_rails_env: true,
|
158
140
|
# Daemon
|
159
|
-
'daemon.lazy_start':
|
160
|
-
hostname:
|
141
|
+
'daemon.lazy_start': true,
|
142
|
+
hostname: Util::Hostname.default_hostname,
|
161
143
|
report_max_spans_exceeded: false,
|
162
|
-
prune_large_traces:
|
144
|
+
prune_large_traces: true
|
163
145
|
}
|
164
146
|
|
165
|
-
unless Util::Platform::OS == -"darwin"
|
166
|
-
ret[:'daemon.ssl_cert_path'] = Util::SSL.ca_cert_file_or_default
|
167
|
-
ret[:'daemon.ssl_cert_dir'] = Util::SSL.ca_cert_dir
|
168
|
-
end
|
147
|
+
ret[:'daemon.ssl_cert_path'] = Util::SSL.ca_cert_file_or_default unless Util::Platform::OS == -"darwin"
|
169
148
|
|
170
149
|
if Skylight.native?
|
171
150
|
native_path = Skylight.libskylight_path
|
@@ -180,65 +159,64 @@ module Skylight
|
|
180
159
|
|
181
160
|
REQUIRED_KEYS = {
|
182
161
|
authentication: "authentication token",
|
183
|
-
hostname:
|
184
|
-
auth_url:
|
162
|
+
hostname: "server hostname",
|
163
|
+
auth_url: "authentication url",
|
185
164
|
validation_url: "config validation url"
|
186
165
|
}.freeze
|
187
166
|
|
188
167
|
def self.native_env_keys
|
189
|
-
@native_env_keys ||=
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
168
|
+
@native_env_keys ||=
|
169
|
+
%i[
|
170
|
+
native_log_level
|
171
|
+
native_log_file
|
172
|
+
log_sql_parse_errors
|
173
|
+
version
|
174
|
+
root
|
175
|
+
proxy_url
|
176
|
+
hostname
|
177
|
+
session_token
|
178
|
+
auth_url
|
179
|
+
auth_http_deflate
|
180
|
+
auth_http_connect_timeout
|
181
|
+
auth_http_read_timeout
|
182
|
+
report_url
|
183
|
+
report_http_deflate
|
184
|
+
report_http_connect_timeout
|
185
|
+
report_http_read_timeout
|
186
|
+
report_http_disabled
|
187
|
+
daemon.lazy_start
|
188
|
+
daemon.exec_path
|
189
|
+
daemon.lib_path
|
190
|
+
daemon.pidfile_path
|
191
|
+
daemon.sockdir_path
|
192
|
+
daemon.batch_queue_depth
|
193
|
+
daemon.batch_sample_size
|
194
|
+
daemon.batch_flush_interval
|
195
|
+
daemon.tick_interval
|
196
|
+
daemon.lock_check_interval
|
197
|
+
daemon.inactivity_timeout
|
198
|
+
daemon.max_connect_tries
|
199
|
+
daemon.connect_try_window
|
200
|
+
daemon.max_prespawn_jitter
|
201
|
+
daemon.wait_timeout
|
202
|
+
daemon.client_check_interval
|
203
|
+
daemon.client_queue_depth
|
204
|
+
daemon.client_write_timeout
|
205
|
+
daemon.ssl_cert_path
|
206
|
+
daemon.ssl_cert_dir
|
207
|
+
daemon.enable_tcp
|
208
|
+
daemon.tcp_port
|
209
|
+
]
|
228
210
|
end
|
229
211
|
|
230
212
|
# Maps legacy config keys to new config keys
|
231
213
|
def self.legacy_keys
|
232
|
-
@legacy_keys ||= {
|
233
|
-
'agent.sockfile_path': :'daemon.sockdir_path',
|
234
|
-
'agent.lockfile': :'daemon.pidfile_path'
|
235
|
-
}
|
214
|
+
@legacy_keys ||= { 'agent.sockfile_path': :'daemon.sockdir_path', 'agent.lockfile': :'daemon.pidfile_path' }
|
236
215
|
end
|
237
216
|
|
238
217
|
def self.validators
|
239
|
-
@validators ||=
|
240
|
-
'agent.interval': [->(v, _c) { v.is_a?(Integer) && v > 0 }, "must be an integer greater than 0"]
|
241
|
-
}
|
218
|
+
@validators ||=
|
219
|
+
{ 'agent.interval': [->(v, _c) { v.is_a?(Integer) && v > 0 }, "must be an integer greater than 0"] }
|
242
220
|
end
|
243
221
|
|
244
222
|
# @api private
|
@@ -248,9 +226,7 @@ module Skylight
|
|
248
226
|
def initialize(*args)
|
249
227
|
attrs = {}
|
250
228
|
|
251
|
-
if args.last.is_a?(Hash)
|
252
|
-
attrs = args.pop.dup
|
253
|
-
end
|
229
|
+
attrs = args.pop.dup if args.last.is_a?(Hash)
|
254
230
|
|
255
231
|
@values = {}
|
256
232
|
@priority = {}
|
@@ -264,13 +240,9 @@ module Skylight
|
|
264
240
|
@priority_regexp = /^#{Regexp.escape(priority_key)}\.(.+)$/
|
265
241
|
end
|
266
242
|
|
267
|
-
attrs.each
|
268
|
-
self[k] = v
|
269
|
-
end
|
243
|
+
attrs.each { |k, v| self[k] = v }
|
270
244
|
|
271
|
-
p&.each
|
272
|
-
@priority[self.class.remap_key(k)] = v
|
273
|
-
end
|
245
|
+
p&.each { |k, v| @priority[self.class.remap_key(k)] = v }
|
274
246
|
end
|
275
247
|
|
276
248
|
def self.load(opts = {}, env = ENV)
|
@@ -282,10 +254,8 @@ module Skylight
|
|
282
254
|
if path
|
283
255
|
error = nil
|
284
256
|
begin
|
285
|
-
attrs =
|
286
|
-
|
287
|
-
[], # permitted_symbols
|
288
|
-
true) # aliases enabled
|
257
|
+
attrs =
|
258
|
+
YAML.safe_load(ERB.new(File.read(path)).result, permitted_classes: [], permitted_symbols: [], aliases: true)
|
289
259
|
error = "empty file" unless attrs
|
290
260
|
error = "invalid format" if attrs && !attrs.is_a?(Hash)
|
291
261
|
rescue Exception => e
|
@@ -298,15 +268,11 @@ module Skylight
|
|
298
268
|
# The key-value pairs in this `priority` option are inserted into the
|
299
269
|
# config's @priority hash *after* anything listed under priority_key;
|
300
270
|
# i.e., ENV takes precendence over priority_key
|
301
|
-
if env
|
302
|
-
attrs[:priority] = remap_env(env)
|
303
|
-
end
|
271
|
+
attrs[:priority] = remap_env(env) if env
|
304
272
|
|
305
273
|
config = new(priority_key, attrs)
|
306
274
|
|
307
|
-
opts.each
|
308
|
-
config[k] = v
|
309
|
-
end
|
275
|
+
opts.each { |k, v| config[k] = v }
|
310
276
|
|
311
277
|
config
|
312
278
|
end
|
@@ -333,12 +299,18 @@ module Skylight
|
|
333
299
|
|
334
300
|
ret[key] =
|
335
301
|
case val
|
336
|
-
when /^false$/i
|
337
|
-
|
338
|
-
when /^
|
339
|
-
|
340
|
-
when
|
341
|
-
|
302
|
+
when /^false$/i
|
303
|
+
false
|
304
|
+
when /^true$/i
|
305
|
+
true
|
306
|
+
when /^(nil|null)$/i
|
307
|
+
nil
|
308
|
+
when /^\d+$/
|
309
|
+
val.to_i
|
310
|
+
when /^\d+\.\d+$/
|
311
|
+
val.to_f
|
312
|
+
else
|
313
|
+
val
|
342
314
|
end
|
343
315
|
end
|
344
316
|
|
@@ -347,11 +319,7 @@ module Skylight
|
|
347
319
|
|
348
320
|
# @api private
|
349
321
|
def validate!
|
350
|
-
REQUIRED_KEYS.each
|
351
|
-
unless get(k)
|
352
|
-
raise ConfigError, "#{v} required"
|
353
|
-
end
|
354
|
-
end
|
322
|
+
REQUIRED_KEYS.each { |k, v| raise ConfigError, "#{v} required" unless get(k) }
|
355
323
|
|
356
324
|
log_file = self[:log_file]
|
357
325
|
alert_log_file = self[:alert_log_file]
|
@@ -359,6 +327,7 @@ module Skylight
|
|
359
327
|
|
360
328
|
check_logfile_permissions(log_file, "log_file")
|
361
329
|
check_logfile_permissions(alert_log_file, "alert_log_file")
|
330
|
+
|
362
331
|
# TODO: Support rotation interpolation in this check
|
363
332
|
check_logfile_permissions(native_log_file, "native_log_file")
|
364
333
|
|
@@ -378,15 +347,20 @@ module Skylight
|
|
378
347
|
file_root = File.dirname(file)
|
379
348
|
|
380
349
|
# Try to make the directory, don't blow up if we can't. Our writable? check will fail later.
|
381
|
-
|
350
|
+
begin
|
351
|
+
FileUtils.mkdir_p file_root
|
352
|
+
rescue StandardError
|
353
|
+
nil
|
354
|
+
end
|
382
355
|
|
383
356
|
if File.exist?(file) && !FileTest.writable?(file)
|
384
357
|
raise ConfigError, "File `#{file}` is not writable. Please set #{key} in your config to a writable path"
|
385
358
|
end
|
386
359
|
|
387
360
|
unless FileTest.writable?(file_root)
|
388
|
-
raise ConfigError,
|
389
|
-
|
361
|
+
raise ConfigError,
|
362
|
+
"Directory `#{file_root}` is not writable. Please set #{key} in your config to a " \
|
363
|
+
"writable path"
|
390
364
|
end
|
391
365
|
end
|
392
366
|
|
@@ -406,7 +380,7 @@ module Skylight
|
|
406
380
|
key = self.class.remap_key(key)
|
407
381
|
|
408
382
|
return @priority[key] if @priority.key?(key)
|
409
|
-
return @values[key]
|
383
|
+
return @values[key] if @values.key?(key)
|
410
384
|
return self.class.default_values[key] if self.class.default_values.key?(key)
|
411
385
|
|
412
386
|
if default
|
@@ -421,14 +395,10 @@ module Skylight
|
|
421
395
|
alias [] get
|
422
396
|
|
423
397
|
def set(key, val, scope = nil)
|
424
|
-
if scope
|
425
|
-
key = [scope, key].join(".")
|
426
|
-
end
|
398
|
+
key = [scope, key].join(".") if scope
|
427
399
|
|
428
400
|
if val.is_a?(Hash)
|
429
|
-
val.each
|
430
|
-
set(k, v, key)
|
431
|
-
end
|
401
|
+
val.each { |k, v| set(k, v, key) }
|
432
402
|
else
|
433
403
|
k = self.class.remap_key(key)
|
434
404
|
|
@@ -442,9 +412,7 @@ module Skylight
|
|
442
412
|
end
|
443
413
|
end
|
444
414
|
|
445
|
-
if @priority_regexp && k =~ @priority_regexp
|
446
|
-
@priority[$1.to_sym] = val
|
447
|
-
end
|
415
|
+
@priority[$1.to_sym] = val if @priority_regexp && k =~ @priority_regexp
|
448
416
|
|
449
417
|
@values[k] = val
|
450
418
|
end
|
@@ -466,7 +434,8 @@ module Skylight
|
|
466
434
|
v / 1_000
|
467
435
|
when "nanos"
|
468
436
|
v / 1_000_000
|
469
|
-
else
|
437
|
+
else
|
438
|
+
# "s", "sec", nil
|
470
439
|
v * 1000
|
471
440
|
end
|
472
441
|
else
|
@@ -477,13 +446,16 @@ module Skylight
|
|
477
446
|
def to_native_env
|
478
447
|
ret = []
|
479
448
|
|
480
|
-
self
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
449
|
+
self
|
450
|
+
.class
|
451
|
+
.native_env_keys
|
452
|
+
.each do |key|
|
453
|
+
value = send_or_get(key)
|
454
|
+
unless value.nil?
|
455
|
+
env_key = KEY_TO_NATIVE_ENV[key] || ENV_TO_KEY.key(key) || key.upcase
|
456
|
+
ret << "SKYLIGHT_#{env_key}" << cast_for_env(value)
|
457
|
+
end
|
485
458
|
end
|
486
|
-
end
|
487
459
|
|
488
460
|
ret << "SKYLIGHT_AUTHENTICATION" << authentication_with_meta
|
489
461
|
ret << "SKYLIGHT_VALIDATE_AUTHENTICATION" << "false"
|
@@ -514,9 +486,7 @@ module Skylight
|
|
514
486
|
|
515
487
|
# If, for some odd reason you have a comma in your endpoint name, use the
|
516
488
|
# YML config instead.
|
517
|
-
if ignored_endpoints.is_a?(String)
|
518
|
-
ignored_endpoints = ignored_endpoints.split(/\s*,\s*/)
|
519
|
-
end
|
489
|
+
ignored_endpoints = ignored_endpoints.split(/\s*,\s*/) if ignored_endpoints.is_a?(String)
|
520
490
|
|
521
491
|
val = Array(get(:ignored_endpoint))
|
522
492
|
val.concat(Array(ignored_endpoints))
|
@@ -529,9 +499,7 @@ module Skylight
|
|
529
499
|
@source_location_ignored_gems ||=
|
530
500
|
begin
|
531
501
|
ignored_gems = get(:source_location_ignored_gems)
|
532
|
-
if ignored_gems.is_a?(String)
|
533
|
-
ignored_gems = ignored_gems.split(/\s*,\s*/)
|
534
|
-
end
|
502
|
+
ignored_gems = ignored_gems.split(/\s*,\s*/) if ignored_gems.is_a?(String)
|
535
503
|
|
536
504
|
Array(ignored_gems) | DEFAULT_IGNORED_SOURCE_LOCATION_GEMS
|
537
505
|
end
|
@@ -547,61 +515,56 @@ module Skylight
|
|
547
515
|
Logger::DEBUG
|
548
516
|
else
|
549
517
|
case get(:log_level)
|
550
|
-
when /^debug$/i
|
551
|
-
|
552
|
-
when /^
|
553
|
-
|
554
|
-
when /^
|
555
|
-
|
518
|
+
when /^debug$/i
|
519
|
+
Logger::DEBUG
|
520
|
+
when /^info$/i
|
521
|
+
Logger::INFO
|
522
|
+
when /^warn$/i
|
523
|
+
Logger::WARN
|
524
|
+
when /^error$/i
|
525
|
+
Logger::ERROR
|
526
|
+
when /^fatal$/i
|
527
|
+
Logger::FATAL
|
528
|
+
else
|
529
|
+
Logger::ERROR
|
556
530
|
end
|
557
531
|
end
|
558
532
|
end
|
559
533
|
|
560
534
|
def native_log_level
|
561
|
-
|
562
|
-
if trace?
|
563
|
-
"trace"
|
564
|
-
else
|
565
|
-
case log_level
|
566
|
-
when Logger::DEBUG then "debug"
|
567
|
-
when Logger::INFO then "info"
|
568
|
-
when Logger::WARN then "warn"
|
569
|
-
else "error"
|
570
|
-
end
|
571
|
-
end
|
535
|
+
get(:native_log_level).to_s.downcase
|
572
536
|
end
|
573
537
|
|
574
538
|
def logger
|
575
|
-
@logger ||=
|
576
|
-
MUTEX.synchronize do
|
577
|
-
load_logger
|
578
|
-
end
|
539
|
+
@logger ||= MUTEX.synchronize { load_logger }
|
579
540
|
end
|
580
541
|
|
581
542
|
def native_log_file
|
582
|
-
@native_log_file ||=
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
543
|
+
@native_log_file ||=
|
544
|
+
get("native_log_file") do
|
545
|
+
log_file = self["log_file"]
|
546
|
+
return "-" if log_file == "-"
|
547
|
+
|
548
|
+
parts = log_file.to_s.split(".")
|
549
|
+
parts.insert(-2, "native")
|
550
|
+
parts.join(".")
|
551
|
+
end
|
590
552
|
end
|
591
553
|
|
592
554
|
attr_writer :logger, :alert_logger
|
593
555
|
|
594
556
|
def alert_logger
|
595
|
-
@alert_logger ||=
|
596
|
-
|
597
|
-
|
598
|
-
|
557
|
+
@alert_logger ||=
|
558
|
+
MUTEX.synchronize do
|
559
|
+
unless (l = @alert_logger)
|
560
|
+
out = get(:alert_log_file)
|
561
|
+
out = Util::AlertLogger.new(load_logger) if out == "-"
|
599
562
|
|
600
|
-
|
601
|
-
|
563
|
+
l = create_logger(out, level: Logger::DEBUG)
|
564
|
+
end
|
602
565
|
|
603
|
-
|
604
|
-
|
566
|
+
l
|
567
|
+
end
|
605
568
|
end
|
606
569
|
|
607
570
|
def enable_segments?
|
@@ -630,36 +593,41 @@ module Skylight
|
|
630
593
|
|
631
594
|
private
|
632
595
|
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
# May be redundant since we also do this in the permissions check
|
637
|
-
FileUtils.mkdir_p(File.dirname(out))
|
638
|
-
end
|
596
|
+
def create_logger(out, level: :info)
|
597
|
+
if out.is_a?(String)
|
598
|
+
out = File.expand_path(out, root)
|
639
599
|
|
640
|
-
|
641
|
-
|
642
|
-
Logger.new($stdout, progname: "Skylight", level: level)
|
600
|
+
# May be redundant since we also do this in the permissions check
|
601
|
+
FileUtils.mkdir_p(File.dirname(out))
|
643
602
|
end
|
644
603
|
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
l = create_logger(out, level: log_level)
|
650
|
-
end
|
604
|
+
Logger.new(out, progname: "Skylight", level: level)
|
605
|
+
rescue StandardError
|
606
|
+
Logger.new($stdout, progname: "Skylight", level: level)
|
607
|
+
end
|
651
608
|
|
652
|
-
|
609
|
+
def load_logger
|
610
|
+
unless (l = @logger)
|
611
|
+
out = get(:log_file)
|
612
|
+
out = $stdout if out == "-"
|
613
|
+
l = create_logger(out, level: log_level)
|
653
614
|
end
|
654
615
|
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
616
|
+
l
|
617
|
+
end
|
618
|
+
|
619
|
+
def cast_for_env(val)
|
620
|
+
case val
|
621
|
+
when true
|
622
|
+
"true"
|
623
|
+
when false
|
624
|
+
"false"
|
625
|
+
when nil
|
626
|
+
"nil"
|
627
|
+
else
|
628
|
+
val.to_s
|
662
629
|
end
|
630
|
+
end
|
663
631
|
|
664
632
|
public
|
665
633
|
|
@@ -676,22 +644,18 @@ module Skylight
|
|
676
644
|
return false
|
677
645
|
end
|
678
646
|
|
679
|
-
if res.error_response?
|
680
|
-
warn("Unable to reach server for config validation")
|
681
|
-
end
|
647
|
+
warn("Unable to reach server for config validation") if res.error_response?
|
682
648
|
|
683
649
|
unless res.config_valid?
|
684
650
|
warn("Invalid configuration") unless res.error_response?
|
685
|
-
res.validation_errors.each
|
686
|
-
warn(" #{k}: #{v}")
|
687
|
-
end
|
651
|
+
res.validation_errors.each { |k, v| warn(" #{k}: #{v}") }
|
688
652
|
|
689
653
|
return false if res.forbidden?
|
690
654
|
|
691
655
|
corrected_config = res.corrected_config
|
692
656
|
|
693
657
|
# Use defaults if no corrected config is available. This will happen if the request failed.
|
694
|
-
corrected_config ||=
|
658
|
+
corrected_config ||= SERVER_VALIDATE.map { |k| [k, self.class.default_values.fetch(k)] }.to_h
|
695
659
|
|
696
660
|
config_to_update = corrected_config.reject { |k, v| get(k) == v }
|
697
661
|
unless config_to_update.empty?
|
@@ -713,29 +677,33 @@ module Skylight
|
|
713
677
|
|
714
678
|
def check_sockdir_permissions(sockdir_path)
|
715
679
|
# Try to make the directory, don't blow up if we can't. Our writable? check will fail later.
|
716
|
-
|
680
|
+
begin
|
681
|
+
FileUtils.mkdir_p sockdir_path
|
682
|
+
rescue StandardError
|
683
|
+
nil
|
684
|
+
end
|
717
685
|
|
718
686
|
unless FileTest.writable?(sockdir_path)
|
719
|
-
raise ConfigError,
|
720
|
-
|
687
|
+
raise ConfigError,
|
688
|
+
"Directory `#{sockdir_path}` is not writable. Please set daemon.sockdir_path in " \
|
689
|
+
"your config to a writable path"
|
721
690
|
end
|
722
691
|
|
723
692
|
if check_nfs(sockdir_path)
|
724
|
-
raise ConfigError,
|
725
|
-
|
693
|
+
raise ConfigError,
|
694
|
+
"Directory `#{sockdir_path}` is an NFS mount and will not allow sockets. Please set " \
|
695
|
+
"daemon.sockdir_path in your config to a non-NFS path."
|
726
696
|
end
|
727
697
|
end
|
728
698
|
|
729
699
|
def write(path)
|
730
700
|
FileUtils.mkdir_p(File.dirname(path))
|
731
701
|
|
732
|
-
File.open(path, "w")
|
733
|
-
f.puts <<~YAML
|
702
|
+
File.open(path, "w") { |f| f.puts <<~YAML }
|
734
703
|
---
|
735
704
|
# The authentication token for the application.
|
736
705
|
authentication: #{self[:authentication]}
|
737
706
|
YAML
|
738
|
-
end
|
739
707
|
end
|
740
708
|
|
741
709
|
#
|
@@ -765,17 +733,11 @@ module Skylight
|
|
765
733
|
end
|
766
734
|
|
767
735
|
def components
|
768
|
-
@components ||=
|
769
|
-
|
770
|
-
get(:env),
|
771
|
-
Util::Component
|
772
|
-
|
773
|
-
worker: Util::Component.new(
|
774
|
-
get(:env),
|
775
|
-
get(:component) || get(:worker_component),
|
776
|
-
force_worker: true
|
777
|
-
)
|
778
|
-
}
|
736
|
+
@components ||=
|
737
|
+
{
|
738
|
+
web: Util::Component.new(get(:env), Util::Component::DEFAULT_NAME),
|
739
|
+
worker: Util::Component.new(get(:env), get(:component) || get(:worker_component), force_worker: true)
|
740
|
+
}
|
779
741
|
rescue ArgumentError => e
|
780
742
|
raise ConfigError, e.message
|
781
743
|
end
|
@@ -789,25 +751,20 @@ module Skylight
|
|
789
751
|
end
|
790
752
|
|
791
753
|
def as_json(*)
|
792
|
-
{
|
793
|
-
config: {
|
794
|
-
priority: @priority.merge(component.as_json),
|
795
|
-
values: @values
|
796
|
-
}
|
797
|
-
}
|
754
|
+
{ config: { priority: @priority.merge(component.as_json), values: @values } }
|
798
755
|
end
|
799
756
|
|
800
757
|
private
|
801
758
|
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
759
|
+
def check_nfs(path)
|
760
|
+
# Should work on most *nix, though not on OS X
|
761
|
+
`stat -f -L -c %T #{path} 2>&1`.strip == "nfs"
|
762
|
+
end
|
806
763
|
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
764
|
+
def reporting_env?
|
765
|
+
# true if env was explicitly set,
|
766
|
+
# or if we are auto-detecting via the opt-in SKYLIGHT_REPORT_RAILS_ENV=true
|
767
|
+
!!(get(:report_rails_env) || get(:env))
|
768
|
+
end
|
812
769
|
end
|
813
770
|
end
|