hoss-agent 1.0.11
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/.github/ISSUE_TEMPLATE/Bug_report.md +40 -0
- data/.github/ISSUE_TEMPLATE/Feature_request.md +17 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +60 -0
- data/.gitignore +27 -0
- data/.rspec +2 -0
- data/Dockerfile +43 -0
- data/Gemfile +105 -0
- data/LICENSE +201 -0
- data/hoss-agent.gemspec +42 -0
- data/lib/hoss-agent.rb +210 -0
- data/lib/hoss.rb +21 -0
- data/lib/hoss/agent.rb +235 -0
- data/lib/hoss/central_config.rb +184 -0
- data/lib/hoss/central_config/cache_control.rb +51 -0
- data/lib/hoss/child_durations.rb +64 -0
- data/lib/hoss/config.rb +315 -0
- data/lib/hoss/config/bytes.rb +42 -0
- data/lib/hoss/config/duration.rb +40 -0
- data/lib/hoss/config/options.rb +154 -0
- data/lib/hoss/config/regexp_list.rb +30 -0
- data/lib/hoss/config/wildcard_pattern_list.rb +54 -0
- data/lib/hoss/context.rb +64 -0
- data/lib/hoss/context/request.rb +28 -0
- data/lib/hoss/context/request/socket.rb +36 -0
- data/lib/hoss/context/request/url.rb +59 -0
- data/lib/hoss/context/response.rb +47 -0
- data/lib/hoss/context/user.rb +59 -0
- data/lib/hoss/context_builder.rb +112 -0
- data/lib/hoss/deprecations.rb +39 -0
- data/lib/hoss/error.rb +49 -0
- data/lib/hoss/error/exception.rb +70 -0
- data/lib/hoss/error/log.rb +41 -0
- data/lib/hoss/error_builder.rb +90 -0
- data/lib/hoss/event.rb +131 -0
- data/lib/hoss/instrumenter.rb +107 -0
- data/lib/hoss/internal_error.rb +23 -0
- data/lib/hoss/logging.rb +70 -0
- data/lib/hoss/metadata.rb +36 -0
- data/lib/hoss/metadata/process_info.rb +35 -0
- data/lib/hoss/metadata/service_info.rb +76 -0
- data/lib/hoss/metadata/system_info.rb +47 -0
- data/lib/hoss/metadata/system_info/container_info.rb +136 -0
- data/lib/hoss/naively_hashable.rb +38 -0
- data/lib/hoss/rails.rb +68 -0
- data/lib/hoss/railtie.rb +42 -0
- data/lib/hoss/report.rb +9 -0
- data/lib/hoss/sinatra.rb +53 -0
- data/lib/hoss/spies.rb +104 -0
- data/lib/hoss/spies/faraday.rb +117 -0
- data/lib/hoss/spies/http.rb +93 -0
- data/lib/hoss/spies/net_http.rb +113 -0
- data/lib/hoss/stacktrace.rb +33 -0
- data/lib/hoss/stacktrace/frame.rb +66 -0
- data/lib/hoss/stacktrace_builder.rb +124 -0
- data/lib/hoss/transport/base.rb +191 -0
- data/lib/hoss/transport/connection.rb +55 -0
- data/lib/hoss/transport/connection/http.rb +139 -0
- data/lib/hoss/transport/connection/proxy_pipe.rb +94 -0
- data/lib/hoss/transport/filters.rb +60 -0
- data/lib/hoss/transport/filters/hash_sanitizer.rb +77 -0
- data/lib/hoss/transport/filters/secrets_filter.rb +48 -0
- data/lib/hoss/transport/headers.rb +74 -0
- data/lib/hoss/transport/serializers.rb +113 -0
- data/lib/hoss/transport/serializers/context_serializer.rb +112 -0
- data/lib/hoss/transport/serializers/error_serializer.rb +92 -0
- data/lib/hoss/transport/serializers/event_serializer.rb +73 -0
- data/lib/hoss/transport/serializers/metadata_serializer.rb +92 -0
- data/lib/hoss/transport/serializers/report_serializer.rb +33 -0
- data/lib/hoss/transport/user_agent.rb +48 -0
- data/lib/hoss/transport/worker.rb +330 -0
- data/lib/hoss/util.rb +54 -0
- data/lib/hoss/util/inflector.rb +110 -0
- data/lib/hoss/util/lru_cache.rb +65 -0
- data/lib/hoss/util/throttle.rb +52 -0
- data/lib/hoss/version.rb +22 -0
- metadata +147 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
module Hoss
|
21
|
+
class Config
|
22
|
+
# @api private
|
23
|
+
class Bytes
|
24
|
+
MULTIPLIERS = {
|
25
|
+
'kb' => 1024,
|
26
|
+
'mb' => 1024 * 1_000,
|
27
|
+
'gb' => 1024 * 100_000
|
28
|
+
}.freeze
|
29
|
+
REGEX = /^(\d+)(b|kb|mb|gb)?$/i.freeze
|
30
|
+
|
31
|
+
def initialize(default_unit: 'kb')
|
32
|
+
@default_unit = default_unit
|
33
|
+
end
|
34
|
+
|
35
|
+
def call(value)
|
36
|
+
_, amount, unit = REGEX.match(String(value)).to_a
|
37
|
+
unit ||= @default_unit
|
38
|
+
MULTIPLIERS.fetch(unit.downcase, 1) * amount.to_i
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
module Hoss
|
21
|
+
class Config
|
22
|
+
# @api private
|
23
|
+
class Duration
|
24
|
+
MULTIPLIERS = { 'ms' => 0.001, 'm' => 60 }.freeze
|
25
|
+
REGEX = /^(-)?(\d+)(m|ms|s)?$/i.freeze
|
26
|
+
|
27
|
+
def initialize(default_unit: 's')
|
28
|
+
@default_unit = default_unit
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(str)
|
32
|
+
_, negative, amount, unit = REGEX.match(String(str)).to_a
|
33
|
+
unit ||= @default_unit
|
34
|
+
seconds = MULTIPLIERS.fetch(unit.downcase, 1) * amount.to_i
|
35
|
+
seconds = 0 - seconds if negative
|
36
|
+
seconds
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
module Hoss
|
21
|
+
class Config
|
22
|
+
# @api private
|
23
|
+
module Options
|
24
|
+
# @api private
|
25
|
+
class Option
|
26
|
+
def initialize(
|
27
|
+
key,
|
28
|
+
value: nil,
|
29
|
+
type: :string,
|
30
|
+
default: nil,
|
31
|
+
converter: nil
|
32
|
+
)
|
33
|
+
@key = key
|
34
|
+
@type = type
|
35
|
+
@default = default
|
36
|
+
@converter = converter
|
37
|
+
|
38
|
+
set(value || default)
|
39
|
+
end
|
40
|
+
|
41
|
+
attr_reader :key, :value, :default, :type
|
42
|
+
|
43
|
+
def set(value)
|
44
|
+
@value = normalize(value)
|
45
|
+
end
|
46
|
+
|
47
|
+
def env_key
|
48
|
+
"HOSS_#{key.upcase}"
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
54
|
+
def normalize(val)
|
55
|
+
return if val.nil?
|
56
|
+
|
57
|
+
if @converter
|
58
|
+
return @converter.call(val)
|
59
|
+
end
|
60
|
+
|
61
|
+
case type
|
62
|
+
when :string then val.to_s
|
63
|
+
when :int then val.to_i
|
64
|
+
when :float then val.to_f
|
65
|
+
when :bool then normalize_bool(val)
|
66
|
+
when :list then normalize_list(val)
|
67
|
+
when :dict then normalize_dict(val)
|
68
|
+
when :url then normalize_url(val)
|
69
|
+
else
|
70
|
+
# raise "Unknown options type '#{type.inspect}'"
|
71
|
+
val
|
72
|
+
end
|
73
|
+
end
|
74
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
75
|
+
|
76
|
+
def normalize_bool(val)
|
77
|
+
return val unless val.is_a?(String)
|
78
|
+
!%w[0 false].include?(val.strip.downcase)
|
79
|
+
end
|
80
|
+
|
81
|
+
def normalize_list(val)
|
82
|
+
return Array(val) unless val.is_a?(String)
|
83
|
+
val.split(/[ ,]/)
|
84
|
+
end
|
85
|
+
|
86
|
+
def normalize_dict(val)
|
87
|
+
return val unless val.is_a?(String)
|
88
|
+
Hash[val.split(/[&,]/).map { |kv| kv.split('=') }]
|
89
|
+
end
|
90
|
+
|
91
|
+
def normalize_url(val)
|
92
|
+
val = val.to_s
|
93
|
+
val.end_with?('/') ? val.chomp('/') : val
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# @api private
|
98
|
+
module ClassMethods
|
99
|
+
def schema
|
100
|
+
@schema ||= {}
|
101
|
+
end
|
102
|
+
|
103
|
+
def option(key, **args)
|
104
|
+
schema[key] = args
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# @api private
|
109
|
+
module InstanceMethods
|
110
|
+
def load_schema
|
111
|
+
Hash[self.class.schema.map do |key, args|
|
112
|
+
[key, Option.new(key, **args)]
|
113
|
+
end]
|
114
|
+
end
|
115
|
+
|
116
|
+
def method_missing(name, *value)
|
117
|
+
name_str = name.to_s
|
118
|
+
|
119
|
+
if name_str.end_with?('=')
|
120
|
+
key = name_str[0...-1].to_sym
|
121
|
+
set(key, value.first)
|
122
|
+
|
123
|
+
elsif name_str.end_with?('?')
|
124
|
+
key = name_str[0...-1].to_sym
|
125
|
+
options.key?(key) ? options[key].value : super
|
126
|
+
|
127
|
+
elsif options.key?(name)
|
128
|
+
options.fetch(name).value
|
129
|
+
|
130
|
+
else
|
131
|
+
super
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def [](key)
|
136
|
+
options[key]
|
137
|
+
end
|
138
|
+
alias :get :[]
|
139
|
+
|
140
|
+
def set(key, value)
|
141
|
+
options.fetch(key.to_sym).set(value)
|
142
|
+
rescue KeyError
|
143
|
+
warn format("Unknown option '%s'", key)
|
144
|
+
nil
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.extended(kls)
|
149
|
+
kls.instance_eval { extend ClassMethods }
|
150
|
+
kls.class_eval { include InstanceMethods }
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
module Hoss
|
21
|
+
class Config
|
22
|
+
# @api private
|
23
|
+
class RegexpList
|
24
|
+
def call(value)
|
25
|
+
value = value.is_a?(String) ? value.split(',') : Array(value)
|
26
|
+
value.map(&Regexp.method(:new))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
module Hoss
|
21
|
+
class Config
|
22
|
+
# @api private
|
23
|
+
class WildcardPatternList
|
24
|
+
# @api private
|
25
|
+
class WildcardPattern
|
26
|
+
def initialize(str)
|
27
|
+
@pattern = convert(str)
|
28
|
+
end
|
29
|
+
|
30
|
+
def match?(other)
|
31
|
+
!!@pattern.match(other)
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :match :match?
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def convert(str)
|
39
|
+
parts =
|
40
|
+
str.chars.each_with_object([]) do |char, arr|
|
41
|
+
arr << (char == '*' ? '.*' : Regexp.escape(char))
|
42
|
+
end
|
43
|
+
|
44
|
+
Regexp.new('\A' + parts.join + '\Z', Regexp::IGNORECASE)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def call(value)
|
49
|
+
value = value.is_a?(String) ? value.split(',') : Array(value)
|
50
|
+
value.map(&WildcardPattern.method(:new))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/hoss/context.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
require 'hoss/context/request'
|
21
|
+
require 'hoss/context/request/socket'
|
22
|
+
require 'hoss/context/request/url'
|
23
|
+
require 'hoss/context/response'
|
24
|
+
require 'hoss/context/user'
|
25
|
+
|
26
|
+
module Hoss
|
27
|
+
# @api private
|
28
|
+
class Context
|
29
|
+
def initialize(custom: {}, labels: {}, user: nil, service: nil)
|
30
|
+
@custom = custom
|
31
|
+
@labels = labels
|
32
|
+
@user = user || User.new
|
33
|
+
@service = service
|
34
|
+
end
|
35
|
+
|
36
|
+
Service = Struct.new(:framework)
|
37
|
+
Framework = Struct.new(:name, :version)
|
38
|
+
|
39
|
+
attr_accessor :request
|
40
|
+
attr_accessor :response
|
41
|
+
attr_accessor :user
|
42
|
+
attr_reader :custom
|
43
|
+
attr_reader :labels
|
44
|
+
attr_reader :service
|
45
|
+
|
46
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
47
|
+
def empty?
|
48
|
+
return false if labels.any?
|
49
|
+
return false if custom.any?
|
50
|
+
return false if user.any?
|
51
|
+
return false if service
|
52
|
+
return false if request || response
|
53
|
+
|
54
|
+
true
|
55
|
+
end
|
56
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
57
|
+
|
58
|
+
def set_service(framework_name: nil, framework_version: nil)
|
59
|
+
@service = Service.new(
|
60
|
+
Framework.new(framework_name, framework_version)
|
61
|
+
)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
module Hoss
|
21
|
+
class Context
|
22
|
+
# @api private
|
23
|
+
class Request
|
24
|
+
attr_accessor :body, :cookies, :env, :headers, :http_version, :method,
|
25
|
+
:socket, :url
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
module Hoss
|
21
|
+
# @api private
|
22
|
+
class Context
|
23
|
+
# @api private
|
24
|
+
class Request
|
25
|
+
# @api private
|
26
|
+
class Socket
|
27
|
+
def initialize(req)
|
28
|
+
@remote_addr = req.env['REMOTE_ADDR']
|
29
|
+
@encrypted = req.scheme == 'https'
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :remote_addr, :encrypted
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|