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