skylight 3.1.4 → 5.3.4
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 +465 -294
- data/CLA.md +1 -1
- data/CONTRIBUTING.md +11 -3
- data/ERRORS.md +3 -0
- data/LICENSE.md +8 -18
- data/README.md +1 -2
- data/bin/skylight +1 -1
- data/ext/extconf.rb +118 -122
- data/ext/libskylight.yml +8 -6
- data/ext/skylight_native.c +56 -100
- data/lib/skylight/api.rb +41 -27
- data/lib/skylight/cli/doctor.rb +68 -70
- data/lib/skylight/cli/helpers.rb +3 -5
- data/lib/skylight/cli/merger.rb +99 -92
- data/lib/skylight/cli.rb +40 -43
- data/lib/skylight/config.rb +656 -201
- data/lib/skylight/data/cacert.pem +730 -1023
- data/lib/skylight/deprecation.rb +17 -0
- data/lib/skylight/errors.rb +34 -16
- 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 +82 -39
- data/lib/skylight/instrumenter.rb +339 -9
- data/lib/skylight/middleware.rb +147 -1
- data/lib/skylight/native.rb +71 -23
- data/lib/skylight/native_ext_fetcher.rb +39 -47
- 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 +45 -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 +169 -0
- data/lib/skylight/probes/mongoid.rb +6 -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 +68 -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 +172 -0
- data/lib/skylight/railtie.rb +172 -15
- data/lib/skylight/sidekiq.rb +47 -0
- data/lib/skylight/sinatra.rb +2 -2
- data/lib/skylight/subscriber.rb +130 -0
- data/lib/skylight/test.rb +147 -0
- data/lib/skylight/trace.rb +331 -15
- data/lib/skylight/user_config.rb +60 -0
- data/lib/skylight/util/allocation_free.rb +26 -0
- data/lib/skylight/util/clock.rb +57 -0
- data/lib/skylight/util/component.rb +47 -9
- data/lib/skylight/util/deploy.rb +24 -40
- data/lib/skylight/util/gzip.rb +20 -0
- data/lib/skylight/util/hostname.rb +4 -4
- data/lib/skylight/util/http.rb +62 -71
- 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 +74 -0
- data/lib/skylight/util/proxy.rb +13 -0
- data/lib/skylight/util/ssl.rb +4 -28
- 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 +213 -24
- metadata +171 -53
|
@@ -1,33 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
1
5
|
module Skylight
|
|
2
6
|
module Util
|
|
3
7
|
class Component
|
|
4
|
-
|
|
5
8
|
attr_accessor :environment, :name
|
|
6
9
|
|
|
7
|
-
NAME_FORMAT = /\A[a-
|
|
8
|
-
DEFAULT_NAME =
|
|
9
|
-
|
|
10
|
+
NAME_FORMAT = /\A[a-zA-Z0-9_-]+\z/.freeze
|
|
11
|
+
DEFAULT_NAME = "web"
|
|
12
|
+
WORKER_NAME = "worker"
|
|
13
|
+
DEFAULT_ENVIRONMENT = "production"
|
|
10
14
|
|
|
11
|
-
def initialize(environment, name)
|
|
15
|
+
def initialize(environment, name, force_worker: false)
|
|
12
16
|
@environment = environment || DEFAULT_ENVIRONMENT
|
|
13
|
-
@name
|
|
17
|
+
@name = resolve_name(name, force_worker)
|
|
14
18
|
|
|
15
19
|
raise ArgumentError, "environment can't be blank" if @environment.empty?
|
|
16
|
-
|
|
17
|
-
validate_string!(@
|
|
20
|
+
|
|
21
|
+
validate_string!(@environment, "environment")
|
|
22
|
+
validate_string!(@name, "name")
|
|
18
23
|
end
|
|
19
24
|
|
|
20
25
|
def to_s
|
|
21
26
|
"#{name}:#{environment}"
|
|
22
27
|
end
|
|
23
28
|
|
|
29
|
+
def to_encoded_s
|
|
30
|
+
@to_encoded_s ||= URI.encode_www_form_component(to_s)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def web?
|
|
34
|
+
name == DEFAULT_NAME
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def worker?
|
|
38
|
+
!web?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# keys here should match those from the main config
|
|
42
|
+
def as_json(*)
|
|
43
|
+
{ component: name, env: environment }
|
|
44
|
+
end
|
|
45
|
+
|
|
24
46
|
private
|
|
25
47
|
|
|
48
|
+
def program_name
|
|
49
|
+
$PROGRAM_NAME
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def argv
|
|
53
|
+
ARGV
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def resolve_name(given_name, force_worker)
|
|
57
|
+
# don't allow workers to be called 'web'
|
|
58
|
+
return WORKER_NAME if force_worker && (given_name.nil? || given_name == DEFAULT_NAME)
|
|
59
|
+
return DEFAULT_NAME if given_name.nil?
|
|
60
|
+
|
|
61
|
+
given_name
|
|
62
|
+
end
|
|
63
|
+
|
|
26
64
|
def validate_string!(string, kind)
|
|
27
65
|
return true if string =~ NAME_FORMAT
|
|
66
|
+
|
|
28
67
|
raise ArgumentError, "#{kind} can only contain lowercase letters, numbers, and dashes"
|
|
29
68
|
end
|
|
30
69
|
end
|
|
31
70
|
end
|
|
32
71
|
end
|
|
33
|
-
|
data/lib/skylight/util/deploy.rb
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require "json"
|
|
2
|
+
require "skylight/util/logging"
|
|
3
3
|
|
|
4
4
|
module Skylight
|
|
5
5
|
module Util
|
|
6
|
-
|
|
7
6
|
module Deploy
|
|
8
|
-
|
|
9
7
|
def self.build(config)
|
|
10
8
|
DEPLOY_TYPES.each do |type|
|
|
11
9
|
deploy = type.new(config)
|
|
@@ -15,9 +13,7 @@ module Skylight
|
|
|
15
13
|
end
|
|
16
14
|
|
|
17
15
|
class EmptyDeploy
|
|
18
|
-
|
|
19
|
-
attr_reader :config
|
|
20
|
-
attr_reader :timestamp
|
|
16
|
+
attr_reader :config, :timestamp
|
|
21
17
|
|
|
22
18
|
def initialize(config)
|
|
23
19
|
@config = config
|
|
@@ -38,75 +34,66 @@ module Skylight
|
|
|
38
34
|
|
|
39
35
|
def to_query_hash
|
|
40
36
|
hash = {
|
|
41
|
-
timestamp:
|
|
42
|
-
deploy_id:
|
|
37
|
+
timestamp: timestamp,
|
|
38
|
+
deploy_id: id.to_s[0..100] # Keep this sane
|
|
43
39
|
}
|
|
44
40
|
hash[:git_sha] = git_sha.to_s[0..40] if git_sha # A valid SHA will never exceed 40
|
|
45
41
|
hash[:description] = description[0..255] if description # Avoid massive descriptions
|
|
46
42
|
hash
|
|
47
43
|
end
|
|
48
|
-
|
|
49
44
|
end
|
|
50
45
|
|
|
51
46
|
class DefaultDeploy < EmptyDeploy
|
|
52
|
-
include
|
|
47
|
+
include Util::Logging
|
|
53
48
|
|
|
54
49
|
def initialize(*)
|
|
55
50
|
super
|
|
56
|
-
if description && !id
|
|
57
|
-
warn "The configured deploy will be ignored as an id or git_sha must be provided."
|
|
58
|
-
end
|
|
51
|
+
warn "The configured deploy will be ignored as an id or git_sha must be provided." if description && !id
|
|
59
52
|
end
|
|
60
53
|
|
|
61
54
|
def id
|
|
62
|
-
config.get(:
|
|
55
|
+
config.get(:"deploy.id") || git_sha
|
|
63
56
|
end
|
|
64
57
|
|
|
65
58
|
def git_sha
|
|
66
|
-
config.get(:
|
|
59
|
+
config.get(:"deploy.git_sha")
|
|
67
60
|
end
|
|
68
61
|
|
|
69
62
|
def description
|
|
70
|
-
config.get(:
|
|
63
|
+
config.get(:"deploy.description")
|
|
71
64
|
end
|
|
72
|
-
|
|
73
65
|
end
|
|
74
66
|
|
|
75
67
|
class HerokuDeploy < EmptyDeploy
|
|
76
|
-
|
|
77
68
|
def initialize(*)
|
|
78
69
|
super
|
|
79
70
|
@info = get_info
|
|
80
71
|
end
|
|
81
72
|
|
|
82
73
|
def id
|
|
83
|
-
@info ? @info[
|
|
74
|
+
@info ? @info["id"] : nil
|
|
84
75
|
end
|
|
85
76
|
|
|
86
77
|
def git_sha
|
|
87
|
-
@info ? @info[
|
|
78
|
+
@info ? @info["commit"] : nil
|
|
88
79
|
end
|
|
89
80
|
|
|
90
81
|
def description
|
|
91
|
-
@info ? @info[
|
|
82
|
+
@info ? @info["description"] : nil
|
|
92
83
|
end
|
|
93
84
|
|
|
94
85
|
private
|
|
95
86
|
|
|
96
|
-
|
|
97
|
-
|
|
87
|
+
def get_info
|
|
88
|
+
info_path = config[:"heroku.dyno_info_path"]
|
|
98
89
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
info['release']
|
|
102
|
-
end
|
|
103
|
-
end
|
|
90
|
+
if File.exist?(info_path) && (info = JSON.parse(File.read(info_path)))
|
|
91
|
+
info["release"]
|
|
104
92
|
end
|
|
105
|
-
|
|
93
|
+
end
|
|
106
94
|
end
|
|
107
95
|
|
|
108
96
|
class GitDeploy < EmptyDeploy
|
|
109
|
-
|
|
110
97
|
attr_reader :git_sha, :description
|
|
111
98
|
|
|
112
99
|
def initialize(*)
|
|
@@ -116,18 +103,15 @@ module Skylight
|
|
|
116
103
|
|
|
117
104
|
private
|
|
118
105
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
end
|
|
106
|
+
def get_info
|
|
107
|
+
Dir.chdir(config.root) do
|
|
108
|
+
info = `git log -1 --pretty="%H %s" 2>&1`
|
|
109
|
+
info.split(" ", 2).map(&:strip) if $CHILD_STATUS.success?
|
|
124
110
|
end
|
|
125
|
-
|
|
111
|
+
end
|
|
126
112
|
end
|
|
127
113
|
|
|
128
|
-
DEPLOY_TYPES = [DefaultDeploy, HerokuDeploy, GitDeploy]
|
|
129
|
-
|
|
114
|
+
DEPLOY_TYPES = [DefaultDeploy, HerokuDeploy, GitDeploy].freeze
|
|
130
115
|
end
|
|
131
|
-
|
|
132
116
|
end
|
|
133
117
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require "zlib"
|
|
2
|
+
|
|
3
|
+
module Skylight
|
|
4
|
+
module Util
|
|
5
|
+
# Provides Gzip compressing support
|
|
6
|
+
module Gzip
|
|
7
|
+
# Compress a string with Gzip
|
|
8
|
+
#
|
|
9
|
+
# @param str [String] uncompressed string
|
|
10
|
+
# @return [String] compressed string
|
|
11
|
+
def self.compress(str)
|
|
12
|
+
output = StringIO.new
|
|
13
|
+
gz = Zlib::GzipWriter.new(output)
|
|
14
|
+
gz.write(str)
|
|
15
|
+
gz.close
|
|
16
|
+
output.string
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require "socket"
|
|
2
|
+
require "securerandom"
|
|
3
3
|
|
|
4
4
|
module Skylight
|
|
5
5
|
module Util
|
|
6
6
|
module Hostname
|
|
7
7
|
def self.default_hostname
|
|
8
|
-
if hostname = Socket.gethostname
|
|
8
|
+
if (hostname = Socket.gethostname)
|
|
9
9
|
hostname.strip!
|
|
10
|
-
hostname = nil if hostname ==
|
|
10
|
+
hostname = nil if hostname == ""
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
hostname || "gen-#{SecureRandom.uuid}"
|
data/lib/skylight/util/http.rb
CHANGED
|
@@ -1,70 +1,68 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
1
|
+
require "uri"
|
|
2
|
+
require "json"
|
|
3
|
+
require "openssl"
|
|
4
|
+
require "net/http"
|
|
5
|
+
require "net/https"
|
|
6
|
+
require "skylight/util/gzip"
|
|
7
|
+
require "skylight/util/ssl"
|
|
8
8
|
|
|
9
9
|
module Skylight
|
|
10
10
|
module Util
|
|
11
11
|
class HTTP
|
|
12
|
-
CONTENT_ENCODING =
|
|
13
|
-
CONTENT_LENGTH
|
|
14
|
-
CONTENT_TYPE
|
|
15
|
-
ACCEPT
|
|
16
|
-
X_VERSION_HDR
|
|
17
|
-
APPLICATION_JSON =
|
|
18
|
-
AUTHORIZATION
|
|
19
|
-
DEFLATE
|
|
20
|
-
GZIP
|
|
21
|
-
|
|
22
|
-
include
|
|
12
|
+
CONTENT_ENCODING = "content-encoding".freeze
|
|
13
|
+
CONTENT_LENGTH = "content-length".freeze
|
|
14
|
+
CONTENT_TYPE = "content-type".freeze
|
|
15
|
+
ACCEPT = "Accept".freeze
|
|
16
|
+
X_VERSION_HDR = "x-skylight-agent-version".freeze
|
|
17
|
+
APPLICATION_JSON = "application/json".freeze
|
|
18
|
+
AUTHORIZATION = "authorization".freeze
|
|
19
|
+
DEFLATE = "deflate".freeze
|
|
20
|
+
GZIP = "gzip".freeze
|
|
21
|
+
|
|
22
|
+
include Logging
|
|
23
23
|
|
|
24
24
|
attr_accessor :authentication
|
|
25
25
|
attr_reader :host, :port, :config
|
|
26
26
|
|
|
27
|
-
READ_EXCEPTIONS = [Timeout::Error, EOFError]
|
|
28
|
-
# This doesn't exist on Ruby 1.9.3
|
|
29
|
-
READ_EXCEPTIONS << Net::ReadTimeout if defined?(Net::ReadTimeout)
|
|
30
|
-
READ_EXCEPTIONS.freeze
|
|
27
|
+
READ_EXCEPTIONS = [Timeout::Error, EOFError, Net::ReadTimeout].freeze
|
|
31
28
|
|
|
32
29
|
class StartError < StandardError
|
|
33
30
|
attr_reader :original
|
|
34
31
|
|
|
35
|
-
def initialize(
|
|
36
|
-
@original =
|
|
37
|
-
super
|
|
32
|
+
def initialize(error)
|
|
33
|
+
@original = error
|
|
34
|
+
super error.inspect
|
|
38
35
|
end
|
|
39
|
-
|
|
40
36
|
end
|
|
41
37
|
|
|
42
|
-
class ReadResponseError < StandardError
|
|
38
|
+
class ReadResponseError < StandardError
|
|
39
|
+
end
|
|
43
40
|
|
|
44
41
|
def initialize(config, service = :auth, opts = {})
|
|
45
42
|
@config = config
|
|
46
43
|
|
|
47
|
-
unless url = config["#{service}_url"]
|
|
44
|
+
unless (url = config["#{service}_url"])
|
|
48
45
|
raise ArgumentError, "no URL specified for #{service}"
|
|
49
46
|
end
|
|
50
47
|
|
|
51
48
|
url = URI.parse(url)
|
|
52
49
|
|
|
53
|
-
@ssl
|
|
50
|
+
@ssl = url.scheme == "https"
|
|
54
51
|
@host = url.host
|
|
55
52
|
@port = url.port
|
|
56
53
|
|
|
57
|
-
if proxy_url = config[:proxy_url]
|
|
54
|
+
if (proxy_url = config[:proxy_url])
|
|
58
55
|
proxy_url = URI.parse(proxy_url)
|
|
59
|
-
@proxy_addr
|
|
60
|
-
@
|
|
56
|
+
@proxy_addr = proxy_url.host
|
|
57
|
+
@proxy_port = proxy_url.port
|
|
58
|
+
@proxy_user, @proxy_pass = (proxy_url.userinfo || "").split(/:/)
|
|
61
59
|
end
|
|
62
60
|
|
|
63
61
|
@open_timeout = get_timeout(:connect, config, service, opts)
|
|
64
62
|
@read_timeout = get_timeout(:read, config, service, opts)
|
|
65
63
|
|
|
66
64
|
@deflate = config["#{service}_http_deflate"]
|
|
67
|
-
@authentication = config[:
|
|
65
|
+
@authentication = config[:authentication]
|
|
68
66
|
end
|
|
69
67
|
|
|
70
68
|
def get(endpoint, hdrs = {})
|
|
@@ -82,25 +80,22 @@ module Skylight
|
|
|
82
80
|
execute(request, body)
|
|
83
81
|
end
|
|
84
82
|
|
|
85
|
-
|
|
83
|
+
private
|
|
86
84
|
|
|
87
85
|
def get_timeout(type, config, service, opts)
|
|
88
|
-
config.duration_ms("#{service}_http_#{type}_timeout") ||
|
|
89
|
-
opts[:timeout] || 15
|
|
86
|
+
config.duration_ms("#{service}_http_#{type}_timeout") || opts[:timeout] || 15
|
|
90
87
|
end
|
|
91
88
|
|
|
92
|
-
def build_request(type, endpoint, hdrs, length=nil)
|
|
89
|
+
def build_request(type, endpoint, hdrs, length = nil)
|
|
93
90
|
headers = {}
|
|
94
91
|
|
|
95
|
-
headers[CONTENT_LENGTH]
|
|
96
|
-
headers[AUTHORIZATION]
|
|
97
|
-
headers[ACCEPT]
|
|
98
|
-
headers[X_VERSION_HDR]
|
|
92
|
+
headers[CONTENT_LENGTH] = length.to_s if length
|
|
93
|
+
headers[AUTHORIZATION] = authentication if authentication
|
|
94
|
+
headers[ACCEPT] = APPLICATION_JSON
|
|
95
|
+
headers[X_VERSION_HDR] = VERSION
|
|
99
96
|
headers[CONTENT_ENCODING] = GZIP if length && @deflate
|
|
100
97
|
|
|
101
|
-
hdrs.each
|
|
102
|
-
headers[k] = v
|
|
103
|
-
end
|
|
98
|
+
hdrs.each { |k, v| headers[k] = v }
|
|
104
99
|
|
|
105
100
|
type.new(endpoint, headers)
|
|
106
101
|
end
|
|
@@ -108,7 +103,7 @@ module Skylight
|
|
|
108
103
|
def do_request(http, req)
|
|
109
104
|
begin
|
|
110
105
|
client = http.start
|
|
111
|
-
rescue => e
|
|
106
|
+
rescue StandardError => e
|
|
112
107
|
# TODO: Retry here
|
|
113
108
|
raise StartError, e
|
|
114
109
|
end
|
|
@@ -121,20 +116,24 @@ module Skylight
|
|
|
121
116
|
|
|
122
117
|
yield res
|
|
123
118
|
ensure
|
|
124
|
-
client
|
|
119
|
+
client&.finish
|
|
125
120
|
end
|
|
126
121
|
|
|
127
|
-
def execute(req, body=nil)
|
|
128
|
-
t
|
|
129
|
-
|
|
122
|
+
def execute(req, body = nil)
|
|
123
|
+
t do
|
|
124
|
+
fmt "executing HTTP request; host=%s; port=%s; path=%s, body=%s",
|
|
125
|
+
@host,
|
|
126
|
+
@port,
|
|
127
|
+
req.path,
|
|
128
|
+
body && body.bytesize
|
|
129
|
+
end
|
|
130
130
|
|
|
131
131
|
if body
|
|
132
132
|
body = Gzip.compress(body) if @deflate
|
|
133
133
|
req.body = body
|
|
134
134
|
end
|
|
135
135
|
|
|
136
|
-
http = Net::HTTP.new(@host, @port,
|
|
137
|
-
@proxy_addr, @proxy_port, @proxy_user, @proxy_pass)
|
|
136
|
+
http = Net::HTTP.new(@host, @port, @proxy_addr, @proxy_port, @proxy_user, @proxy_pass)
|
|
138
137
|
|
|
139
138
|
http.open_timeout = @open_timeout
|
|
140
139
|
http.read_timeout = @read_timeout
|
|
@@ -142,9 +141,7 @@ module Skylight
|
|
|
142
141
|
if @ssl
|
|
143
142
|
http.use_ssl = true
|
|
144
143
|
|
|
145
|
-
unless SSL.ca_cert_file?
|
|
146
|
-
http.ca_file = SSL.ca_cert_file_or_default
|
|
147
|
-
end
|
|
144
|
+
http.ca_file = SSL.ca_cert_file_or_default unless SSL.ca_cert_file?
|
|
148
145
|
|
|
149
146
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
150
147
|
end
|
|
@@ -167,7 +164,7 @@ module Skylight
|
|
|
167
164
|
attr_reader :status, :headers, :body, :exception
|
|
168
165
|
|
|
169
166
|
def initialize(status, headers, body)
|
|
170
|
-
@status
|
|
167
|
+
@status = status
|
|
171
168
|
@headers = headers
|
|
172
169
|
|
|
173
170
|
if (headers[CONTENT_TYPE] || "").include?(APPLICATION_JSON)
|
|
@@ -190,16 +187,10 @@ module Skylight
|
|
|
190
187
|
end
|
|
191
188
|
|
|
192
189
|
def get(key)
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
res = body
|
|
196
|
-
key.split('.').each do |part|
|
|
197
|
-
return unless res = res[part]
|
|
198
|
-
end
|
|
199
|
-
res
|
|
190
|
+
body.dig(*key.split(".")) if body.is_a?(Hash)
|
|
200
191
|
end
|
|
201
192
|
|
|
202
|
-
def respond_to_missing?(name, include_all=false)
|
|
193
|
+
def respond_to_missing?(name, include_all = false)
|
|
203
194
|
super || body.respond_to?(name, include_all)
|
|
204
195
|
end
|
|
205
196
|
|
|
@@ -212,16 +203,16 @@ module Skylight
|
|
|
212
203
|
end
|
|
213
204
|
end
|
|
214
205
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
206
|
+
ErrorResponse =
|
|
207
|
+
Struct.new(:request, :exception) do
|
|
208
|
+
def status
|
|
209
|
+
nil
|
|
210
|
+
end
|
|
219
211
|
|
|
220
|
-
|
|
221
|
-
|
|
212
|
+
def success?
|
|
213
|
+
false
|
|
214
|
+
end
|
|
222
215
|
end
|
|
223
|
-
end
|
|
224
|
-
|
|
225
216
|
end
|
|
226
217
|
end
|
|
227
218
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Skylight
|
|
2
|
+
module Util
|
|
3
|
+
module InstrumenterMethod
|
|
4
|
+
def instrumenter_method(name, block: false)
|
|
5
|
+
if block
|
|
6
|
+
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
7
|
+
def #{name}(*args) # def mute(*args)
|
|
8
|
+
unless instrumenter # unless instrumenter
|
|
9
|
+
return yield if block_given? # return yield if block_given?
|
|
10
|
+
return # return
|
|
11
|
+
end # end
|
|
12
|
+
#
|
|
13
|
+
instrumenter.#{name}(*args) { yield } # instrumenter.mute(*args) { yield }
|
|
14
|
+
end # end
|
|
15
|
+
RUBY
|
|
16
|
+
else
|
|
17
|
+
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
18
|
+
def #{name}(*args) # def config(*args)
|
|
19
|
+
instrumenter&.#{name}(*args) # instrumenter&.config(*args)
|
|
20
|
+
end # end
|
|
21
|
+
RUBY
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
require "logger"
|
|
2
|
+
|
|
3
|
+
module Skylight
|
|
4
|
+
module Util
|
|
5
|
+
# Log both to the specified logger and STDOUT
|
|
6
|
+
class AlertLogger
|
|
7
|
+
def initialize(logger)
|
|
8
|
+
@logger = logger
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def write(*args)
|
|
12
|
+
$stderr.write(*args)
|
|
13
|
+
|
|
14
|
+
# Try to avoid writing to STDOUT/STDERR twice
|
|
15
|
+
logger_logdev = @logger.instance_variable_get(:@logdev)
|
|
16
|
+
logger_out = logger_logdev.respond_to?(:dev) ? logger_logdev.dev : nil
|
|
17
|
+
@logger.<<(*args) if logger_out != $stdout && logger_out != $stderr
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def close; end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module Logging
|
|
24
|
+
def log_context
|
|
25
|
+
{}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def trace?
|
|
29
|
+
!!ENV[-"SKYLIGHT_ENABLE_TRACE_LOGS"]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def raise_on_error?
|
|
33
|
+
!!ENV[-"SKYLIGHT_RAISE_ON_ERROR"]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Logs if tracing
|
|
37
|
+
#
|
|
38
|
+
# @param (see #debug)
|
|
39
|
+
#
|
|
40
|
+
# See {trace?}.
|
|
41
|
+
def trace(msg, *args)
|
|
42
|
+
return unless trace?
|
|
43
|
+
|
|
44
|
+
log :debug, msg, *args
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Evaluates and logs the result of the block if tracing
|
|
48
|
+
#
|
|
49
|
+
# @yield block to be evaluted
|
|
50
|
+
# @yieldreturn arguments for {#debug}
|
|
51
|
+
#
|
|
52
|
+
# See {trace?}.
|
|
53
|
+
def t
|
|
54
|
+
return unless trace?
|
|
55
|
+
|
|
56
|
+
log :debug, yield
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @param msg (see #log)
|
|
60
|
+
# @param args (see #log)
|
|
61
|
+
def debug(msg, *args)
|
|
62
|
+
log :debug, msg, *args
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @param msg (see #log)
|
|
66
|
+
# @param args (see #log)
|
|
67
|
+
def info(msg, *args)
|
|
68
|
+
log :info, msg, *args
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @param msg (see #log)
|
|
72
|
+
# @param args (see #log)
|
|
73
|
+
def warn(msg, *args)
|
|
74
|
+
log :warn, msg, *args
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# @param msg (see #log)
|
|
78
|
+
# @param args (see #log)
|
|
79
|
+
def error(msg, *args)
|
|
80
|
+
log :error, msg, *args
|
|
81
|
+
raise format(msg, *args) if raise_on_error?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
alias log_trace trace
|
|
85
|
+
alias log_debug debug
|
|
86
|
+
alias log_info info
|
|
87
|
+
alias log_warn warn
|
|
88
|
+
alias log_error error
|
|
89
|
+
|
|
90
|
+
# Alias for `Kernel#sprintf`
|
|
91
|
+
# @return [String]
|
|
92
|
+
def fmt(*args)
|
|
93
|
+
sprintf(*args)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def config_for_logging
|
|
97
|
+
if respond_to?(:config)
|
|
98
|
+
config
|
|
99
|
+
elsif is_a?(Skylight::Config)
|
|
100
|
+
self
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# @param level [String,Symbol] the method on `logger` to use for logging
|
|
105
|
+
# @param msg [String] the message to log
|
|
106
|
+
# @param args [Array] values for `Kernel#sprintf` on `msg`
|
|
107
|
+
def log(level, msg, *args)
|
|
108
|
+
c = config_for_logging
|
|
109
|
+
logger = c ? c.logger : nil
|
|
110
|
+
|
|
111
|
+
msg = log_context.map { |(k, v)| "#{k}=#{v}; " }.join << msg
|
|
112
|
+
|
|
113
|
+
if logger
|
|
114
|
+
if logger.respond_to?(level)
|
|
115
|
+
if args.empty?
|
|
116
|
+
logger.send level, msg
|
|
117
|
+
else
|
|
118
|
+
logger.send level, format(msg, *args)
|
|
119
|
+
end
|
|
120
|
+
return # rubocop:disable Style/RedundantReturn
|
|
121
|
+
else
|
|
122
|
+
Kernel.warn "Invalid logger"
|
|
123
|
+
end
|
|
124
|
+
# Fallback to stderr for warn and error levels
|
|
125
|
+
elsif %i[warn error].include?(level)
|
|
126
|
+
$stderr.puts format("[SKYLIGHT] #{msg}", *args)
|
|
127
|
+
end
|
|
128
|
+
rescue Exception => e
|
|
129
|
+
if trace?
|
|
130
|
+
puts "[ERROR] #{e.message}"
|
|
131
|
+
puts e.backtrace
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|