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