tingyun_rpm 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +14 -0
  4. data/.travis.yml +4 -0
  5. data/CODE_OF_CONDUCT.md +13 -0
  6. data/Gemfile +3 -0
  7. data/Guardfile +25 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +41 -0
  10. data/cert/cacert.pem +0 -0
  11. data/lib/ting_yun/agent/agent.rb +128 -0
  12. data/lib/ting_yun/agent/class_methods.rb +21 -0
  13. data/lib/ting_yun/agent/collector/base_sampler.rb +2 -0
  14. data/lib/ting_yun/agent/collector/error_collector/error_trace_array.rb +88 -0
  15. data/lib/ting_yun/agent/collector/error_collector/noticed_error.rb +129 -0
  16. data/lib/ting_yun/agent/collector/error_collector.rb +165 -0
  17. data/lib/ting_yun/agent/collector/middle_ware_collector/cpu_sampler.rb +68 -0
  18. data/lib/ting_yun/agent/collector/middle_ware_collector/memory_sampler.rb +139 -0
  19. data/lib/ting_yun/agent/collector/middle_ware_collector/middle_ware.rb +13 -0
  20. data/lib/ting_yun/agent/collector/middle_ware_collector/sampler.rb +59 -0
  21. data/lib/ting_yun/agent/collector/middle_ware_collector.rb +80 -0
  22. data/lib/ting_yun/agent/collector/sql_sampler.rb +299 -0
  23. data/lib/ting_yun/agent/collector/stats_engine/metric_stats.rb +170 -0
  24. data/lib/ting_yun/agent/collector/stats_engine/stats_hash.rb +172 -0
  25. data/lib/ting_yun/agent/collector/stats_engine.rb +28 -0
  26. data/lib/ting_yun/agent/collector/transaction_sampler/slowest_sample_buffer.rb +25 -0
  27. data/lib/ting_yun/agent/collector/transaction_sampler/transaction_sample_buffer_base.rb +96 -0
  28. data/lib/ting_yun/agent/collector/transaction_sampler.rb +226 -0
  29. data/lib/ting_yun/agent/container_data_manager.rb +94 -0
  30. data/lib/ting_yun/agent/cross_app/cross_app_monitor.rb +131 -0
  31. data/lib/ting_yun/agent/cross_app/cross_app_tracing.rb +202 -0
  32. data/lib/ting_yun/agent/cross_app/inbound_request_monitor.rb +22 -0
  33. data/lib/ting_yun/agent/database.rb +410 -0
  34. data/lib/ting_yun/agent/datastore/metric_helper.rb +82 -0
  35. data/lib/ting_yun/agent/datastore/mongo.rb +44 -0
  36. data/lib/ting_yun/agent/datastore.rb +33 -0
  37. data/lib/ting_yun/agent/dispatcher.rb +39 -0
  38. data/lib/ting_yun/agent/event/event_listener.rb +47 -0
  39. data/lib/ting_yun/agent/event/event_loop.rb +194 -0
  40. data/lib/ting_yun/agent/instance_methods/connect.rb +164 -0
  41. data/lib/ting_yun/agent/instance_methods/container_data_manager.rb +137 -0
  42. data/lib/ting_yun/agent/instance_methods/handle_errors.rb +71 -0
  43. data/lib/ting_yun/agent/instance_methods/start.rb +219 -0
  44. data/lib/ting_yun/agent/instance_methods/start_worker_thread.rb +51 -0
  45. data/lib/ting_yun/agent/instance_methods.rb +39 -0
  46. data/lib/ting_yun/agent/method_tracer.rb +256 -0
  47. data/lib/ting_yun/agent/method_tracer_helpers.rb +85 -0
  48. data/lib/ting_yun/agent/threading/agent_thread.rb +49 -0
  49. data/lib/ting_yun/agent/transaction/attributes.rb +22 -0
  50. data/lib/ting_yun/agent/transaction/request_attributes.rb +126 -0
  51. data/lib/ting_yun/agent/transaction/trace.rb +125 -0
  52. data/lib/ting_yun/agent/transaction/trace_node.rb +110 -0
  53. data/lib/ting_yun/agent/transaction/traced_method_stack.rb +80 -0
  54. data/lib/ting_yun/agent/transaction/transaction_metrics.rb +51 -0
  55. data/lib/ting_yun/agent/transaction/transaction_sample_builder.rb +63 -0
  56. data/lib/ting_yun/agent/transaction/transaction_state.rb +112 -0
  57. data/lib/ting_yun/agent/transaction.rb +522 -0
  58. data/lib/ting_yun/agent.rb +207 -0
  59. data/lib/ting_yun/configuration/default_source.rb +638 -0
  60. data/lib/ting_yun/configuration/dotted_hash.rb +46 -0
  61. data/lib/ting_yun/configuration/environment_source.rb +116 -0
  62. data/lib/ting_yun/configuration/manager.rb +232 -0
  63. data/lib/ting_yun/configuration/manual_source.rb +14 -0
  64. data/lib/ting_yun/configuration/server_source.rb +88 -0
  65. data/lib/ting_yun/configuration/yaml_source.rb +136 -0
  66. data/lib/ting_yun/configuration.rb +9 -0
  67. data/lib/ting_yun/environment_report.rb +123 -0
  68. data/lib/ting_yun/frameworks/class_methods.rb +47 -0
  69. data/lib/ting_yun/frameworks/external.rb +15 -0
  70. data/lib/ting_yun/frameworks/instance_methods.rb +120 -0
  71. data/lib/ting_yun/frameworks/instrumentation.rb +67 -0
  72. data/lib/ting_yun/frameworks/rails.rb +63 -0
  73. data/lib/ting_yun/frameworks/rails3.rb +26 -0
  74. data/lib/ting_yun/frameworks/rails4.rb +14 -0
  75. data/lib/ting_yun/frameworks/ruby.rb +17 -0
  76. data/lib/ting_yun/frameworks/sinatra.rb +10 -0
  77. data/lib/ting_yun/frameworks.rb +34 -0
  78. data/lib/ting_yun/http/generic_request.rb +8 -0
  79. data/lib/ting_yun/http/net_http_request.rb +46 -0
  80. data/lib/ting_yun/instrumentation/active_record.rb +103 -0
  81. data/lib/ting_yun/instrumentation/middleware_proxy.rb +77 -0
  82. data/lib/ting_yun/instrumentation/middleware_tracing.rb +84 -0
  83. data/lib/ting_yun/instrumentation/mongo.rb +103 -0
  84. data/lib/ting_yun/instrumentation/mongo2.rb +37 -0
  85. data/lib/ting_yun/instrumentation/mongo_command_log_subscriber.rb +97 -0
  86. data/lib/ting_yun/instrumentation/moped.rb +95 -0
  87. data/lib/ting_yun/instrumentation/net.rb +59 -0
  88. data/lib/ting_yun/instrumentation/rack.rb +109 -0
  89. data/lib/ting_yun/instrumentation/rails3/action_controller.rb +63 -0
  90. data/lib/ting_yun/instrumentation/rails3/action_view.rb +115 -0
  91. data/lib/ting_yun/instrumentation/rails4/action_controller_subscriber.rb +124 -0
  92. data/lib/ting_yun/instrumentation/rails4/action_view_subscriber.rb +118 -0
  93. data/lib/ting_yun/instrumentation/rails4/active_record_subscriber.rb +124 -0
  94. data/lib/ting_yun/instrumentation/rails_middleware.rb +38 -0
  95. data/lib/ting_yun/instrumentation/redis.rb +70 -0
  96. data/lib/ting_yun/instrumentation/support/active_record_helper.rb +178 -0
  97. data/lib/ting_yun/instrumentation/support/controller_instrumentation.rb +54 -0
  98. data/lib/ting_yun/instrumentation/support/database.rb +38 -0
  99. data/lib/ting_yun/instrumentation/support/event_formatter.rb +19 -0
  100. data/lib/ting_yun/instrumentation/support/evented_subscriber.rb +97 -0
  101. data/lib/ting_yun/instrumentation/support/external_error.rb +52 -0
  102. data/lib/ting_yun/instrumentation/support/metric_translator.rb +84 -0
  103. data/lib/ting_yun/instrumentation/support/mongo_formatter.rb +49 -0
  104. data/lib/ting_yun/instrumentation/support/parameter_filtering.rb +21 -0
  105. data/lib/ting_yun/instrumentation/support/queue_time.rb +76 -0
  106. data/lib/ting_yun/instrumentation/support/transaction_namer.rb +68 -0
  107. data/lib/ting_yun/instrumentation/thrift.rb +329 -0
  108. data/lib/ting_yun/logger/agent_logger.rb +196 -0
  109. data/lib/ting_yun/logger/log_once.rb +38 -0
  110. data/lib/ting_yun/logger/memory_logger.rb +56 -0
  111. data/lib/ting_yun/logger/null_logger.rb +31 -0
  112. data/lib/ting_yun/logger/startup_logger.rb +13 -0
  113. data/lib/ting_yun/logger.rb +8 -0
  114. data/lib/ting_yun/metrics/metric_data.rb +86 -0
  115. data/lib/ting_yun/metrics/metric_spec.rb +89 -0
  116. data/lib/ting_yun/metrics/stats.rb +158 -0
  117. data/lib/ting_yun/metrics.rb +12 -0
  118. data/lib/ting_yun/support/coerce.rb +86 -0
  119. data/lib/ting_yun/support/collector.rb +29 -0
  120. data/lib/ting_yun/support/exception.rb +79 -0
  121. data/lib/ting_yun/support/hash_extensions.rb +25 -0
  122. data/lib/ting_yun/support/helper.rb +54 -0
  123. data/lib/ting_yun/support/hostname.rb +13 -0
  124. data/lib/ting_yun/support/http_clients/uri_util.rb +49 -0
  125. data/lib/ting_yun/support/language_support.rb +155 -0
  126. data/lib/ting_yun/support/library_detection.rb +129 -0
  127. data/lib/ting_yun/support/local_environment.rb +185 -0
  128. data/lib/ting_yun/support/path.rb +13 -0
  129. data/lib/ting_yun/support/serialize/encodes.rb +61 -0
  130. data/lib/ting_yun/support/serialize/encoding_normalizer.rb +84 -0
  131. data/lib/ting_yun/support/serialize/json_marshaller.rb +73 -0
  132. data/lib/ting_yun/support/serialize/json_wrapper.rb +78 -0
  133. data/lib/ting_yun/support/serialize/marshaller.rb +69 -0
  134. data/lib/ting_yun/support/serialize/ok_json.rb +651 -0
  135. data/lib/ting_yun/support/system_info.rb +206 -0
  136. data/lib/ting_yun/support/timer_lib.rb +29 -0
  137. data/lib/ting_yun/support/version_number.rb +70 -0
  138. data/lib/ting_yun/ting_yun_service/connection.rb +118 -0
  139. data/lib/ting_yun/ting_yun_service/http.rb +41 -0
  140. data/lib/ting_yun/ting_yun_service/request.rb +90 -0
  141. data/lib/ting_yun/ting_yun_service/ssl.rb +45 -0
  142. data/lib/ting_yun/ting_yun_service/upload_service.rb +149 -0
  143. data/lib/ting_yun/ting_yun_service.rb +124 -0
  144. data/lib/ting_yun/version.rb +17 -0
  145. data/lib/tingyun_rpm.rb +47 -0
  146. data/tingyun_rpm.gemspec +60 -0
  147. metadata +415 -0
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+
3
+ # Base class for startup logging and testing in multiverse
4
+ require 'ting_yun/logger/log_once'
5
+
6
+ module TingYun
7
+ module Logger
8
+ class MemoryLogger
9
+ include LogOnce
10
+
11
+ def initialize
12
+ @already_logged_lock = Mutex.new
13
+ clear_already_logged
14
+
15
+ @messages = []
16
+ end
17
+
18
+ def is_startup_logger?
19
+ true
20
+ end
21
+
22
+ attr_accessor :messages, :level, :log_formatter
23
+
24
+ def fatal(*msgs, &blk)
25
+ messages << [:fatal, msgs, blk]
26
+ end
27
+
28
+ def error(*msgs, &blk)
29
+ messages << [:error, msgs, blk]
30
+ end
31
+
32
+ def warn(*msgs, &blk)
33
+ messages << [:warn, msgs, blk]
34
+ end
35
+
36
+ def info(*msgs, &blk)
37
+ messages << [:info, msgs, blk]
38
+ end
39
+
40
+ def debug(*msgs, &blk)
41
+ messages << [:debug, msgs, blk]
42
+ end
43
+
44
+ def log_exception(level, e, backtrace_level=level)
45
+ messages << [:log_exception, [level, e, backtrace_level]]
46
+ end
47
+
48
+ def dump(logger)
49
+ messages.each do |(method, args, blk)|
50
+ logger.send(method, *args, &blk)
51
+ end
52
+ messages.clear
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ module TingYun
4
+ module Logger
5
+ class NullLogger
6
+ def fatal(*args)
7
+ ;
8
+ end
9
+
10
+ def error(*args)
11
+ ;
12
+ end
13
+
14
+ def warn(*args)
15
+ ;
16
+ end
17
+
18
+ def info(*args)
19
+ ;
20
+ end
21
+
22
+ def debug(*args)
23
+ ;
24
+ end
25
+
26
+ def method_missing(method, *args, &blk)
27
+ nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+ require 'ting_yun/logger/memory_logger'
3
+ require 'singleton'
4
+
5
+ module TingYun
6
+ module Logger
7
+ # In an effort to not lose messages during startup, we trap them in memory
8
+ # The real logger will then dump its contents out when it arrives.
9
+ class StartupLogger < MemoryLogger
10
+ include Singleton
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+ module TingYun
5
+ module Logger
6
+
7
+ end
8
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+ require 'ting_yun/support/coerce'
5
+
6
+ module TingYun
7
+ module Metrics
8
+ class MetricData
9
+
10
+ # nil, or a TingYun::Metrics::MetricSpec object if we have no cached ID
11
+ attr_reader :metric_spec
12
+ # nil or a cached integer ID for the metric from the collector.
13
+ attr_accessor :metric_id
14
+ # the actual statistics object
15
+ attr_accessor :stats
16
+
17
+ def initialize(metric_spec, stats, metric_id)
18
+ @metric_spec = metric_spec
19
+ self.stats = stats
20
+ self.metric_id = metric_id
21
+ end
22
+
23
+ def eql?(o)
24
+ (metric_spec.eql? o.metric_spec) && (stats.eql? o.stats)
25
+ end
26
+
27
+ def hash
28
+ metric_spec.hash ^ stats.hash
29
+ end
30
+
31
+ # Serialize with all attributes, but if the metric id is not nil, then don't send the metric spec
32
+ def to_json(*a)
33
+ %Q[{"metric_spec":#{metric_id ? 'null' : metric_spec.to_json},"stats":{"total_exclusive_time":#{stats.total_exclusive_time},"min_call_time":#{stats.min_call_time},"call_count":#{stats.call_count},"sum_of_squares":#{stats.sum_of_squares},"total_call_time":#{stats.total_call_time},"max_call_time":#{stats.max_call_time}},"metric_id":#{metric_id ? metric_id : 'null'}}]
34
+ end
35
+
36
+ def to_s
37
+ if metric_spec
38
+ "#{metric_spec.name}(#{metric_spec.scope}): #{stats}"
39
+ else
40
+ "#{metric_id}: #{stats}"
41
+ end
42
+ end
43
+
44
+ def inspect
45
+ "#<MetricData metric_spec:#{metric_spec.inspect}, stats:#{stats.inspect}, metric_id:#{metric_id.inspect}>"
46
+ end
47
+
48
+ include TingYun::Support::Coerce
49
+
50
+ def to_collector_array(encoder=nil)
51
+ stat_key = metric_id || stats_has_parent?
52
+ [ stat_key,metrics(stat_key)]
53
+ end
54
+
55
+ def stats_has_parent?
56
+ hash = { 'name' => metric_spec.name }
57
+ hash['calleeId'] = metric_spec.calleeId unless metric_spec.calleeId.nil?
58
+ hash['calleeName'] = metric_spec.calleeName unless metric_spec.calleeName.nil?
59
+ unless metric_spec.scope.empty?
60
+ hash['parent'] = metric_spec.scope
61
+ end
62
+
63
+ return hash
64
+ end
65
+
66
+ def metrics(stat_key)
67
+
68
+ metrics = []
69
+
70
+ metrics << int(stats.call_count, stat_key)
71
+ if stats.max_call_time != 0.0 #apedx
72
+ metrics << float(stats.total_call_time.round, stat_key)
73
+ metrics << float(stats.total_exclusive_time.round, stat_key)
74
+ metrics << float(stats.max_call_time.round, stat_key)
75
+ end
76
+
77
+ if stats.min_call_time !=0.0 #
78
+ metrics << float(stats.min_call_time.round, stat_key)
79
+ metrics << float(stats.sum_of_squares.round, stat_key)
80
+ end
81
+
82
+ metrics
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,89 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+
5
+
6
+ # this struct uniquely defines a metric, optionally inside
7
+ # the call scope of another metric
8
+ module TingYun
9
+ module Metrics
10
+ class MetricSpec
11
+ attr_accessor :name, :scope, :calleeId, :calleeName
12
+
13
+ # the maximum length of a metric name or metric scope
14
+ MAX_LENGTH = 255
15
+ LENGTH_RANGE = (0...MAX_LENGTH)
16
+ EMPTY_SCOPE = ''.freeze
17
+
18
+ def initialize(metric_name='', metric_scope=nil)
19
+ if metric_name.to_s.length > MAX_LENGTH
20
+ @name = metric_name.to_s[LENGTH_RANGE]
21
+ else
22
+ @name = metric_name.to_s
23
+ end
24
+
25
+ if metric_scope
26
+ if metric_scope.to_s.length > MAX_LENGTH
27
+ @scope = metric_scope.to_s[LENGTH_RANGE]
28
+ else
29
+ @scope = metric_scope.to_s
30
+ end
31
+ else
32
+ @scope = EMPTY_SCOPE
33
+ end
34
+ end
35
+
36
+ def ==(o)
37
+ self.eql?(o)
38
+ end
39
+
40
+ def eql? o
41
+ @name == o.name && @scope == o.scope
42
+ end
43
+
44
+ def hash
45
+ @name.hash ^ @scope.hash
46
+ end
47
+
48
+ # return a new metric spec if the given regex
49
+ # matches the name or scope.
50
+ def sub(pattern, replacement, apply_to_scope = true)
51
+ ::TingYun::Agent.logger.warn("The sub method on metric specs is deprecated") rescue nil
52
+ return nil if name !~ pattern &&
53
+ (!apply_to_scope || scope.nil? || scope !~ pattern)
54
+ new_name = name.sub(pattern, replacement)[LENGTH_RANGE]
55
+
56
+ if apply_to_scope
57
+ new_scope = (scope && scope.sub(pattern, replacement)[LENGTH_RANGE])
58
+ else
59
+ new_scope = scope
60
+ end
61
+
62
+ self.class.new new_name, new_scope
63
+ end
64
+
65
+ def to_s
66
+ return name if scope.empty?
67
+ "#{name}:#{scope}"
68
+ end
69
+
70
+ def inspect
71
+ "#<TingYun::Metrics::MetricSpec '#{name}':'#{scope}'>"
72
+ end
73
+
74
+ def to_json(*a)
75
+ {'name' => name,
76
+ 'scope' => scope}.to_json(*a)
77
+ end
78
+
79
+ def <=>(o)
80
+ namecmp = self.name <=> o.name
81
+ return namecmp if namecmp != 0
82
+ return (self.scope || '') <=> (o.scope || '')
83
+ end
84
+
85
+
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,158 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+ module TingYun
5
+ module Metrics
6
+ class Stats
7
+ attr_accessor :call_count
8
+ attr_accessor :min_call_time
9
+ attr_accessor :max_call_time
10
+ attr_accessor :total_call_time
11
+ attr_accessor :total_exclusive_time
12
+ attr_accessor :sum_of_squares
13
+
14
+
15
+ def self.create_from_hash(hash_value)
16
+ stats = Stats.new
17
+ stats.call_count = hash_value[:count] if hash_value[:count]
18
+ stats.total_call_time = hash_value[:total] if hash_value[:total]
19
+ stats.total_exclusive_time = hash_value[:total] if hash_value[:total]
20
+ stats.min_call_time = hash_value[:min] if hash_value[:min]
21
+ stats.max_call_time = hash_value[:max] if hash_value[:max]
22
+ stats.sum_of_squares = hash_value[:sum_of_squares] if hash_value[:sum_of_squares]
23
+ stats
24
+ end
25
+
26
+
27
+ def initialize
28
+ reset
29
+ end
30
+
31
+ def reset
32
+ @call_count = 0
33
+ @total_call_time = 0.0
34
+ @total_exclusive_time = 0.0
35
+ @min_call_time = 0.0
36
+ @max_call_time = 0.0
37
+ @sum_of_squares = 0.0
38
+ end
39
+
40
+ alias_method :apdex_s, :call_count
41
+ alias_method :apdex_t, :total_call_time
42
+ alias_method :apdex_f, :total_exclusive_time
43
+
44
+
45
+ def is_reset?
46
+ call_count == 0 && total_call_time == 0.0 && total_exclusive_time == 0.0
47
+ end
48
+
49
+ #self不变
50
+ def merge(other_stats)
51
+ stats = self.clone
52
+ stats.merge!(other_stats)
53
+ end
54
+
55
+ #self变化
56
+ def merge!(other)
57
+ @min_call_time = other.min_call_time if min_time_less?(other)
58
+ @max_call_time = other.max_call_time if max_time?(other)
59
+ @total_call_time += other.total_call_time
60
+ @total_exclusive_time += other.total_exclusive_time
61
+ @sum_of_squares += other.sum_of_squares
62
+ @call_count += other.call_count
63
+ self
64
+ end
65
+
66
+ def to_s
67
+ "[#{'%2i' % call_count.to_i} calls #{'%.4f' % total_call_time.to_f}s / #{'%.4f' % total_exclusive_time.to_f}s ex]"
68
+ end
69
+
70
+ def to_json(*_)
71
+ {
72
+ 'call_count' => call_count.to_i,
73
+ 'min_call_time' => min_call_time.to_f,
74
+ 'max_call_time' => max_call_time.to_f,
75
+ 'total_call_time' => total_call_time.to_f,
76
+ 'total_exclusive_time' => total_exclusive_time.to_f,
77
+ 'sum_of_squares' => sum_of_squares.to_f
78
+ }.to_json(*_)
79
+ end
80
+
81
+ def record(value=nil, aux=nil, &blk)
82
+ if blk
83
+ yield self
84
+ else
85
+ case value
86
+ when Numeric
87
+ aux ||= value
88
+ self.record_data_point(value, aux)
89
+ when :apdex_s, :apdex_t, :apdex_f
90
+ self.record_apdex(value, aux)
91
+ when TingYun::Metrics::Stats
92
+ self.merge!(value)
93
+ end
94
+ end
95
+ end
96
+
97
+ def record_apdex(bucket, apdex_t)
98
+ case bucket
99
+ when :apdex_s then @call_count += 1
100
+ when :apdex_t then @total_call_time += 1
101
+ when :apdex_f then @total_exclusive_time += 1
102
+ end
103
+ if apdex_t
104
+ @max_call_time = apdex_t
105
+ else
106
+ ::TingYun::Agent.logger.warn("Attempted to set apdex_t to #{apdex_t.inspect}, backtrace = #{caller.join("\n")}")
107
+ end
108
+ end
109
+
110
+
111
+
112
+ # record a single data point into the statistical gatherer. The gatherer
113
+ # will aggregate all data points collected over a specified period and upload
114
+ # its data to the TingYun server
115
+ def record_data_point(value, exclusive_time = value)
116
+ @call_count += 1
117
+ @total_call_time += value
118
+ @min_call_time = value if value < @min_call_time || @call_count == 1
119
+ @max_call_time = value if value > @max_call_time
120
+ @total_exclusive_time += exclusive_time
121
+
122
+ @sum_of_squares += (value * value)
123
+ self
124
+ end
125
+
126
+ alias trace_call record_data_point
127
+
128
+ # increments the call_count by one
129
+ def increment_count(value = 1)
130
+ @call_count += value
131
+ end
132
+
133
+ def ==(other)
134
+ other.class == self.class &&
135
+ (
136
+ @min_call_time == other.min_call_time &&
137
+ @max_call_time == other.max_call_time &&
138
+ @total_call_time == other.total_call_time &&
139
+ @total_exclusive_time == other.total_exclusive_time &&
140
+ @sum_of_squares == other.sum_of_squares &&
141
+ @call_count == other.call_count
142
+ )
143
+ end
144
+
145
+
146
+ protected
147
+
148
+ def min_time_less?(other)
149
+ (other.min_call_time < min_call_time && other.call_count > 0) || call_count == 0
150
+ end
151
+
152
+ def max_time?(other)
153
+ other.max_call_time > max_call_time
154
+ end
155
+
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+ module TingYun
5
+ module Metrics
6
+ CONTROLLER = "Controller"
7
+ DISPATCHER = "HttpDispatcher"
8
+ ACTIVE_RECORD = "ActiveRecord"
9
+ USER_TIME = "CPU/User Time"
10
+ MEMORY = "Memory/Physical"
11
+ end
12
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+ require 'ting_yun/agent'
3
+
4
+ module TingYun
5
+ module Support
6
+ # We really don't want to send bad values to the collector, and it doesn't
7
+ # accept types like Rational that have occasionally slipped into our data.
8
+ #
9
+ # These methods are intended to safely coerce things into the form we want,
10
+ # to provide documentation of expected types on to_collector_array methods,
11
+ # and to log failures if totally invalid data gets into outgoing data
12
+ module Coerce
13
+ module_function
14
+
15
+ def int(value, context=nil)
16
+ Integer(value)
17
+ rescue => error
18
+ log_failure(value, Integer, context, error)
19
+ 0
20
+ end
21
+
22
+ def int_or_nil(value, context=nil)
23
+ return nil if value.nil?
24
+ Integer(value)
25
+ rescue => error
26
+ log_failure(value, Integer, context, error)
27
+ nil
28
+ end
29
+
30
+ def float(value, context=nil)
31
+ result = Float(value)
32
+ raise "Value #{result.inspect} is not finite." unless result.finite?
33
+ result
34
+ rescue => error
35
+ log_failure(value, Float, context, error)
36
+ 0.0
37
+ end
38
+
39
+ def string(value, context=nil)
40
+ return value if value.nil?
41
+ String(value)
42
+ rescue => error
43
+ log_failure(value.class, String, context, error)
44
+ ""
45
+ end
46
+
47
+ # Convert a hash into a format acceptable to be included with Transaction
48
+ # event data.
49
+ #
50
+ # We accept a hash and will return a new hash where all of the keys
51
+ # have been converted to strings. As values we only allow Strings,
52
+ # Floats, Integers. Symbols are also allowed but are converted to strings.
53
+ # Any values of other type (e.g. Hash, Array, any other class) are
54
+ # discarded. Their keys are also removed from the results hash.
55
+ def event_params(value, context=nil)
56
+ unless value.is_a? Hash
57
+ raise ArgumentError, "Expected Hash but got #{value.class}"
58
+ end
59
+ value.inject({}) do |memo, (key, val)|
60
+ case val
61
+ when String, Integer, TrueClass, FalseClass
62
+ memo[key.to_s] = val
63
+ when Float
64
+ if val.finite?
65
+ memo[key.to_s] = val
66
+ else
67
+ memo[key.to_s] = nil
68
+ end
69
+ when Symbol
70
+ memo[key.to_s] = val.to_s
71
+ end
72
+ memo
73
+ end
74
+ rescue => error
75
+ log_failure(value.class, 'valid event params', context, error)
76
+ {}
77
+ end
78
+
79
+ def log_failure(value, type, context, error)
80
+ msg = "Unable to convert '#{value}' to #{type}"
81
+ msg += " in context '#{context}'" if context
82
+ TingYun::Agent.logger.warn(msg, error)
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ require 'ting_yun/agent'
4
+
5
+ module TingYun
6
+ module Support
7
+ class Collector < Struct.new :name, :port
8
+ def to_s; "#{name}:#{port}"; end
9
+ end
10
+
11
+ module CollectorMethods
12
+ def collector
13
+ @remote_collector ||= collector_from_host
14
+ end
15
+
16
+ def api_collector
17
+ @api_collector ||= Collector.new(TingYun::Agent.config[:api_host], TingYun::Agent.config[:api_port])
18
+ end
19
+
20
+ def collector_from_host(hostname=nil)
21
+ Collector.new(hostname || TingYun::Agent.config[:host], TingYun::Agent.config[:port])
22
+ end
23
+
24
+ end
25
+
26
+ extend CollectorMethods
27
+
28
+ end
29
+ end
@@ -0,0 +1,79 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+ #
5
+
6
+ module TingYun
7
+ module Support
8
+ module Exception
9
+ # An exception that is thrown by the server if the agent license is invalid.
10
+ class LicenseException < StandardError;
11
+ end
12
+
13
+ # An exception that is thrown by the agent, if server['nbs.agent_enable']==false.
14
+ class AgentEnableException <StandardError;
15
+ end
16
+
17
+ # An exception that is thrown by the server, drop the data.
18
+ class UnKnownServerException < StandardError;
19
+ end
20
+
21
+ # An exception that forces an agent to stop reporting until its mongrel is restarted.
22
+ class ForceDisconnectException < StandardError;
23
+ end
24
+
25
+ # An exception that forces an agent to restart.
26
+ class ForceRestartException < StandardError;
27
+ end
28
+
29
+ # An exception that forces an agent to restart.
30
+ class InvalidDataException < StandardError;
31
+ end
32
+
33
+ class ExpiredConfigurationException < StandardError;
34
+ end
35
+
36
+ # An exception that forces an agent to restart initAgentApp.
37
+ class InvalidDataTokenException < StandardError;
38
+ end
39
+ # Used to blow out of a periodic task without logging a an error, such as for routine
40
+ # failures.
41
+ class ServerConnectionException < StandardError;
42
+ end
43
+
44
+ # When a post is either too large or poorly formatted we should
45
+ # drop it and not try to resend
46
+ class UnrecoverableServerException < ServerConnectionException;
47
+ end
48
+
49
+ # An unrecoverable client-side error that prevents the agent from continuing
50
+ class UnrecoverableAgentException < ServerConnectionException;
51
+ end
52
+
53
+ # An error while serializing data for the collector
54
+ class SerializationError < StandardError;
55
+ end
56
+
57
+ class BackgroundLoadingError < StandardError;
58
+ end
59
+
60
+ class UnsupportedMediaType < StandardError
61
+ end
62
+ # Used to wrap errors reported to agent by the collector
63
+ class CollectorError < StandardError;
64
+ end
65
+
66
+ #This is the base class for all errors that we want to record , It provides the
67
+ # standard support text at the front of the message, and is used for flagging
68
+ # agent errors when checking queue limits.
69
+ class InternalAgentError < StandardError
70
+ def initialize(msg=nil)
71
+ super("Ruby agent internal error. Please contact support referencing this error.\n #{msg}")
72
+ end
73
+ end
74
+
75
+ class InternalServerError < StandardError
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+ module TingYun
5
+ module Support
6
+ module HashExtensions
7
+ module_function
8
+
9
+ # recurses through hashes and arrays and stringifies keys
10
+ def stringify_keys_in_object(object)
11
+ case object
12
+ when Hash
13
+ object.inject({}) do |memo, (k, v)|
14
+ memo[k.to_s] = stringify_keys_in_object(v)
15
+ memo
16
+ end
17
+ when Array
18
+ object.map {|o| stringify_keys_in_object(o)}
19
+ else
20
+ object
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end