tingyun_rpm 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +14 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +3 -0
- data/Guardfile +25 -0
- data/LICENSE.txt +22 -0
- data/README.md +41 -0
- data/cert/cacert.pem +0 -0
- data/lib/ting_yun/agent/agent.rb +128 -0
- data/lib/ting_yun/agent/class_methods.rb +21 -0
- data/lib/ting_yun/agent/collector/base_sampler.rb +2 -0
- data/lib/ting_yun/agent/collector/error_collector/error_trace_array.rb +88 -0
- data/lib/ting_yun/agent/collector/error_collector/noticed_error.rb +129 -0
- data/lib/ting_yun/agent/collector/error_collector.rb +165 -0
- data/lib/ting_yun/agent/collector/middle_ware_collector/cpu_sampler.rb +68 -0
- data/lib/ting_yun/agent/collector/middle_ware_collector/memory_sampler.rb +139 -0
- data/lib/ting_yun/agent/collector/middle_ware_collector/middle_ware.rb +13 -0
- data/lib/ting_yun/agent/collector/middle_ware_collector/sampler.rb +59 -0
- data/lib/ting_yun/agent/collector/middle_ware_collector.rb +80 -0
- data/lib/ting_yun/agent/collector/sql_sampler.rb +299 -0
- data/lib/ting_yun/agent/collector/stats_engine/metric_stats.rb +170 -0
- data/lib/ting_yun/agent/collector/stats_engine/stats_hash.rb +172 -0
- data/lib/ting_yun/agent/collector/stats_engine.rb +28 -0
- data/lib/ting_yun/agent/collector/transaction_sampler/slowest_sample_buffer.rb +25 -0
- data/lib/ting_yun/agent/collector/transaction_sampler/transaction_sample_buffer_base.rb +96 -0
- data/lib/ting_yun/agent/collector/transaction_sampler.rb +226 -0
- data/lib/ting_yun/agent/container_data_manager.rb +94 -0
- data/lib/ting_yun/agent/cross_app/cross_app_monitor.rb +131 -0
- data/lib/ting_yun/agent/cross_app/cross_app_tracing.rb +202 -0
- data/lib/ting_yun/agent/cross_app/inbound_request_monitor.rb +22 -0
- data/lib/ting_yun/agent/database.rb +410 -0
- data/lib/ting_yun/agent/datastore/metric_helper.rb +82 -0
- data/lib/ting_yun/agent/datastore/mongo.rb +44 -0
- data/lib/ting_yun/agent/datastore.rb +33 -0
- data/lib/ting_yun/agent/dispatcher.rb +39 -0
- data/lib/ting_yun/agent/event/event_listener.rb +47 -0
- data/lib/ting_yun/agent/event/event_loop.rb +194 -0
- data/lib/ting_yun/agent/instance_methods/connect.rb +164 -0
- data/lib/ting_yun/agent/instance_methods/container_data_manager.rb +137 -0
- data/lib/ting_yun/agent/instance_methods/handle_errors.rb +71 -0
- data/lib/ting_yun/agent/instance_methods/start.rb +219 -0
- data/lib/ting_yun/agent/instance_methods/start_worker_thread.rb +51 -0
- data/lib/ting_yun/agent/instance_methods.rb +39 -0
- data/lib/ting_yun/agent/method_tracer.rb +256 -0
- data/lib/ting_yun/agent/method_tracer_helpers.rb +85 -0
- data/lib/ting_yun/agent/threading/agent_thread.rb +49 -0
- data/lib/ting_yun/agent/transaction/attributes.rb +22 -0
- data/lib/ting_yun/agent/transaction/request_attributes.rb +126 -0
- data/lib/ting_yun/agent/transaction/trace.rb +125 -0
- data/lib/ting_yun/agent/transaction/trace_node.rb +110 -0
- data/lib/ting_yun/agent/transaction/traced_method_stack.rb +80 -0
- data/lib/ting_yun/agent/transaction/transaction_metrics.rb +51 -0
- data/lib/ting_yun/agent/transaction/transaction_sample_builder.rb +63 -0
- data/lib/ting_yun/agent/transaction/transaction_state.rb +112 -0
- data/lib/ting_yun/agent/transaction.rb +522 -0
- data/lib/ting_yun/agent.rb +207 -0
- data/lib/ting_yun/configuration/default_source.rb +638 -0
- data/lib/ting_yun/configuration/dotted_hash.rb +46 -0
- data/lib/ting_yun/configuration/environment_source.rb +116 -0
- data/lib/ting_yun/configuration/manager.rb +232 -0
- data/lib/ting_yun/configuration/manual_source.rb +14 -0
- data/lib/ting_yun/configuration/server_source.rb +88 -0
- data/lib/ting_yun/configuration/yaml_source.rb +136 -0
- data/lib/ting_yun/configuration.rb +9 -0
- data/lib/ting_yun/environment_report.rb +123 -0
- data/lib/ting_yun/frameworks/class_methods.rb +47 -0
- data/lib/ting_yun/frameworks/external.rb +15 -0
- data/lib/ting_yun/frameworks/instance_methods.rb +120 -0
- data/lib/ting_yun/frameworks/instrumentation.rb +67 -0
- data/lib/ting_yun/frameworks/rails.rb +63 -0
- data/lib/ting_yun/frameworks/rails3.rb +26 -0
- data/lib/ting_yun/frameworks/rails4.rb +14 -0
- data/lib/ting_yun/frameworks/ruby.rb +17 -0
- data/lib/ting_yun/frameworks/sinatra.rb +10 -0
- data/lib/ting_yun/frameworks.rb +34 -0
- data/lib/ting_yun/http/generic_request.rb +8 -0
- data/lib/ting_yun/http/net_http_request.rb +46 -0
- data/lib/ting_yun/instrumentation/active_record.rb +103 -0
- data/lib/ting_yun/instrumentation/middleware_proxy.rb +77 -0
- data/lib/ting_yun/instrumentation/middleware_tracing.rb +84 -0
- data/lib/ting_yun/instrumentation/mongo.rb +103 -0
- data/lib/ting_yun/instrumentation/mongo2.rb +37 -0
- data/lib/ting_yun/instrumentation/mongo_command_log_subscriber.rb +97 -0
- data/lib/ting_yun/instrumentation/moped.rb +95 -0
- data/lib/ting_yun/instrumentation/net.rb +59 -0
- data/lib/ting_yun/instrumentation/rack.rb +109 -0
- data/lib/ting_yun/instrumentation/rails3/action_controller.rb +63 -0
- data/lib/ting_yun/instrumentation/rails3/action_view.rb +115 -0
- data/lib/ting_yun/instrumentation/rails4/action_controller_subscriber.rb +124 -0
- data/lib/ting_yun/instrumentation/rails4/action_view_subscriber.rb +118 -0
- data/lib/ting_yun/instrumentation/rails4/active_record_subscriber.rb +124 -0
- data/lib/ting_yun/instrumentation/rails_middleware.rb +38 -0
- data/lib/ting_yun/instrumentation/redis.rb +70 -0
- data/lib/ting_yun/instrumentation/support/active_record_helper.rb +178 -0
- data/lib/ting_yun/instrumentation/support/controller_instrumentation.rb +54 -0
- data/lib/ting_yun/instrumentation/support/database.rb +38 -0
- data/lib/ting_yun/instrumentation/support/event_formatter.rb +19 -0
- data/lib/ting_yun/instrumentation/support/evented_subscriber.rb +97 -0
- data/lib/ting_yun/instrumentation/support/external_error.rb +52 -0
- data/lib/ting_yun/instrumentation/support/metric_translator.rb +84 -0
- data/lib/ting_yun/instrumentation/support/mongo_formatter.rb +49 -0
- data/lib/ting_yun/instrumentation/support/parameter_filtering.rb +21 -0
- data/lib/ting_yun/instrumentation/support/queue_time.rb +76 -0
- data/lib/ting_yun/instrumentation/support/transaction_namer.rb +68 -0
- data/lib/ting_yun/instrumentation/thrift.rb +329 -0
- data/lib/ting_yun/logger/agent_logger.rb +196 -0
- data/lib/ting_yun/logger/log_once.rb +38 -0
- data/lib/ting_yun/logger/memory_logger.rb +56 -0
- data/lib/ting_yun/logger/null_logger.rb +31 -0
- data/lib/ting_yun/logger/startup_logger.rb +13 -0
- data/lib/ting_yun/logger.rb +8 -0
- data/lib/ting_yun/metrics/metric_data.rb +86 -0
- data/lib/ting_yun/metrics/metric_spec.rb +89 -0
- data/lib/ting_yun/metrics/stats.rb +158 -0
- data/lib/ting_yun/metrics.rb +12 -0
- data/lib/ting_yun/support/coerce.rb +86 -0
- data/lib/ting_yun/support/collector.rb +29 -0
- data/lib/ting_yun/support/exception.rb +79 -0
- data/lib/ting_yun/support/hash_extensions.rb +25 -0
- data/lib/ting_yun/support/helper.rb +54 -0
- data/lib/ting_yun/support/hostname.rb +13 -0
- data/lib/ting_yun/support/http_clients/uri_util.rb +49 -0
- data/lib/ting_yun/support/language_support.rb +155 -0
- data/lib/ting_yun/support/library_detection.rb +129 -0
- data/lib/ting_yun/support/local_environment.rb +185 -0
- data/lib/ting_yun/support/path.rb +13 -0
- data/lib/ting_yun/support/serialize/encodes.rb +61 -0
- data/lib/ting_yun/support/serialize/encoding_normalizer.rb +84 -0
- data/lib/ting_yun/support/serialize/json_marshaller.rb +73 -0
- data/lib/ting_yun/support/serialize/json_wrapper.rb +78 -0
- data/lib/ting_yun/support/serialize/marshaller.rb +69 -0
- data/lib/ting_yun/support/serialize/ok_json.rb +651 -0
- data/lib/ting_yun/support/system_info.rb +206 -0
- data/lib/ting_yun/support/timer_lib.rb +29 -0
- data/lib/ting_yun/support/version_number.rb +70 -0
- data/lib/ting_yun/ting_yun_service/connection.rb +118 -0
- data/lib/ting_yun/ting_yun_service/http.rb +41 -0
- data/lib/ting_yun/ting_yun_service/request.rb +90 -0
- data/lib/ting_yun/ting_yun_service/ssl.rb +45 -0
- data/lib/ting_yun/ting_yun_service/upload_service.rb +149 -0
- data/lib/ting_yun/ting_yun_service.rb +124 -0
- data/lib/ting_yun/version.rb +17 -0
- data/lib/tingyun_rpm.rb +47 -0
- data/tingyun_rpm.gemspec +60 -0
- metadata +415 -0
@@ -0,0 +1,170 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under Ting Yun's license terms.
|
3
|
+
|
4
|
+
module TingYun
|
5
|
+
module Agent
|
6
|
+
module Collector
|
7
|
+
class StatsEngine
|
8
|
+
module MetricStats
|
9
|
+
# Handles methods related to actual Metric collection
|
10
|
+
|
11
|
+
SCOPE_PLACEHOLDER = '__SCOPE__'.freeze
|
12
|
+
|
13
|
+
# Update the unscoped metrics given in metric_names.
|
14
|
+
# metric_names may be either a single name, or an array of names.
|
15
|
+
#
|
16
|
+
# This is an internal method, subject to change at any time. Client apps
|
17
|
+
# and gems should use the public API (TingYun::Agent.record_metric)
|
18
|
+
# instead.
|
19
|
+
#
|
20
|
+
# There are four ways to use this method:
|
21
|
+
#
|
22
|
+
# 1. With a numeric value, it will update the Stats objects associated
|
23
|
+
# with the given metrics by calling record_data_point(value, aux).
|
24
|
+
# aux will be treated in this case as the exclusive time associated
|
25
|
+
# with the call being recorded.
|
26
|
+
#
|
27
|
+
# 2. With a value of :apdex_s, :apdex_t, or :apdex_f, it will treat the
|
28
|
+
# associated stats as an Apdex metric, updating it to reflect the
|
29
|
+
# occurrence of a transaction falling into the given category.
|
30
|
+
# The aux value in this case should be the apdex threshold used in
|
31
|
+
# bucketing the request.
|
32
|
+
#
|
33
|
+
# 3. If a block is given, value and aux will be ignored, and instead the
|
34
|
+
# Stats object associated with each named unscoped metric will be
|
35
|
+
# yielded to the block for customized update logic.
|
36
|
+
#
|
37
|
+
# 4. If value is a Stats instance, it will be merged into the Stats
|
38
|
+
# associated with each named unscoped metric.
|
39
|
+
#
|
40
|
+
# If this method is called during a transaction, the metrics will be
|
41
|
+
# attached to the Transaction, and not merged into the global set until
|
42
|
+
# the end of the transaction.
|
43
|
+
#
|
44
|
+
# Otherwise, the metrics will be recorded directly into the global set
|
45
|
+
# of metrics, under a lock.
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
#
|
49
|
+
|
50
|
+
|
51
|
+
def tl_record_unscoped_metrics(metric_names, value=nil, aux=nil, &blk)
|
52
|
+
state = TingYun::Agent::TransactionState.tl_get
|
53
|
+
record_unscoped_metrics(state, metric_names, value, aux, &blk)
|
54
|
+
end
|
55
|
+
|
56
|
+
def record_unscoped_metrics(state, metric_names, value=nil, aux=nil, &blk)
|
57
|
+
txn = state.current_transaction
|
58
|
+
|
59
|
+
if txn
|
60
|
+
txn.metrics.record_unscoped(metric_names, value, aux, &blk)
|
61
|
+
else
|
62
|
+
specs = coerce_to_metric_spec_array(metric_names, nil)
|
63
|
+
with_stats_lock do
|
64
|
+
@stats_hash.record(specs, value, aux, &blk)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Like tl_record_unscoped_metrics, but records a scoped metric as well.
|
70
|
+
#
|
71
|
+
# This is an internal method, subject to change at any time. Client apps
|
72
|
+
# and gems should use the public API (TingYun::Agent.record_metric)
|
73
|
+
# instead.
|
74
|
+
#
|
75
|
+
# The given scoped_metric will be recoded as both a scoped *and* an
|
76
|
+
# unscoped metric. The summary_metrics will be recorded as unscoped
|
77
|
+
# metrics only.
|
78
|
+
#
|
79
|
+
# If called during a transaction, all metrics will be attached to the
|
80
|
+
# Transaction, and not merged into the global set of metrics until the
|
81
|
+
# end of the transaction.
|
82
|
+
#
|
83
|
+
# If called outside of a transaction, only the *unscoped* metrics will
|
84
|
+
# be recorded, directly into the global set of metrics (under a lock).
|
85
|
+
#
|
86
|
+
# @api private
|
87
|
+
|
88
|
+
def tl_record_scoped_and_unscoped_metrics(scoped_metric, summary_metrics=nil, value=nil, aux=nil, &blk)
|
89
|
+
state = TingYun::Agent::TransactionState.tl_get
|
90
|
+
record_scoped_and_unscoped_metrics(state, scoped_metric, summary_metrics, value, aux, &blk)
|
91
|
+
end
|
92
|
+
|
93
|
+
def record_scoped_and_unscoped_metrics(state, scoped_metric, summary_metrics=nil, value=nil, aux=nil ,&blk)
|
94
|
+
txn = state.current_transaction
|
95
|
+
|
96
|
+
if txn
|
97
|
+
txn.metrics.record_scoped(scoped_metric, value, aux, &blk)
|
98
|
+
txn.metrics.record_unscoped(scoped_metric, value, aux, &blk)
|
99
|
+
if summary_metrics
|
100
|
+
txn.metrics.record_unscoped(summary_metrics, value, aux, &blk)
|
101
|
+
end
|
102
|
+
else
|
103
|
+
specs = coerce_to_metric_spec_array(scoped_metric, nil)
|
104
|
+
if summary_metrics
|
105
|
+
specs.concat(coerce_to_metric_spec_array(summary_metrics, nil))
|
106
|
+
end
|
107
|
+
with_stats_lock do
|
108
|
+
@stats_hash.record(specs, value, aux, &blk)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def coerce_to_metric_spec_array(metric_names_or_specs, scope)
|
114
|
+
specs = []
|
115
|
+
Array(metric_names_or_specs).map do |name_or_spec|
|
116
|
+
case name_or_spec
|
117
|
+
when String
|
118
|
+
specs << TingYun::Metrics::MetricSpec.new(name_or_spec)
|
119
|
+
specs << TingYun::Metrics::MetricSpec.new(name_or_spec, scope) if scope
|
120
|
+
when TingYun::Metrics::MetricSpec
|
121
|
+
specs << name_or_spec
|
122
|
+
end
|
123
|
+
end
|
124
|
+
specs
|
125
|
+
end
|
126
|
+
|
127
|
+
def reset!
|
128
|
+
with_stats_lock do
|
129
|
+
old = @stats_hash
|
130
|
+
@stats_hash = StatsHash.new
|
131
|
+
old
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def harvest!
|
136
|
+
now = Time.now
|
137
|
+
snapshot = reset!
|
138
|
+
snapshot.harvested_at = now
|
139
|
+
snapshot
|
140
|
+
end
|
141
|
+
|
142
|
+
# Renamed to reset!, here for backwards compatibility with 3rd-party
|
143
|
+
# gems (though this really isn't part of the public API).
|
144
|
+
# @deprecated
|
145
|
+
def reset_stats; reset!; end
|
146
|
+
|
147
|
+
# merge data from previous harvests into this stats engine
|
148
|
+
def merge!(other_stats_hash)
|
149
|
+
with_stats_lock do
|
150
|
+
@stats_hash.merge!(other_stats_hash)
|
151
|
+
@stats_hash
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# For use by test code only.
|
156
|
+
def to_h
|
157
|
+
with_stats_lock { @stats_hash.to_h }
|
158
|
+
end
|
159
|
+
|
160
|
+
def merge_transaction_metrics!(txn_metrics, scope)
|
161
|
+
with_stats_lock do
|
162
|
+
@stats_hash.merge_transaction_metrics!(txn_metrics, scope)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
|
4
|
+
# A Hash-like class for storing perfMetrics data.
|
5
|
+
#
|
6
|
+
# Internally, metrics are split into unscoped and scoped collections.
|
7
|
+
#
|
8
|
+
# Unscoped metrics are stored in a Hash, keyed by Strings representing the name
|
9
|
+
# of the metrics.
|
10
|
+
#
|
11
|
+
# Scoped metrics are stored in a Hash where the keys are TingYun::Metrics::MetricSpec
|
12
|
+
# objects (effectively <name, scope> tuples).
|
13
|
+
#
|
14
|
+
# Values in both hashes are TingYun::Metrics::Stats objects.
|
15
|
+
#
|
16
|
+
# Missing keys will be automatically created as empty TingYun::Metrics::Stats
|
17
|
+
# instances, so use has_key? explicitly to check for key existence.
|
18
|
+
#
|
19
|
+
# Note that instances of this class are intended to be append-only with respect
|
20
|
+
# to new metrics. That is, you should not attempt to *remove* an entry after it
|
21
|
+
# has been added, only update it (create a new instance if you need to start
|
22
|
+
# over with a blank slate).
|
23
|
+
#
|
24
|
+
# This class makes no provisions for safe usage from multiple threads, such
|
25
|
+
# measures should be externally provided.
|
26
|
+
|
27
|
+
require 'ting_yun/metrics/stats'
|
28
|
+
require 'ting_yun/metrics/metric_spec'
|
29
|
+
require 'ting_yun/support/exception'
|
30
|
+
|
31
|
+
module TingYun
|
32
|
+
module Agent
|
33
|
+
module Collector
|
34
|
+
class StatsHash
|
35
|
+
|
36
|
+
attr_accessor :started_at, :harvested_at
|
37
|
+
|
38
|
+
def initialize(started_at=Time.now)
|
39
|
+
@started_at = started_at.to_f
|
40
|
+
@scoped = Hash.new { |h, k| h[k] = TingYun::Metrics::Stats.new }
|
41
|
+
@unscoped = Hash.new { |h, k| h[k] = TingYun::Metrics::Stats.new }
|
42
|
+
end
|
43
|
+
|
44
|
+
def marshal_dump
|
45
|
+
[@started_at, Hash[@scoped], Hash[@unscoped]]
|
46
|
+
end
|
47
|
+
|
48
|
+
def marshal_load(data)
|
49
|
+
@started_at = data.shift
|
50
|
+
@scoped = Hash.new { |h, k| h[k] = TingYun::Metrics::Stats.new }
|
51
|
+
@unscoped = Hash.new { |h, k| h[k] = TingYun::Metrics::Stats.new }
|
52
|
+
@scoped.merge!(data.shift)
|
53
|
+
@unscoped.merge!(data.shift)
|
54
|
+
end
|
55
|
+
|
56
|
+
def ==(other)
|
57
|
+
self.to_h == other.to_h
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_h
|
61
|
+
hash = {}
|
62
|
+
@scoped.each { |k, v| hash[k] = v }
|
63
|
+
@unscoped.each { |k, v| hash[TingYun::Metrics::MetricSpec.new(k)] = v }
|
64
|
+
hash
|
65
|
+
end
|
66
|
+
|
67
|
+
def [](key)
|
68
|
+
case key
|
69
|
+
when String
|
70
|
+
@unscoped[key]
|
71
|
+
when TingYun::Metrics::MetricSpec
|
72
|
+
if key.scope.empty?
|
73
|
+
@unscoped[key.name]
|
74
|
+
else
|
75
|
+
@scoped[key]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def each
|
81
|
+
@scoped.each do |k, v|
|
82
|
+
yield k, v
|
83
|
+
end
|
84
|
+
@unscoped.each do |k, v|
|
85
|
+
spec = TingYun::Metrics::MetricSpec.new(k)
|
86
|
+
yield spec, v
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def empty?
|
91
|
+
@unscoped.empty? && @scoped.empty?
|
92
|
+
end
|
93
|
+
|
94
|
+
def size
|
95
|
+
@unscoped.size + @scoped.size
|
96
|
+
end
|
97
|
+
|
98
|
+
def merge!(other)
|
99
|
+
@started_at = other.started_at if other.started_at < @started_at
|
100
|
+
|
101
|
+
other.each do |spec, val|
|
102
|
+
if spec.scope.empty?
|
103
|
+
merge_or_insert(@unscoped, spec.name, val)
|
104
|
+
else
|
105
|
+
merge_or_insert(@scoped, spec, val)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
class StatsHashLookupError < TingYun::Support::Exception::InternalAgentError
|
112
|
+
def initialize(original_error, hash, metric_spec)
|
113
|
+
super("Lookup error in StatsHash: #{original_error.class}: #{original_error.message}. Falling back adding #{metric_spec.inspect}")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def record(metric_specs, value=nil, aux=nil, &blk)
|
118
|
+
Array(metric_specs).each do |metric_spec|
|
119
|
+
if metric_spec.scope.empty?
|
120
|
+
key = metric_spec.name
|
121
|
+
hash = @unscoped
|
122
|
+
else
|
123
|
+
key = metric_spec
|
124
|
+
hash = @scoped
|
125
|
+
end
|
126
|
+
|
127
|
+
begin
|
128
|
+
stats = hash[key]
|
129
|
+
rescue NoMethodError => e
|
130
|
+
stats = handle_stats_lookup_error(key, hash, e)
|
131
|
+
end
|
132
|
+
|
133
|
+
stats.record(value, aux, &blk)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def merge_transaction_metrics!(txn_metrics, scope)
|
138
|
+
|
139
|
+
txn_metrics.each_unscoped do |name, stats|
|
140
|
+
merge_or_insert(@unscoped, name, stats)
|
141
|
+
end
|
142
|
+
txn_metrics.each_scoped do |name, stats|
|
143
|
+
spec = TingYun::Metrics::MetricSpec.new(name, scope)
|
144
|
+
merge_or_insert(@scoped, spec, stats)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def merge_or_insert(target, name, stats)
|
149
|
+
if target.has_key?(name)
|
150
|
+
target[name].merge!(stats)
|
151
|
+
else
|
152
|
+
target[name] = stats
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def handle_stats_lookup_error(key, hash, error)
|
157
|
+
# This only happen in the case of a corrupted default_proc
|
158
|
+
# Side-step it manually, notice the issue, and carry on....
|
159
|
+
::TingYun::Agent.instance.error_collector. \
|
160
|
+
notice_agent_error(StatsHashLookupError.new(error, hash, key))
|
161
|
+
stats = TingYun::Metrics::Stats.new
|
162
|
+
hash[key] = stats
|
163
|
+
# Try to restore the default_proc so we won't continually trip the error
|
164
|
+
if hash.respond_to?(:default_proc=)
|
165
|
+
hash.default_proc = Proc.new { |h, k| h[k] = TingYun::Metrics::Stats.new }
|
166
|
+
end
|
167
|
+
stats
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'ting_yun/agent/collector/stats_engine/stats_hash'
|
4
|
+
require 'ting_yun/agent/collector/stats_engine/metric_stats'
|
5
|
+
|
6
|
+
module TingYun
|
7
|
+
module Agent
|
8
|
+
module Collector
|
9
|
+
# This class handles all the statistics gathering for the agent
|
10
|
+
class StatsEngine
|
11
|
+
|
12
|
+
include MetricStats
|
13
|
+
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@stats_lock = Mutex.new
|
17
|
+
@stats_hash = StatsHash.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# All access to the @stats_hash ivar should be funnelled through this
|
21
|
+
# method to ensure thread-safety.
|
22
|
+
def with_stats_lock
|
23
|
+
@stats_lock.synchronize { yield }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under Ting Yun's license terms.
|
3
|
+
|
4
|
+
require 'ting_yun/agent/collector/transaction_sampler/transaction_sample_buffer_base'
|
5
|
+
module TingYun
|
6
|
+
module Agent
|
7
|
+
module Collector
|
8
|
+
class TransactionSampler
|
9
|
+
class SlowestSampleBuffer < TransactionSampleBufferBase
|
10
|
+
|
11
|
+
CAPACITY = 1
|
12
|
+
|
13
|
+
def capacity
|
14
|
+
CAPACITY
|
15
|
+
end
|
16
|
+
|
17
|
+
def allow_sample?(sample)
|
18
|
+
sample.threshold && sample.duration >= sample.threshold
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under Ting Yun's license terms.
|
3
|
+
|
4
|
+
module TingYun
|
5
|
+
module Agent
|
6
|
+
module Collector
|
7
|
+
class TransactionSampler
|
8
|
+
class TransactionSampleBufferBase
|
9
|
+
|
10
|
+
SINGLE_BUFFER_MAX = 20
|
11
|
+
NO_SAMPLES = [].freeze
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@samples = []
|
15
|
+
end
|
16
|
+
|
17
|
+
#If a buffer needs to modify, override this method.
|
18
|
+
def allow_sample?(sample)
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
#If a buffer needs to modify, override this method.
|
23
|
+
def enabled?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset!
|
28
|
+
@samples = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def harvest_samples
|
32
|
+
@samples
|
33
|
+
ensure
|
34
|
+
reset!
|
35
|
+
end
|
36
|
+
|
37
|
+
def store(sample)
|
38
|
+
return unless enabled?
|
39
|
+
if allow_sample?(sample)
|
40
|
+
add_sample(sample)
|
41
|
+
truncate_samples_if_needed
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def store_previous(previous_samples)
|
46
|
+
return unless enabled?
|
47
|
+
previous_samples.each do |sample|
|
48
|
+
add_sample(sample) if allow_sample?(sample)
|
49
|
+
end
|
50
|
+
truncate_samples_if_needed
|
51
|
+
end
|
52
|
+
|
53
|
+
def truncate_samples_if_needed
|
54
|
+
truncate_samples if full?
|
55
|
+
end
|
56
|
+
|
57
|
+
def full?
|
58
|
+
@samples.length >= max_capacity
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# Capacity is the desired number of samples a buffer will hold. This
|
63
|
+
# can be user dictated via config if a feature wants.
|
64
|
+
#
|
65
|
+
# This value will be forcibly capped by the max_capacity
|
66
|
+
def capacity
|
67
|
+
raise NotImplementedError.new("TransactionSampleBufferBase subclasses must provide a capacity override")
|
68
|
+
end
|
69
|
+
|
70
|
+
def max_capacity
|
71
|
+
capacity > SINGLE_BUFFER_MAX ? SINGLE_BUFFER_MAX : capacity
|
72
|
+
end
|
73
|
+
|
74
|
+
# Our default truncation strategy is to keep max_capacity
|
75
|
+
# worth of the longest samples. Override this method for alternate
|
76
|
+
# behavior.
|
77
|
+
def truncate_samples
|
78
|
+
@samples.sort!{|a,b| a.duration <=> b.duration}
|
79
|
+
@samples.slice!(0..-(max_capacity + 1))
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# If a buffer needs to modify an added sample, override this method.
|
86
|
+
# Bounds checking, allowing samples and truncation belongs elsewhere.
|
87
|
+
def add_sample(sample)
|
88
|
+
@samples << sample
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|