Class: NewRelic::Agent::RequestSampler
- Inherits:
-
Object
- Object
- NewRelic::Agent::RequestSampler
- Includes:
- MonitorMixin, Coerce
- Defined in:
- lib/new_relic/agent/request_sampler.rb
Constant Summary collapse
- DEFAULT_SAMPLE_RATE_MS =
The amount of time between samples, in milliseconds
50
- MIN_SAMPLE_RATE_MS =
The minimum amount of time between samples, in milliseconds
25
- DEFAULT_REPORT_FREQUENCY =
The number of seconds between harvests :TODO: Get this from the agent instead?
60
- MAX_FAILED_REPORT_RETENTION =
Regardless of whether #throttle is successfully called, we will store at most this many harvest-cycles worth of samples total, to avoid unbounded memory growth when there’s a low-level failure talking to the collector.
10
- CONFIG_NAMESPACE =
The namespace and keys of config values
'request_sampler'
- SAMPLE_RATE_KEY =
"#{CONFIG_NAMESPACE}.sample_rate_ms".to_sym
- ENABLED_KEY =
"#{CONFIG_NAMESPACE}.enabled".to_sym
- SAMPLE_TYPE =
The type field of the sample
'Transaction'
- TYPE_KEY =
Strings for static keys of the sample structure
'type'
- TIMESTAMP_KEY =
'timestamp'
- NAME_KEY =
'name'
- DURATION_KEY =
'duration'
Instance Attribute Summary collapse
-
#last_sample_taken ⇒ Object
readonly
The Time when the last sample was kept.
-
#normal_sample_rate_ms ⇒ Object
readonly
The sample rate, in milliseconds between samples, that the sampler uses under normal circumstances.
-
#sample_rate_ms ⇒ Object
readonly
The current sample rate, which may be different from the #normal_sample_rate_ms if the sampler is throttled.
Instance Method Summary collapse
-
#<<(sample) ⇒ Object
Add a datapoint to the sampler if a sample is due.
-
#initialize(event_listener) ⇒ RequestSampler
constructor
Create a new RequestSampler that will keep samples added to it every
sample_rate_ms
milliseconds. -
#on_transaction_finished(metric, duration, options = {}) ⇒ Object
Event handler for the :transaction_finished event.
- #record_sampling_rate(request_count, sample_count) ⇒ Object
-
#register_config_callbacks ⇒ Object
:group: Event handlers.
-
#reset ⇒ Object
Clear any existing samples and reset the last sample time.
-
#samples ⇒ Object
Fetch a copy of the sampler’s gathered samples.
-
#throttle(resolution = nil) ⇒ Object
Downsample the gathered data and reduce the sampling rate to conserve memory.
Methods included from Coerce
#float, #int, #log_failure, #string
Constructor Details
#initialize(event_listener) ⇒ RequestSampler
Create a new RequestSampler that will keep samples added to it every sample_rate_ms
milliseconds.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/new_relic/agent/request_sampler.rb', line 47 def initialize( event_listener ) super() @enabled = false @sample_rate_ms = DEFAULT_SAMPLE_RATE_MS @normal_sample_rate_ms = @sample_rate_ms @last_sample_taken = nil @samples = [] @notified_max_samples = false @sample_count = 0 @request_count = 0 @sample_count_total = 0 @request_count_total = 0 event_listener.subscribe( :transaction_finished, &method(:on_transaction_finished) ) self.register_config_callbacks end |
Instance Attribute Details
#last_sample_taken ⇒ Object (readonly)
The Time when the last sample was kept
80 81 82 |
# File 'lib/new_relic/agent/request_sampler.rb', line 80 def last_sample_taken @last_sample_taken end |
#normal_sample_rate_ms ⇒ Object (readonly)
The sample rate, in milliseconds between samples, that the sampler uses under normal circumstances
73 74 75 |
# File 'lib/new_relic/agent/request_sampler.rb', line 73 def normal_sample_rate_ms @normal_sample_rate_ms end |
#sample_rate_ms ⇒ Object (readonly)
The current sample rate, which may be different from the #normal_sample_rate_ms if the sampler is throttled.
77 78 79 |
# File 'lib/new_relic/agent/request_sampler.rb', line 77 def sample_rate_ms @sample_rate_ms end |
Instance Method Details
#<<(sample) ⇒ Object
Add a datapoint to the sampler if a sample is due. The sample
should be of the form:
{
'name' => '<transaction/metric name>',
'duration' => <duration in seconds as a Float>,
}
This method is synchronized.
173 174 175 176 177 178 179 180 |
# File 'lib/new_relic/agent/request_sampler.rb', line 173 def <<( sample ) self.synchronize do @request_count += 1 self.add_sample( sample ) if should_sample? end return self end |
#on_transaction_finished(metric, duration, options = {}) ⇒ Object
Event handler for the :transaction_finished event.
149 150 151 152 153 154 155 |
# File 'lib/new_relic/agent/request_sampler.rb', line 149 def on_transaction_finished( metric, duration, ={} ) return unless @enabled self << { NAME_KEY => string(metric), DURATION_KEY => float(duration) }.merge() end |
#record_sampling_rate(request_count, sample_count) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/new_relic/agent/request_sampler.rb', line 109 def record_sampling_rate(request_count, sample_count) @request_count_total += request_count @sample_count_total += sample_count NewRelic::Agent.logger.debug("Sampled #{sample_count} / #{request_count} (%.1f %%) requests this cycle" % (sample_count.to_f / request_count * 100.0)) NewRelic::Agent.logger.debug("Sampled #{@sample_count_total} / #{@request_count_total} (%.1f %%) requests since startup" % (@sample_count_total.to_f / @request_count_total * 100.0)) engine = NewRelic::Agent.instance.stats_engine engine.record_supportability_metric_count("RequestSampler/requests", request_count) engine.record_supportability_metric_count("RequestSampler/samples", sample_count) end |
#register_config_callbacks ⇒ Object
:group: Event handlers
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/new_relic/agent/request_sampler.rb', line 125 def register_config_callbacks NewRelic::Agent.config.register_callback(SAMPLE_RATE_KEY) do |rate_ms| NewRelic::Agent.logger.debug "RequestSampler sample rate to %dms" % [ rate_ms ] if rate_ms < MIN_SAMPLE_RATE_MS NewRelic::Agent.logger.warn " limiting RequestSampler frequency to %dms (was %dms)" % [ MIN_SAMPLE_RATE_MS, rate_ms ] rate_ms = MIN_SAMPLE_RATE_MS end @normal_sample_rate_ms = rate_ms @max_samples = calculate_max_samples NewRelic::Agent.logger.debug "RequestSampler max_samples set to #{@max_samples}" self.reset end NewRelic::Agent.config.register_callback(ENABLED_KEY) do |enabled| NewRelic::Agent.logger.info "%sabling the Request Sampler." % [ enabled ? 'En' : 'Dis' ] @enabled = enabled end end |
#reset ⇒ Object
Clear any existing samples and reset the last sample time. (Synchronized)
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/new_relic/agent/request_sampler.rb', line 90 def reset NewRelic::Agent.logger.debug "Resetting RequestSampler" request_count = nil sample_count = nil self.synchronize do sample_count = @samples.size request_count = @request_count @request_count = 0 @samples.clear @sample_rate_ms = @normal_sample_rate_ms @last_sample_taken = Time.now @notified_max_samples = false end record_sampling_rate(request_count, sample_count) if @enabled end |
#samples ⇒ Object
Fetch a copy of the sampler’s gathered samples. (Synchronized)
84 85 86 |
# File 'lib/new_relic/agent/request_sampler.rb', line 84 def samples return self.synchronize { @samples.dup } end |
#throttle(resolution = nil) ⇒ Object
Downsample the gathered data and reduce the sampling rate to conserve memory. The amount the sampler is throttled is proportional to resolution
, which defaults to the number of normal report periods which have elapsed. E.g., if three sessions with the agent have failed, the sampler downsamples its data to include one out of even three samples, and only samples a third of the time it normally would.
This method is synchronized.
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/new_relic/agent/request_sampler.rb', line 190 def throttle( resolution=nil ) # Only throttle if the sampler was running self.synchronize do if @last_sample_taken && !@samples.empty? resolution ||= (Time.now - @last_sample_taken) / DEFAULT_REPORT_FREQUENCY @sample_rate_ms = @normal_sample_rate_ms * resolution self.downsample_data( resolution ) end end if resolution NewRelic::Agent.logger.debug " resolution is now: %d -> 1 sample every %dms" % [ resolution, @sample_rate_ms ] end end |