newrelic_rpm 3.13.2.302 → 3.14.0.305
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +20 -0
- data/README.md +1 -13
- data/lib/new_relic/agent/agent.rb +40 -15
- data/lib/new_relic/agent/agent_logger.rb +1 -1
- data/lib/new_relic/agent/configuration/default_source.rb +16 -6
- data/lib/new_relic/agent/configuration/server_source.rb +2 -1
- data/lib/new_relic/agent/error_collector.rb +13 -21
- data/lib/new_relic/agent/error_event_aggregator.rb +124 -0
- data/lib/new_relic/agent/error_trace_aggregator.rb +15 -5
- data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +16 -2
- data/lib/new_relic/agent/new_relic_service.rb +11 -10
- data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +1 -1
- data/lib/new_relic/agent/payload_metric_mapping.rb +58 -0
- data/lib/new_relic/agent/sampled_buffer.rb +15 -1
- data/lib/new_relic/agent/supported_versions.rb +4 -4
- data/lib/new_relic/agent/transaction.rb +52 -44
- data/lib/new_relic/agent/transaction/request_attributes.rb +110 -0
- data/lib/new_relic/agent/transaction_event_aggregator.rb +4 -41
- data/lib/new_relic/noticed_error.rb +25 -9
- data/lib/new_relic/rack/agent_middleware.rb +5 -0
- data/lib/new_relic/version.rb +2 -2
- data/newrelic_rpm.gemspec +6 -0
- data/test/agent_helper.rb +16 -7
- data/test/environments/norails/Gemfile +1 -0
- data/test/multiverse/lib/multiverse/runner.rb +1 -1
- data/test/multiverse/lib/multiverse/suite.rb +6 -3
- data/test/multiverse/suites/agent_only/agent_attributes_test.rb +57 -0
- data/test/multiverse/suites/agent_only/audit_log_test.rb +1 -2
- data/test/multiverse/suites/agent_only/error_events_test.rb +82 -0
- data/test/multiverse/suites/agent_only/harvest_timestamps_test.rb +31 -6
- data/test/multiverse/suites/agent_only/logging_test.rb +2 -2
- data/test/multiverse/suites/agent_only/marshaling_test.rb +6 -0
- data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +2 -2
- data/test/multiverse/suites/agent_only/thread_profiling_test.rb +0 -20
- data/test/multiverse/suites/grape/grape_test.rb +16 -1
- data/test/multiverse/suites/no_json/Envfile +12 -0
- data/test/multiverse/suites/no_json/config/newrelic.yml +27 -0
- data/test/multiverse/suites/no_json/marshal_config_test.rb +22 -0
- data/test/multiverse/suites/rack/example_app.rb +19 -0
- data/test/multiverse/suites/rack/response_content_type_test.rb +50 -0
- data/test/multiverse/suites/rails/error_tracing_test.rb +12 -7
- data/test/multiverse/suites/rails/parameter_capture_test.rb +21 -1
- data/test/multiverse/suites/sinatra/sinatra_error_tracing_test.rb +5 -2
- data/test/multiverse/suites/sinatra/sinatra_parameter_capture_test.rb +16 -1
- data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +4 -2
- data/test/new_relic/agent/agent_logger_test.rb +9 -0
- data/test/new_relic/agent/agent_test.rb +6 -4
- data/test/new_relic/agent/audit_logger_test.rb +0 -7
- data/test/new_relic/agent/error_collector_test.rb +20 -250
- data/test/new_relic/agent/error_event_aggregator_test.rb +294 -0
- data/test/new_relic/agent/error_trace_aggregator_test.rb +273 -5
- data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +2 -2
- data/test/new_relic/agent/new_relic_service_test.rb +8 -32
- data/test/new_relic/agent/payload_metric_mapping_test.rb +74 -0
- data/test/new_relic/agent/pipe_channel_manager_test.rb +6 -5
- data/test/new_relic/agent/sampled_buffer_test.rb +36 -0
- data/test/new_relic/agent/sql_sampler_test.rb +4 -14
- data/test/new_relic/agent/stats_engine/stats_hash_test.rb +5 -4
- data/test/new_relic/agent/threading/thread_profile_test.rb +1 -2
- data/test/new_relic/agent/transaction/request_attributes_test.rb +76 -0
- data/test/new_relic/agent/transaction_event_aggregator_test.rb +12 -1
- data/test/new_relic/agent/transaction_test.rb +60 -11
- data/test/new_relic/data_container_tests.rb +17 -6
- data/test/new_relic/fake_collector.rb +16 -21
- data/test/new_relic/marshalling_test_cases.rb +1 -0
- data/test/new_relic/noticed_error_test.rb +59 -0
- data/test/new_relic/rack/agent_hooks_test.rb +1 -1
- data/test/new_relic/rack/error_collector_test.rb +7 -5
- data/test/performance/suites/error_collector.rb +28 -0
- data/test/performance/suites/marshalling.rb +0 -8
- metadata +14 -3
- data/lib/new_relic/agent/new_relic_service/pruby_marshaller.rb +0 -56
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 50bd75d704008669a67edbf82f40967d3465fb59
|
4
|
+
data.tar.gz: 82b7cf098d58c681ea061926fa1568429687cb62
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6160292363ad82115f434f5e6a6e6182ffd2f871aced553cf8465920ead0325a8146f3f5d00a318411b45ce882eafef5ea765bc68379cbb7ae3ab2c13190606e
|
7
|
+
data.tar.gz: 9398fc0ec397fb3ce9b58dfab6b6b0588248907bd6531fba226edbd919708aeeea5a0fe54c815cd65f8a3caf267bf60c1559445b1e339e8c10adcda76f16dc66
|
data/CHANGELOG
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes #
|
2
2
|
|
3
|
+
## v3.14.0 ##
|
4
|
+
|
5
|
+
* pruby marshaller removed
|
6
|
+
|
7
|
+
The deprecated pruby marshaller has now been removed; the `marshaller` config
|
8
|
+
option now only accepts `json`. Customers still running Ruby 1.8.7/REE must
|
9
|
+
add the `json` gem to their Gemfile, or (preferably) upgrade to Ruby 1.9.3 or
|
10
|
+
newer.
|
11
|
+
|
12
|
+
* Log dates in ISO 8601 format
|
13
|
+
|
14
|
+
The agent will now log dates in ISO 8601 (YYYY-mm-dd) format, instead of
|
15
|
+
mm/dd/yy.
|
16
|
+
|
17
|
+
* Additional attributes collected
|
18
|
+
|
19
|
+
The agent now collects the following information in web transactions (not
|
20
|
+
yet shown in the New Relic UI): Accept, Host, User-Agent, Content-Length HTTP
|
21
|
+
request headers, HTTP request method, and Content-Type HTTP response header.
|
22
|
+
|
3
23
|
## v3.13.2 ##
|
4
24
|
|
5
25
|
* Don't fail to send data when using 'mathn' library
|
data/README.md
CHANGED
@@ -21,21 +21,9 @@ automatically in Rails applications.
|
|
21
21
|
|
22
22
|
## Supported Environments
|
23
23
|
|
24
|
-
|
25
|
-
* JRuby 1.6 and 1.7
|
26
|
-
* Rubinius 2.x (Experimental support only)
|
27
|
-
* Rails 2.1 or later for Production Mode
|
28
|
-
* Rails 2.3 or later for Developer Mode
|
29
|
-
* Sinatra
|
30
|
-
* Rack
|
31
|
-
|
32
|
-
An up to date list of Ruby versions and frameworks for the latest agent
|
24
|
+
An up-to-date list of Ruby versions and frameworks for the latest agent
|
33
25
|
can be found on [our docs site](http://docs.newrelic.com/docs/ruby/supported-frameworks).
|
34
26
|
|
35
|
-
Any Rack based framework should work but may not be tested. Install
|
36
|
-
the Ruby Agent as a gem and add the Developer Mode middleware if
|
37
|
-
desired. Report any problems by visiting support.newrelic.com.
|
38
|
-
|
39
27
|
You can also monitor non-web applications. Refer to the "Other
|
40
28
|
Environments" section under "Getting Started".
|
41
29
|
|
@@ -528,6 +528,14 @@ module NewRelic
|
|
528
528
|
return false
|
529
529
|
end
|
530
530
|
|
531
|
+
unless NewRelic::Agent::NewRelicService::JsonMarshaller.is_supported?
|
532
|
+
NewRelic::Agent.logger.error "JSON marshaller requested, but the 'json' gem was not available. ",
|
533
|
+
"You will need to: 1) upgrade to Ruby 1.9.3 or newer (strongly recommended), ",
|
534
|
+
"2) add the 'json' gem to your Gemfile or operating environment, ",
|
535
|
+
"or 3) use a version of newrelic_rpm prior to 3.14.0."
|
536
|
+
return false
|
537
|
+
end
|
538
|
+
|
531
539
|
return true
|
532
540
|
end
|
533
541
|
|
@@ -547,7 +555,7 @@ module NewRelic
|
|
547
555
|
# Clear out the metric data, errors, and transaction traces, etc.
|
548
556
|
def drop_buffered_data
|
549
557
|
@stats_engine.reset!
|
550
|
-
@error_collector.
|
558
|
+
@error_collector.drop_buffered_data
|
551
559
|
@transaction_sampler.reset!
|
552
560
|
@transaction_event_aggregator.reset!
|
553
561
|
@custom_event_aggregator.reset!
|
@@ -915,7 +923,8 @@ module NewRelic
|
|
915
923
|
case endpoint
|
916
924
|
when :metric_data then @stats_engine
|
917
925
|
when :transaction_sample_data then @transaction_sampler
|
918
|
-
when :error_data then @error_collector
|
926
|
+
when :error_data then @error_collector.error_trace_aggregator
|
927
|
+
when :error_event_data then @error_collector.error_event_aggregator
|
919
928
|
when :analytic_event_data then @transaction_event_aggregator
|
920
929
|
when :custom_event_data then @custom_event_aggregator
|
921
930
|
when :sql_trace_data then @sql_sampler
|
@@ -1006,19 +1015,31 @@ module NewRelic
|
|
1006
1015
|
# The given container should respond to:
|
1007
1016
|
#
|
1008
1017
|
# #harvest!
|
1009
|
-
# returns
|
1010
|
-
# collector.
|
1018
|
+
# returns a payload that contains enumerable collection of data items and
|
1019
|
+
# optional metadata to be sent to the collector.
|
1011
1020
|
#
|
1012
1021
|
# #reset!
|
1013
1022
|
# drop any stored data and reset to a clean state.
|
1014
1023
|
#
|
1015
|
-
# #merge!(
|
1016
|
-
# merge the given
|
1017
|
-
# container, so that
|
1024
|
+
# #merge!(payload)
|
1025
|
+
# merge the given pyalod back into the internal buffer of the
|
1026
|
+
# container, so that it may be harvested again later.
|
1018
1027
|
#
|
1019
1028
|
def harvest_and_send_from_container(container, endpoint)
|
1020
|
-
|
1021
|
-
|
1029
|
+
payload = harvest_from_container(container, endpoint)
|
1030
|
+
sample_count = harvest_size container, payload
|
1031
|
+
if sample_count > 0
|
1032
|
+
NewRelic::Agent.logger.debug("Sending #{sample_count} items to #{endpoint}")
|
1033
|
+
send_data_to_endpoint(endpoint, payload, container)
|
1034
|
+
end
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
def harvest_size container, items
|
1038
|
+
if container.respond_to?(:has_metadata?) && container.has_metadata? && !items.empty?
|
1039
|
+
items.last.size
|
1040
|
+
else
|
1041
|
+
items.size
|
1042
|
+
end
|
1022
1043
|
end
|
1023
1044
|
|
1024
1045
|
def harvest_from_container(container, endpoint)
|
@@ -1032,10 +1053,9 @@ module NewRelic
|
|
1032
1053
|
items
|
1033
1054
|
end
|
1034
1055
|
|
1035
|
-
def send_data_to_endpoint(endpoint,
|
1036
|
-
NewRelic::Agent.logger.debug("Sending #{items.size} items to #{endpoint}")
|
1056
|
+
def send_data_to_endpoint(endpoint, payload, container)
|
1037
1057
|
begin
|
1038
|
-
@service.send(endpoint,
|
1058
|
+
@service.send(endpoint, payload)
|
1039
1059
|
rescue ForceRestartException, ForceDisconnectException
|
1040
1060
|
raise
|
1041
1061
|
rescue SerializationError => e
|
@@ -1044,10 +1064,10 @@ module NewRelic
|
|
1044
1064
|
NewRelic::Agent.logger.warn("#{endpoint} data was rejected by remote service, discarding. Error: ", e)
|
1045
1065
|
rescue ServerConnectionException => e
|
1046
1066
|
log_remote_unavailable(endpoint, e)
|
1047
|
-
container.merge!(
|
1067
|
+
container.merge!(payload)
|
1048
1068
|
rescue => e
|
1049
1069
|
NewRelic::Agent.logger.info("Unable to send #{endpoint} data, will try again later. Error: ", e)
|
1050
|
-
container.merge!(
|
1070
|
+
container.merge!(payload)
|
1051
1071
|
end
|
1052
1072
|
end
|
1053
1073
|
|
@@ -1075,7 +1095,7 @@ module NewRelic
|
|
1075
1095
|
end
|
1076
1096
|
|
1077
1097
|
def harvest_and_send_errors
|
1078
|
-
harvest_and_send_from_container(@error_collector, :error_data)
|
1098
|
+
harvest_and_send_from_container(@error_collector.error_trace_aggregator, :error_data)
|
1079
1099
|
end
|
1080
1100
|
|
1081
1101
|
def harvest_and_send_analytic_event_data
|
@@ -1083,6 +1103,10 @@ module NewRelic
|
|
1083
1103
|
harvest_and_send_from_container(@custom_event_aggregator, :custom_event_data)
|
1084
1104
|
end
|
1085
1105
|
|
1106
|
+
def harvest_and_send_error_event_data
|
1107
|
+
harvest_and_send_from_container @error_collector.error_event_aggregator, :error_event_data
|
1108
|
+
end
|
1109
|
+
|
1086
1110
|
def check_for_and_handle_agent_commands
|
1087
1111
|
begin
|
1088
1112
|
@agent_command_router.check_for_and_handle_agent_commands
|
@@ -1126,6 +1150,7 @@ module NewRelic
|
|
1126
1150
|
@events.notify(:before_harvest)
|
1127
1151
|
@service.session do # use http keep-alive
|
1128
1152
|
harvest_and_send_errors
|
1153
|
+
harvest_and_send_error_event_data
|
1129
1154
|
harvest_and_send_transaction_traces
|
1130
1155
|
harvest_and_send_slowest_sql
|
1131
1156
|
harvest_and_send_timeslice_data
|
@@ -165,7 +165,7 @@ module NewRelic
|
|
165
165
|
@hostname = NewRelic::Agent::Hostname.get
|
166
166
|
@prefix = wants_stdout? ? '** [NewRelic]' : ''
|
167
167
|
@log.formatter = Proc.new do |severity, timestamp, progname, msg|
|
168
|
-
"#{@prefix}[#{timestamp.strftime("%
|
168
|
+
"#{@prefix}[#{timestamp.strftime("%F %H:%M:%S %z")} #{@hostname} (#{$$})] #{severity} : #{msg}\n"
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
@@ -121,10 +121,6 @@ module NewRelic
|
|
121
121
|
Proc.new { NewRelic::Control.instance.local_env.discovered_dispatcher }
|
122
122
|
end
|
123
123
|
|
124
|
-
def self.marshaller
|
125
|
-
Proc.new { NewRelic::Agent::NewRelicService::JsonMarshaller.is_supported? ? 'json' : 'pruby' }
|
126
|
-
end
|
127
|
-
|
128
124
|
# On Rubies with string encodings support (1.9.x+), default to always
|
129
125
|
# normalize encodings since it's safest and fast. Without that support
|
130
126
|
# the conversions are too expensive, so only enable if overridden to.
|
@@ -935,6 +931,20 @@ module NewRelic
|
|
935
931
|
:allowed_from_server => true,
|
936
932
|
:description => 'Specifies a comma-delimited list of error classes that the agent should ignore.'
|
937
933
|
},
|
934
|
+
:'error_collector.capture_events' => {
|
935
|
+
:default => value_of(:'error_collector.enabled'),
|
936
|
+
:public => true,
|
937
|
+
:type => Boolean,
|
938
|
+
:allowed_from_server => true,
|
939
|
+
:description => 'Enable or disable the collection of TransactionError events.'
|
940
|
+
},
|
941
|
+
:'error_collector.max_event_samples_stored' => {
|
942
|
+
:default => 100,
|
943
|
+
:public => true,
|
944
|
+
:type => Fixnum,
|
945
|
+
:allowed_from_server => true,
|
946
|
+
:description => 'The number of TransactionError samples sent to Insights per harvest cycle.'
|
947
|
+
},
|
938
948
|
:'rum.enabled' => {
|
939
949
|
:default => true,
|
940
950
|
:public => false,
|
@@ -1116,11 +1126,11 @@ module NewRelic
|
|
1116
1126
|
:description => 'Maximum overhead percentage for thread profiling before agent reduces polling frequency'
|
1117
1127
|
},
|
1118
1128
|
:marshaller => {
|
1119
|
-
:default =>
|
1129
|
+
:default => 'json',
|
1120
1130
|
:public => true,
|
1121
1131
|
:type => String,
|
1122
1132
|
:allowed_from_server => false,
|
1123
|
-
:description => 'Specifies a marshaller for transmitting data to the New Relic <a href="/docs/apm/new-relic-apm/getting-started/glossary#collector">collector</a>)
|
1133
|
+
:description => 'Specifies a marshaller for transmitting data to the New Relic <a href="/docs/apm/new-relic-apm/getting-started/glossary#collector">collector</a>). Currently \'json\' is the only valid value for this setting. The pruby marshaller has been removed as of 3.14.0.'
|
1124
1134
|
},
|
1125
1135
|
:'analytics_events.enabled' => {
|
1126
1136
|
:default => true,
|
@@ -96,7 +96,8 @@ module NewRelic
|
|
96
96
|
'slow_sql.enabled' => 'collect_traces',
|
97
97
|
'error_collector.enabled' => 'collect_errors',
|
98
98
|
'analytics_events.enabled' => 'collect_analytics_events',
|
99
|
-
'custom_insights_events.enabled' => 'collect_custom_events'
|
99
|
+
'custom_insights_events.enabled' => 'collect_custom_events',
|
100
|
+
'error_collector.capture_events' => 'collect_error_events'
|
100
101
|
}
|
101
102
|
gated_features.each do |config_key, gate_key|
|
102
103
|
if connect_reply.has_key?(gate_key)
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# This file is distributed under New Relic's license terms.
|
3
3
|
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
4
|
require 'new_relic/agent/error_trace_aggregator'
|
5
|
+
require 'new_relic/agent/error_event_aggregator'
|
5
6
|
|
6
7
|
module NewRelic
|
7
8
|
module Agent
|
@@ -16,27 +17,23 @@ module NewRelic
|
|
16
17
|
MAX_ERROR_QUEUE_LENGTH = 20 unless defined? MAX_ERROR_QUEUE_LENGTH
|
17
18
|
EXCEPTION_TAG_IVAR = :'@__nr_seen_exception' unless defined? EXCEPTION_TAG_IVAR
|
18
19
|
|
20
|
+
attr_reader :error_trace_aggregator, :error_event_aggregator
|
21
|
+
|
19
22
|
# Returns a new error collector
|
20
23
|
def initialize
|
21
24
|
@error_trace_aggregator = ErrorTraceAggregator.new(MAX_ERROR_QUEUE_LENGTH)
|
22
|
-
|
25
|
+
@error_event_aggregator = ErrorEventAggregator.new
|
23
26
|
|
24
27
|
# lookup of exception class names to ignore. Hash for fast access
|
25
28
|
@ignore = {}
|
26
29
|
|
27
30
|
initialize_ignored_errors(Agent.config[:'error_collector.ignore_errors'])
|
28
31
|
|
29
|
-
Agent.config.register_callback(:'error_collector.enabled') do |config_enabled|
|
30
|
-
::NewRelic::Agent.logger.debug "Errors will #{config_enabled ? '' : 'not '}be sent to the New Relic service."
|
31
|
-
end
|
32
32
|
Agent.config.register_callback(:'error_collector.ignore_errors') do |ignore_errors|
|
33
33
|
initialize_ignored_errors(ignore_errors)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
def errors
|
38
|
-
@error_trace_aggregator.errors
|
39
|
-
end
|
40
37
|
|
41
38
|
def initialize_ignored_errors(ignore_errors)
|
42
39
|
@ignore.clear
|
@@ -46,7 +43,7 @@ module NewRelic
|
|
46
43
|
end
|
47
44
|
|
48
45
|
def enabled?
|
49
|
-
|
46
|
+
error_trace_aggregator.enabled? || error_event_aggregator.enabled?
|
50
47
|
end
|
51
48
|
|
52
49
|
def disabled?
|
@@ -200,11 +197,13 @@ module NewRelic
|
|
200
197
|
|
201
198
|
state = ::NewRelic::Agent::TransactionState.tl_get
|
202
199
|
increment_error_count!(state, exception, options)
|
203
|
-
|
204
|
-
|
200
|
+
noticed_error = create_noticed_error(exception, options)
|
201
|
+
error_trace_aggregator.add_to_error_queue(noticed_error)
|
202
|
+
error_event_aggregator.append_event(noticed_error, state.current_transaction.payload)
|
205
203
|
exception
|
206
204
|
rescue => e
|
207
205
|
::NewRelic::Agent.logger.warn("Failure when capturing error '#{exception}':", e)
|
206
|
+
nil
|
208
207
|
end
|
209
208
|
|
210
209
|
EMPTY_STRING = ''.freeze
|
@@ -214,6 +213,7 @@ module NewRelic
|
|
214
213
|
|
215
214
|
noticed_error = NewRelic::NoticedError.new(error_metric, exception)
|
216
215
|
noticed_error.request_uri = options.delete(:uri) || EMPTY_STRING
|
216
|
+
noticed_error.request_port = options.delete(:port)
|
217
217
|
noticed_error.attributes = options.delete(:attributes)
|
218
218
|
|
219
219
|
noticed_error.file_name = sense_method(exception, :file_name)
|
@@ -259,18 +259,10 @@ module NewRelic
|
|
259
259
|
@error_trace_aggregator.notice_agent_error(exception)
|
260
260
|
end
|
261
261
|
|
262
|
-
def
|
263
|
-
@error_trace_aggregator.merge!(errors)
|
264
|
-
end
|
265
|
-
|
266
|
-
# Get the errors currently queued up. Unsent errors are left
|
267
|
-
# over from a previous unsuccessful attempt to send them to the server.
|
268
|
-
def harvest!
|
269
|
-
@error_trace_aggregator.harvest!
|
270
|
-
end
|
271
|
-
|
272
|
-
def reset!
|
262
|
+
def drop_buffered_data
|
273
263
|
@error_trace_aggregator.reset!
|
264
|
+
@error_event_aggregator.reset!
|
265
|
+
nil
|
274
266
|
end
|
275
267
|
end
|
276
268
|
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# encoding: utf-8
|
3
|
+
# This file is distributed under New Relic's license terms.
|
4
|
+
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
5
|
+
|
6
|
+
require 'new_relic/agent/sampled_buffer'
|
7
|
+
require 'new_relic/agent/payload_metric_mapping'
|
8
|
+
|
9
|
+
module NewRelic
|
10
|
+
module Agent
|
11
|
+
class ErrorEventAggregator
|
12
|
+
EVENT_TYPE = "TransactionError".freeze
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@lock = Mutex.new
|
16
|
+
@error_event_buffer = SampledBuffer.new Agent.config[:'error_collector.max_event_samples_stored']
|
17
|
+
register_config_callbacks
|
18
|
+
end
|
19
|
+
|
20
|
+
def enabled?
|
21
|
+
Agent.config[:'error_collector.capture_events']
|
22
|
+
end
|
23
|
+
|
24
|
+
def append_event noticed_error, transaction_payload
|
25
|
+
return unless enabled?
|
26
|
+
|
27
|
+
@lock.synchronize do
|
28
|
+
@error_event_buffer.append do
|
29
|
+
event_for_collector(noticed_error, transaction_payload)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def harvest!
|
35
|
+
@lock.synchronize do
|
36
|
+
samples = @error_event_buffer.to_a
|
37
|
+
# Eventually the logic for adding reservoir data will move to the sampled buffer
|
38
|
+
# so it can be shared with the other event aggregators. We'll first get it working
|
39
|
+
# here and then promote the functionality later.
|
40
|
+
stats = reservoir_stats
|
41
|
+
@error_event_buffer.reset!
|
42
|
+
[stats, samples]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def reset!
|
47
|
+
@lock.synchronize do
|
48
|
+
@error_event_buffer.reset!
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# samples will have already been transformed into
|
53
|
+
# collector primitives by event_for_collector
|
54
|
+
def merge! payload
|
55
|
+
@lock.synchronize do
|
56
|
+
_, samples = payload
|
57
|
+
@error_event_buffer.decrement_lifetime_counts_by samples.count
|
58
|
+
samples.each { |s| @error_event_buffer.append s }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def has_metadata?
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def reservoir_stats
|
69
|
+
{
|
70
|
+
:reservoir_size => Agent.config[:'error_collector.max_event_samples_stored'],
|
71
|
+
:events_seen => @error_event_buffer.num_seen
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def register_config_callbacks
|
76
|
+
NewRelic::Agent.config.register_callback(:'error_collector.max_event_samples_stored') do |max_samples|
|
77
|
+
NewRelic::Agent.logger.debug "ErrorEventAggregator max_samples set to #{max_samples}"
|
78
|
+
@lock.synchronize { @error_event_buffer.capacity = max_samples }
|
79
|
+
end
|
80
|
+
|
81
|
+
NewRelic::Agent.config.register_callback(:'error_collector.capture_events') do |enabled|
|
82
|
+
::NewRelic::Agent.logger.debug "Error events will #{enabled ? '' : 'not '}be sent to the New Relic service."
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def event_for_collector noticed_error, transaction_payload
|
87
|
+
[
|
88
|
+
intrinsic_attributes_for(noticed_error, transaction_payload),
|
89
|
+
noticed_error.custom_attributes,
|
90
|
+
noticed_error.agent_attributes
|
91
|
+
]
|
92
|
+
end
|
93
|
+
|
94
|
+
def intrinsic_attributes_for noticed_error, transaction_payload
|
95
|
+
attrs = {
|
96
|
+
:type => EVENT_TYPE,
|
97
|
+
:'error.class' => noticed_error.exception_class_name,
|
98
|
+
:'error.message' => noticed_error.message,
|
99
|
+
:timestamp => noticed_error.timestamp.to_f,
|
100
|
+
:transactionName => transaction_payload[:name],
|
101
|
+
:duration => transaction_payload[:duration]
|
102
|
+
}
|
103
|
+
attrs[:port] = noticed_error.request_port if noticed_error.request_port
|
104
|
+
|
105
|
+
append_synthetics transaction_payload, attrs
|
106
|
+
append_cat transaction_payload, attrs
|
107
|
+
PayloadMetricMapping.append_mapped_metrics transaction_payload[:metrics], attrs
|
108
|
+
|
109
|
+
attrs
|
110
|
+
end
|
111
|
+
|
112
|
+
def append_synthetics transaction_payload, sample
|
113
|
+
sample[:'nr.syntheticsResourceId'] = transaction_payload[:synthetics_resource_id] if transaction_payload[:synthetics_resource_id]
|
114
|
+
sample[:'nr.syntheticsJobId'] = transaction_payload[:synthetics_job_id] if transaction_payload[:synthetics_job_id]
|
115
|
+
sample[:'nr.syntheticsMonitorId'] = transaction_payload[:synthetics_monitor_id] if transaction_payload[:synthetics_monitor_id]
|
116
|
+
end
|
117
|
+
|
118
|
+
def append_cat transaction_payload, sample
|
119
|
+
sample[:'nr.transactionGuid'] = transaction_payload[:guid] if transaction_payload[:guid]
|
120
|
+
sample[:'nr.referringTransactionGuid'] = transaction_payload[:referring_transaction_guid] if transaction_payload[:referring_transaction_guid]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|