hoss-agent 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
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 +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 +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