hoss-agent 1.0.9

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 +315 -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 +106 -0
  51. data/lib/hoss/spies/http.rb +86 -0
  52. data/lib/hoss/spies/net_http.rb +101 -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 +330 -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,113 @@
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
+ module Transport
22
+ # @api private
23
+ module Serializers
24
+ # @api private
25
+ class UnrecognizedResource < InternalError; end
26
+
27
+ # @api private
28
+ class Serializer
29
+ def initialize(config)
30
+ @config = config
31
+ end
32
+
33
+ attr_reader :config
34
+
35
+ private
36
+
37
+ def ms(micros)
38
+ micros.to_f / 1_000
39
+ end
40
+
41
+ def keyword_field(value)
42
+ Util.truncate(value)
43
+ end
44
+
45
+ def keyword_object(hash)
46
+ return unless hash
47
+
48
+ hash.tap do |h|
49
+ h.each { |k, v| hash[k] = keyword_field(v) }
50
+ end
51
+ end
52
+
53
+ def mixed_object(hash)
54
+ return unless hash
55
+
56
+ hash.tap do |h|
57
+ h.each do |k, v|
58
+ hash[k] = v.is_a?(String) ? keyword_field(v) : v
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # @api private
65
+ class Container
66
+ def initialize(config)
67
+ # @transaction = Serializers::TransactionSerializer.new(config)
68
+ # @span = Serializers::SpanSerializer.new(config)
69
+ @report = Serializers::ReportSerializer.new(config)
70
+ @event = Serializers::EventSerializer.new(config)
71
+ @error = Serializers::ErrorSerializer.new(config)
72
+ @metadata = Serializers::MetadataSerializer.new(config)
73
+ # @metricset = Serializers::MetricsetSerializer.new(config)
74
+ end
75
+
76
+ attr_reader :report, :event, :error, :metadata, :metricset
77
+ def serialize(resource)
78
+ case resource
79
+ # when Transaction
80
+ # transaction.build(resource)
81
+ # when Span
82
+ # span.build(resource)
83
+ when Report
84
+ report.build(resource)
85
+ when Event
86
+ event.build(resource)
87
+ when Error
88
+ error.build(resource)
89
+ # when Metricset
90
+ # metricset.build(resource)
91
+ when Metadata
92
+ metadata.build(resource)
93
+ else
94
+ raise UnrecognizedResource, resource.inspect
95
+ end
96
+ end
97
+ end
98
+
99
+ def self.new(config)
100
+ Container.new(config)
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ require 'hoss/transport/serializers/context_serializer'
107
+ # require 'hoss/transport/serializers/transaction_serializer'
108
+ # require 'hoss/transport/serializers/span_serializer'
109
+ require 'hoss/transport/serializers/report_serializer'
110
+ require 'hoss/transport/serializers/event_serializer'
111
+ require 'hoss/transport/serializers/error_serializer'
112
+ # require 'hoss/transport/serializers/metricset_serializer'
113
+ require 'hoss/transport/serializers/metadata_serializer'
@@ -0,0 +1,112 @@
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
+ module Transport
22
+ module Serializers
23
+ # @api private
24
+ class ContextSerializer < Serializer
25
+ def build(context)
26
+ return nil if context.nil? || context.empty?
27
+
28
+ {
29
+ custom: context.custom,
30
+ tags: mixed_object(context.labels),
31
+ request: build_request(context.request),
32
+ response: build_response(context.response),
33
+ user: build_user(context.user),
34
+ service: build_service(context.service)
35
+ }
36
+ end
37
+
38
+ private
39
+
40
+ def build_request(request)
41
+ return unless request
42
+
43
+ {
44
+ body: request.body,
45
+ cookies: request.cookies,
46
+ env: request.env,
47
+ headers: request.headers,
48
+ http_version: keyword_field(request.http_version),
49
+ method: keyword_field(request.method),
50
+ socket: build_socket(request.socket),
51
+ url: build_url(request.url)
52
+ }
53
+ end
54
+
55
+ def build_response(response)
56
+ return unless response
57
+
58
+ {
59
+ status_code: response.status_code.to_i,
60
+ headers: response.headers,
61
+ headers_sent: response.headers_sent,
62
+ finished: response.finished
63
+ }
64
+ end
65
+
66
+ def build_user(user)
67
+ return if !user || user.empty?
68
+
69
+ {
70
+ id: keyword_field(user.id),
71
+ email: keyword_field(user.email),
72
+ username: keyword_field(user.username)
73
+ }
74
+ end
75
+
76
+ def build_socket(socket)
77
+ return unless socket
78
+
79
+ {
80
+ remote_addr: socket.remote_addr,
81
+ encrypted: socket.encrypted
82
+ }
83
+ end
84
+
85
+ def build_url(url)
86
+ return unless url
87
+
88
+ {
89
+ protocol: keyword_field(url.protocol),
90
+ full: keyword_field(url.full),
91
+ hostname: keyword_field(url.hostname),
92
+ port: keyword_field(url.port),
93
+ pathname: keyword_field(url.pathname),
94
+ search: keyword_field(url.search),
95
+ hash: keyword_field(url.hash)
96
+ }
97
+ end
98
+
99
+ def build_service(service)
100
+ return unless service
101
+
102
+ {
103
+ framework: {
104
+ name: keyword_field(service.framework.name),
105
+ version: keyword_field(service.framework.version)
106
+ }
107
+ }
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,92 @@
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
+ module Transport
22
+ module Serializers
23
+ # @api private
24
+ class ErrorSerializer < Serializer
25
+ def context_serializer
26
+ @context_serializer ||= ContextSerializer.new(config)
27
+ end
28
+
29
+ def build(error)
30
+ base = {
31
+ id: error.id,
32
+ transaction_id: error.transaction_id,
33
+ transaction: build_transaction(error.transaction),
34
+ trace_id: error.trace_id,
35
+ parent_id: error.parent_id,
36
+
37
+ culprit: keyword_field(error.culprit),
38
+ timestamp: error.timestamp
39
+ }
40
+
41
+ if (context = context_serializer.build(error.context))
42
+ base[:context] = context
43
+ end
44
+
45
+ if (exception = error.exception)
46
+ base[:exception] = build_exception exception
47
+ end
48
+
49
+ if (log = error.log)
50
+ base[:log] = build_log log
51
+ end
52
+
53
+ { error: base }
54
+ end
55
+
56
+ private
57
+
58
+ def build_exception(exception)
59
+ {
60
+ message: exception.message,
61
+ type: keyword_field(exception.type),
62
+ module: keyword_field(exception.module),
63
+ code: keyword_field(exception.code),
64
+ attributes: exception.attributes,
65
+ stacktrace: exception.stacktrace.to_a,
66
+ handled: exception.handled,
67
+ cause: exception.cause && [build_exception(exception.cause)]
68
+ }
69
+ end
70
+
71
+ def build_log(log)
72
+ {
73
+ message: log.message,
74
+ level: keyword_field(log.level),
75
+ logger_name: keyword_field(log.logger_name),
76
+ param_message: keyword_field(log.param_message),
77
+ stacktrace: log.stacktrace.to_a
78
+ }
79
+ end
80
+
81
+ def build_transaction(transaction)
82
+ return unless transaction
83
+
84
+ {
85
+ sampled: transaction[:sampled],
86
+ type: keyword_field(transaction[:type])
87
+ }
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,73 @@
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
+ module Transport
22
+ module Serializers
23
+ # @api private
24
+ class EventSerializer < Serializer
25
+ def build(event)
26
+ r = {
27
+ eventId: event.id,
28
+ request: build_request(event.request),
29
+ response: build_response(event.response),
30
+ }
31
+ r['error'] = build_error(event.error) if event.error
32
+ r
33
+ end
34
+
35
+ private
36
+
37
+ def build_request(request)
38
+ return unless request
39
+ body = request.body ? Base64.encode64(request.body).strip : nil
40
+
41
+ {
42
+ method: request.method,
43
+ url: request.url,
44
+ headers: request.headers,
45
+ body: body || '',
46
+ receivedAt: request.received_at
47
+ }
48
+ end
49
+
50
+ def build_response(response)
51
+ return unless response
52
+ body = response.body ? Base64.encode64(response.body).strip : nil
53
+
54
+ {
55
+ statusCode: response.status_code,
56
+ headers: response.headers,
57
+ body: body || '',
58
+ receivedAt: response.received_at
59
+ }
60
+ end
61
+
62
+ def build_error(error)
63
+ return unless error
64
+
65
+ {
66
+ type: error.type,
67
+ receivedAt: error.received_at
68
+ }
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,92 @@
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
+ module Transport
22
+ module Serializers
23
+ # @api private
24
+ class MetadataSerializer < Serializer
25
+ def build(metadata)
26
+ {
27
+ metadata: {
28
+ service: build_service(metadata.service),
29
+ process: build_process(metadata.process),
30
+ system: build_system(metadata.system),
31
+ labels: build_labels(metadata.labels)
32
+ }
33
+ }
34
+ end
35
+
36
+ private
37
+
38
+ def build_service(service)
39
+ base =
40
+ {
41
+ name: keyword_field(service.name),
42
+ environment: keyword_field(service.environment),
43
+ version: keyword_field(service.version),
44
+ agent: {
45
+ name: keyword_field(service.agent.name),
46
+ version: keyword_field(service.agent.version)
47
+ },
48
+ framework: {
49
+ name: keyword_field(service.framework.name),
50
+ version: keyword_field(service.framework.version)
51
+ },
52
+ language: {
53
+ name: keyword_field(service.language.name),
54
+ version: keyword_field(service.language.version)
55
+ },
56
+ runtime: {
57
+ name: keyword_field(service.runtime.name),
58
+ version: keyword_field(service.runtime.version)
59
+ }
60
+ }
61
+
62
+ if node_name = service.node_name
63
+ base[:node] = { name: keyword_field(node_name) }
64
+ end
65
+
66
+ base
67
+ end
68
+
69
+ def build_process(process)
70
+ {
71
+ pid: process.pid,
72
+ title: keyword_field(process.title),
73
+ argv: process.argv
74
+ }
75
+ end
76
+
77
+ def build_system(system)
78
+ {
79
+ hostname: keyword_field(system.hostname),
80
+ architecture: keyword_field(system.architecture),
81
+ platform: keyword_field(system.platform),
82
+ kubernetes: keyword_object(system.kubernetes)
83
+ }
84
+ end
85
+
86
+ def build_labels(labels)
87
+ keyword_object(labels)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end