hoss-agent 1.0.6

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.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/Bug_report.md +40 -0
  3. data/.github/ISSUE_TEMPLATE/Feature_request.md +17 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +60 -0
  5. data/.gitignore +27 -0
  6. data/.rspec +2 -0
  7. data/Dockerfile +43 -0
  8. data/Gemfile +105 -0
  9. data/LICENSE +201 -0
  10. data/hoss-agent.gemspec +42 -0
  11. data/lib/hoss-agent.rb +210 -0
  12. data/lib/hoss.rb +21 -0
  13. data/lib/hoss/agent.rb +235 -0
  14. data/lib/hoss/central_config.rb +184 -0
  15. data/lib/hoss/central_config/cache_control.rb +51 -0
  16. data/lib/hoss/child_durations.rb +64 -0
  17. data/lib/hoss/config.rb +313 -0
  18. data/lib/hoss/config/bytes.rb +42 -0
  19. data/lib/hoss/config/duration.rb +40 -0
  20. data/lib/hoss/config/options.rb +154 -0
  21. data/lib/hoss/config/regexp_list.rb +30 -0
  22. data/lib/hoss/config/wildcard_pattern_list.rb +54 -0
  23. data/lib/hoss/context.rb +64 -0
  24. data/lib/hoss/context/request.rb +28 -0
  25. data/lib/hoss/context/request/socket.rb +36 -0
  26. data/lib/hoss/context/request/url.rb +59 -0
  27. data/lib/hoss/context/response.rb +47 -0
  28. data/lib/hoss/context/user.rb +59 -0
  29. data/lib/hoss/context_builder.rb +112 -0
  30. data/lib/hoss/deprecations.rb +39 -0
  31. data/lib/hoss/error.rb +49 -0
  32. data/lib/hoss/error/exception.rb +70 -0
  33. data/lib/hoss/error/log.rb +41 -0
  34. data/lib/hoss/error_builder.rb +90 -0
  35. data/lib/hoss/event.rb +131 -0
  36. data/lib/hoss/instrumenter.rb +107 -0
  37. data/lib/hoss/internal_error.rb +23 -0
  38. data/lib/hoss/logging.rb +70 -0
  39. data/lib/hoss/metadata.rb +36 -0
  40. data/lib/hoss/metadata/process_info.rb +35 -0
  41. data/lib/hoss/metadata/service_info.rb +76 -0
  42. data/lib/hoss/metadata/system_info.rb +47 -0
  43. data/lib/hoss/metadata/system_info/container_info.rb +136 -0
  44. data/lib/hoss/naively_hashable.rb +38 -0
  45. data/lib/hoss/rails.rb +68 -0
  46. data/lib/hoss/railtie.rb +42 -0
  47. data/lib/hoss/report.rb +9 -0
  48. data/lib/hoss/sinatra.rb +53 -0
  49. data/lib/hoss/spies.rb +104 -0
  50. data/lib/hoss/spies/faraday.rb +102 -0
  51. data/lib/hoss/spies/http.rb +81 -0
  52. data/lib/hoss/spies/net_http.rb +97 -0
  53. data/lib/hoss/stacktrace.rb +33 -0
  54. data/lib/hoss/stacktrace/frame.rb +66 -0
  55. data/lib/hoss/stacktrace_builder.rb +124 -0
  56. data/lib/hoss/transport/base.rb +191 -0
  57. data/lib/hoss/transport/connection.rb +55 -0
  58. data/lib/hoss/transport/connection/http.rb +139 -0
  59. data/lib/hoss/transport/connection/proxy_pipe.rb +94 -0
  60. data/lib/hoss/transport/filters.rb +60 -0
  61. data/lib/hoss/transport/filters/hash_sanitizer.rb +77 -0
  62. data/lib/hoss/transport/filters/secrets_filter.rb +48 -0
  63. data/lib/hoss/transport/headers.rb +74 -0
  64. data/lib/hoss/transport/serializers.rb +113 -0
  65. data/lib/hoss/transport/serializers/context_serializer.rb +112 -0
  66. data/lib/hoss/transport/serializers/error_serializer.rb +92 -0
  67. data/lib/hoss/transport/serializers/event_serializer.rb +73 -0
  68. data/lib/hoss/transport/serializers/metadata_serializer.rb +92 -0
  69. data/lib/hoss/transport/serializers/report_serializer.rb +33 -0
  70. data/lib/hoss/transport/user_agent.rb +48 -0
  71. data/lib/hoss/transport/worker.rb +326 -0
  72. data/lib/hoss/util.rb +54 -0
  73. data/lib/hoss/util/inflector.rb +110 -0
  74. data/lib/hoss/util/lru_cache.rb +65 -0
  75. data/lib/hoss/util/throttle.rb +52 -0
  76. data/lib/hoss/version.rb +22 -0
  77. 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
@@ -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