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.
- 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 +313 -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 +102 -0
- data/lib/hoss/spies/http.rb +81 -0
- data/lib/hoss/spies/net_http.rb +97 -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 +326 -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,90 @@
|
|
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 ErrorBuilder
|
23
|
+
def initialize(agent)
|
24
|
+
@agent = agent
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_exception(exception, context: nil, handled: true)
|
28
|
+
error = Error.new context: context || Context.new
|
29
|
+
error.exception =
|
30
|
+
Error::Exception.from_exception(exception, handled: handled)
|
31
|
+
|
32
|
+
Util.reverse_merge!(error.context.labels, @agent.config.default_labels)
|
33
|
+
|
34
|
+
if exception.backtrace
|
35
|
+
add_stacktrace error, :exception, exception.backtrace
|
36
|
+
end
|
37
|
+
|
38
|
+
add_current_transaction_fields error, Hoss.current_transaction
|
39
|
+
|
40
|
+
error
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_log(message, context: nil, backtrace: nil, **attrs)
|
44
|
+
error = Error.new context: context || Context.new
|
45
|
+
error.log = Error::Log.new(message, **attrs)
|
46
|
+
|
47
|
+
if backtrace
|
48
|
+
add_stacktrace error, :log, backtrace
|
49
|
+
end
|
50
|
+
|
51
|
+
add_current_transaction_fields error, Hoss.current_transaction
|
52
|
+
|
53
|
+
error
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def add_stacktrace(error, kind, backtrace)
|
59
|
+
stacktrace =
|
60
|
+
@agent.stacktrace_builder.build(backtrace, type: :error)
|
61
|
+
return unless stacktrace
|
62
|
+
|
63
|
+
case kind
|
64
|
+
when :exception
|
65
|
+
error.exception.stacktrace = stacktrace
|
66
|
+
when :log
|
67
|
+
error.log.stacktrace = stacktrace
|
68
|
+
end
|
69
|
+
|
70
|
+
error.culprit = stacktrace.frames.first&.function
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_current_transaction_fields(error, transaction)
|
74
|
+
return unless transaction
|
75
|
+
|
76
|
+
error.transaction_id = transaction.id
|
77
|
+
error.transaction = {
|
78
|
+
sampled: transaction.sampled?,
|
79
|
+
type: transaction.type
|
80
|
+
}
|
81
|
+
error.trace_id = transaction.trace_id
|
82
|
+
error.parent_id = Hoss.current_span&.id || transaction.id
|
83
|
+
|
84
|
+
return unless transaction.context
|
85
|
+
|
86
|
+
Util.reverse_merge!(error.context.labels, transaction.context.labels)
|
87
|
+
Util.reverse_merge!(error.context.custom, transaction.context.custom)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/hoss/event.rb
ADDED
@@ -0,0 +1,131 @@
|
|
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/span/context'
|
21
|
+
|
22
|
+
module Hoss
|
23
|
+
# @api private
|
24
|
+
class Event
|
25
|
+
extend Forwardable
|
26
|
+
include ChildDurations::Methods
|
27
|
+
|
28
|
+
DEFAULT_TYPE = 'custom'
|
29
|
+
|
30
|
+
class Request
|
31
|
+
extend Forwardable
|
32
|
+
def initialize
|
33
|
+
@headers = {}
|
34
|
+
end
|
35
|
+
attr_accessor(
|
36
|
+
:method,
|
37
|
+
:url,
|
38
|
+
:headers,
|
39
|
+
:body,
|
40
|
+
:received_at
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
class Response
|
45
|
+
extend Forwardable
|
46
|
+
def initialize
|
47
|
+
@headers = {}
|
48
|
+
end
|
49
|
+
attr_accessor(
|
50
|
+
:status_code,
|
51
|
+
:headers,
|
52
|
+
:body,
|
53
|
+
:received_at
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
class Error
|
58
|
+
extend Forwardable
|
59
|
+
ConnectionTimeout = 'CONNECTION_TIMEOUT'
|
60
|
+
RequestTimeout = 'REQUEST_TIMEOUT'
|
61
|
+
ConnectionError = 'CONNECTION_ERROR'
|
62
|
+
def initialize(type)
|
63
|
+
@type = type
|
64
|
+
end
|
65
|
+
attr_accessor(
|
66
|
+
:type,
|
67
|
+
:received_at
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
# rubocop:disable Metrics/ParameterLists
|
72
|
+
def initialize
|
73
|
+
@id = SecureRandom.uuid
|
74
|
+
@request = Request.new
|
75
|
+
# @response = Response.new
|
76
|
+
@filtered = false
|
77
|
+
@retries = 0
|
78
|
+
end
|
79
|
+
# rubocop:enable Metrics/ParameterLists
|
80
|
+
|
81
|
+
attr_accessor(
|
82
|
+
:request,
|
83
|
+
:response,
|
84
|
+
:error,
|
85
|
+
:filtered,
|
86
|
+
:retries,
|
87
|
+
)
|
88
|
+
|
89
|
+
attr_reader(
|
90
|
+
:id
|
91
|
+
)
|
92
|
+
|
93
|
+
# life cycle
|
94
|
+
|
95
|
+
def start(clock_start = Util.monotonic_micros)
|
96
|
+
@timestamp = Util.micros
|
97
|
+
@clock_start = clock_start
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
def stop(clock_end = Util.monotonic_micros)
|
102
|
+
@duration ||= (clock_end - @clock_start)
|
103
|
+
@self_time = @duration - child_durations.duration
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
def done(clock_end: Util.monotonic_micros)
|
108
|
+
stop clock_end
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
def stopped?
|
113
|
+
!!duration
|
114
|
+
end
|
115
|
+
|
116
|
+
def started?
|
117
|
+
!!timestamp
|
118
|
+
end
|
119
|
+
|
120
|
+
def running?
|
121
|
+
started? && !stopped?
|
122
|
+
end
|
123
|
+
|
124
|
+
# relations
|
125
|
+
|
126
|
+
def inspect
|
127
|
+
"<Hoss::Event id:#{id.inspect}" \
|
128
|
+
'>'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,107 @@
|
|
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/child_durations'
|
21
|
+
require 'hoss/event'
|
22
|
+
|
23
|
+
module Hoss
|
24
|
+
# @api private
|
25
|
+
class Instrumenter
|
26
|
+
EVENT_KEY = :__elastic_instrumenter_events_key
|
27
|
+
|
28
|
+
include Logging
|
29
|
+
|
30
|
+
# @api private
|
31
|
+
class Current
|
32
|
+
def initialize
|
33
|
+
self.events = []
|
34
|
+
end
|
35
|
+
|
36
|
+
def events
|
37
|
+
Thread.current[EVENT_KEY] ||= []
|
38
|
+
end
|
39
|
+
|
40
|
+
def events=(events)
|
41
|
+
Thread.current[EVENT_KEY] ||= []
|
42
|
+
Thread.current[EVENT_KEY] = events
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(config, metrics:, stacktrace_builder:, &enqueue)
|
47
|
+
@config = config
|
48
|
+
@stacktrace_builder = stacktrace_builder
|
49
|
+
@enqueue = enqueue
|
50
|
+
@metrics = metrics
|
51
|
+
|
52
|
+
@current = Current.new
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_reader :stacktrace_builder, :enqueue
|
56
|
+
|
57
|
+
def start
|
58
|
+
debug 'Starting instrumenter'
|
59
|
+
# We call register! on @subscriber in case the
|
60
|
+
# instrumenter was stopped and started again
|
61
|
+
@subscriber&.register!
|
62
|
+
end
|
63
|
+
|
64
|
+
def stop
|
65
|
+
debug 'Stopping instrumenter'
|
66
|
+
|
67
|
+
current_events.pop until current_events.empty?
|
68
|
+
|
69
|
+
@subscriber&.unregister!
|
70
|
+
end
|
71
|
+
|
72
|
+
def handle_forking!
|
73
|
+
stop
|
74
|
+
start
|
75
|
+
end
|
76
|
+
|
77
|
+
def subscriber=(subscriber)
|
78
|
+
debug 'Registering subscriber'
|
79
|
+
@subscriber = subscriber
|
80
|
+
@subscriber.register!
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# events
|
85
|
+
|
86
|
+
def current_events
|
87
|
+
@current.events
|
88
|
+
end
|
89
|
+
|
90
|
+
def current_event
|
91
|
+
current_events.last
|
92
|
+
end
|
93
|
+
|
94
|
+
def start_event
|
95
|
+
event = Event.new
|
96
|
+
current_events.push event
|
97
|
+
event.start
|
98
|
+
end
|
99
|
+
|
100
|
+
def end_event
|
101
|
+
return unless (event = current_events.pop)
|
102
|
+
event.done
|
103
|
+
enqueue.call event
|
104
|
+
event
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,23 @@
|
|
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 InternalError < StandardError; end
|
22
|
+
class ExistingTransactionError < InternalError; end
|
23
|
+
end
|
data/lib/hoss/logging.rb
ADDED
@@ -0,0 +1,70 @@
|
|
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
|
+
module Logging
|
23
|
+
PREFIX = '[Hoss] '
|
24
|
+
|
25
|
+
LEVELS = {
|
26
|
+
debug: Logger::DEBUG,
|
27
|
+
info: Logger::INFO,
|
28
|
+
warn: Logger::WARN,
|
29
|
+
error: Logger::ERROR,
|
30
|
+
fatal: Logger::FATAL
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
def debug(msg, *args, &block)
|
34
|
+
log(:debug, msg, *args, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def info(msg, *args, &block)
|
38
|
+
log(:info, msg, *args, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def warn(msg, *args, &block)
|
42
|
+
log(:warn, msg, *args, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
def error(msg, *args, &block)
|
46
|
+
log(:error, msg, *args, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def fatal(msg, *args, &block)
|
50
|
+
log(:fatal, msg, *args, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def log(lvl, msg, *args)
|
56
|
+
return unless (logger = @config&.logger)
|
57
|
+
return unless LEVELS[lvl] >= (@config&.log_level || 0)
|
58
|
+
|
59
|
+
formatted_msg = prepend_prefix(format(msg.to_s, *args))
|
60
|
+
|
61
|
+
return logger.send(lvl, formatted_msg) unless block_given?
|
62
|
+
|
63
|
+
logger.send(lvl, "#{formatted_msg}\n#{yield}")
|
64
|
+
end
|
65
|
+
|
66
|
+
def prepend_prefix(str)
|
67
|
+
"#{PREFIX}#{str}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
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 Metadata
|
23
|
+
def initialize(config)
|
24
|
+
@service = ServiceInfo.new(config)
|
25
|
+
@process = ProcessInfo.new(config)
|
26
|
+
@system = SystemInfo.new(config)
|
27
|
+
@labels = config.global_labels
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :service, :process, :system, :labels
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'hoss/metadata/service_info'
|
35
|
+
require 'hoss/metadata/system_info'
|
36
|
+
require 'hoss/metadata/process_info'
|