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,206 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rbconfig'
4
+
5
+ module TingYun
6
+ module Support
7
+ module SystemInfo
8
+ def self.ruby_os_identifier
9
+ RbConfig::CONFIG['target_os']
10
+ end
11
+
12
+ def self.clear_processor_info
13
+ @processor_info = nil
14
+ end
15
+
16
+ def self.get_processor_info
17
+ if @processor_info.nil?
18
+ case ruby_os_identifier
19
+
20
+ when /darwin/
21
+ @processor_info = {
22
+ :num_physical_packages => sysctl_value('hw.packages').to_i,
23
+ :num_physical_cores => sysctl_value('hw.physicalcpu_max').to_i,
24
+ :num_logical_processors => sysctl_value('hw.logicalcpu_max').to_i
25
+ }
26
+ # in case those don't work, try backup values
27
+ if @processor_info[:num_physical_cores] <= 0
28
+ @processor_info[:num_physical_cores] = sysctl_value('hw.physicalcpu').to_i
29
+ end
30
+ if @processor_info[:num_logical_processors] <= 0
31
+ @processor_info[:num_logical_processors] = sysctl_value('hw.logicalcpu').to_i
32
+ end
33
+ if @processor_info[:num_logical_processors] <= 0
34
+ @processor_info[:num_logical_processors] = sysctl_value('hw.ncpu').to_i
35
+ end
36
+
37
+ when /linux/
38
+ cpuinfo = proc_try_read('/proc/cpuinfo')
39
+ @processor_info = cpuinfo ? parse_cpuinfo(cpuinfo) : {}
40
+
41
+ when /freebsd/
42
+ @processor_info = {
43
+ :num_physical_packages => nil,
44
+ :num_physical_cores => nil,
45
+ :num_logical_processors => sysctl_value('hw.ncpu').to_i
46
+ }
47
+ end
48
+
49
+ # give nils for obviously wrong values
50
+ @processor_info.keys.each do |key|
51
+ value = @processor_info[key]
52
+ if value.is_a?(Numeric) && value <= 0
53
+ @processor_info[key] = nil
54
+ end
55
+ end
56
+ end
57
+
58
+ @processor_info
59
+ rescue
60
+ {}
61
+ end
62
+
63
+ def self.sysctl_value(name)
64
+ # make sure to redirect stderr so we don't spew if the name is unknown
65
+ `sysctl -n #{name} 2>/dev/null`
66
+ end
67
+
68
+ def self.parse_cpuinfo(cpuinfo)
69
+ # Build a hash of the form
70
+ # { [phys_id, core_id] => num_logical_processors_on_this_core }
71
+ cores = Hash.new(0)
72
+ phys_id = core_id = nil
73
+
74
+ total_processors = 0
75
+
76
+ cpuinfo.split("\n").map(&:strip).each do |line|
77
+ case line
78
+ when /^processor\s*:/
79
+ cores[[phys_id, core_id]] += 1 if phys_id && core_id
80
+ phys_id = core_id = nil # reset these values
81
+ total_processors += 1
82
+ when /^physical id\s*:(.*)/
83
+ phys_id = $1.strip.to_i
84
+ when /^core id\s*:(.*)/
85
+ core_id = $1.strip.to_i
86
+ end
87
+ end
88
+ cores[[phys_id, core_id]] += 1 if phys_id && core_id
89
+
90
+ num_physical_packages = cores.keys.map(&:first).uniq.size
91
+ num_physical_cores = cores.size
92
+ num_logical_processors = cores.values.reduce(0,:+)
93
+
94
+ if num_physical_cores == 0
95
+ num_logical_processors = total_processors
96
+
97
+ if total_processors == 1
98
+ # Some older, single-core processors might not list ids,
99
+ # so we'll just mark them all 1.
100
+ num_physical_packages = 1
101
+ num_physical_cores = 1
102
+ else
103
+ # We have no way of knowing how many packages or cores
104
+ # we have, even though we know how many processors there are.
105
+ num_physical_packages = nil
106
+ num_physical_cores = nil
107
+ end
108
+ end
109
+
110
+ {
111
+ :num_physical_packages => num_physical_packages,
112
+ :num_physical_cores => num_physical_cores,
113
+ :num_logical_processors => num_logical_processors
114
+ }
115
+ end
116
+
117
+ def self.num_physical_packages ; get_processor_info[:num_physical_packages ] end
118
+ def self.num_physical_cores ; get_processor_info[:num_physical_cores ] end
119
+ def self.num_logical_processors
120
+ processor_count = get_processor_info[:num_logical_processors]
121
+
122
+ if processor_count.nil?
123
+ TingYun::Agent.logger.warn("Failed to determine processor count, assuming 1")
124
+ processor_count = 1
125
+ end
126
+
127
+ processor_count
128
+ end
129
+
130
+ def self.processor_arch
131
+ RbConfig::CONFIG['target_cpu']
132
+ end
133
+
134
+ def self.os_version
135
+ proc_try_read('/proc/version')
136
+ end
137
+
138
+ def self.docker_container_id
139
+ return unless ruby_os_identifier =~ /linux/
140
+
141
+ cgroup_info = proc_try_read('/proc/self/cgroup')
142
+ return unless cgroup_info
143
+
144
+ parse_docker_container_id(cgroup_info)
145
+ end
146
+
147
+ def self.parse_docker_container_id(cgroup_info)
148
+ cpu_cgroup = parse_cgroup_ids(cgroup_info)['cpu']
149
+ return unless cpu_cgroup
150
+
151
+ case cpu_cgroup
152
+ # docker native driver w/out systemd (fs)
153
+ when %r{^/docker/([0-9a-f]+)$} then $1
154
+ # docker native driver with systemd
155
+ when %r{^/system\.slice/docker-([0-9a-f]+)\.scope$} then $1
156
+ # docker lxc driver
157
+ when %r{^/lxc/([0-9a-f]+)$} then $1
158
+ # not in any cgroup
159
+ when '/' then nil
160
+ # in a cgroup, but we don't recognize its format
161
+ else
162
+ TingYun::Agent.logger.debug("Ignoring unrecognized cgroup ID format: '#{cpu_cgroup}'")
163
+ nil
164
+ end
165
+ end
166
+
167
+ def self.parse_cgroup_ids(cgroup_info)
168
+ cgroup_ids = {}
169
+
170
+ cgroup_info.split("\n").each do |line|
171
+ parts = line.split(':')
172
+ next unless parts.size == 3
173
+ _, subsystems, cgroup_id = parts
174
+ subsystems = subsystems.split(',')
175
+ subsystems.each do |subsystem|
176
+ cgroup_ids[subsystem] = cgroup_id
177
+ end
178
+ end
179
+
180
+ cgroup_ids
181
+ end
182
+
183
+ # A File.read against /(proc|sysfs)/* can hang with some older Linuxes.
184
+ # See https://bugzilla.redhat.com/show_bug.cgi?id=604887, RUBY-736, and
185
+ # https://github.com/opscode/ohai/commit/518d56a6cb7d021b47ed3d691ecf7fba7f74a6a7
186
+ # for details on why we do it this way.
187
+ def self.proc_try_read(path)
188
+ return nil unless File.exist?(path)
189
+ content = ''
190
+ File.open(path) do |f|
191
+ loop do
192
+ begin
193
+ content << f.read_nonblock(4096)
194
+ rescue EOFError
195
+ break
196
+ rescue Errno::EWOULDBLOCK, Errno::EAGAIN
197
+ content = nil
198
+ break # don't select file handle, just give up
199
+ end
200
+ end
201
+ end
202
+ content
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ # This code was borrowed from the system_timer gem under the terms
4
+ # of the Ruby license. It has been slightly modified.
5
+
6
+ # Defines the constant TimerLib to the appropriate timeout library
7
+ module TingYun #:nodoc:
8
+ module Support
9
+
10
+ begin
11
+ # Try to use the SystemTimer gem instead of Ruby's timeout library
12
+ # when running on Ruby 1.8.x. See:
13
+ # http://ph7spot.com/articles/system_timer
14
+ # We don't want to bother trying to load SystemTimer on jruby,
15
+ # ruby 1.9+ and rbx.
16
+ if !defined?(RUBY_ENGINE) || (RUBY_ENGINE == 'ruby' && RUBY_VERSION < '1.9.0')
17
+ require 'system_timer'
18
+ TimerLib = SystemTimer
19
+ else
20
+ require 'timeout'
21
+ TimerLib = Timeout
22
+ end
23
+ rescue LoadError
24
+ require 'timeout'
25
+ TimerLib = Timeout
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+
3
+ module TingYun
4
+ module Support
5
+ class VersionNumber
6
+
7
+ include Comparable
8
+
9
+ attr_reader :parts
10
+
11
+ def initialize(version_string)
12
+ version_string ||= '1.0.0'
13
+ @parts = version_string.split('.').map { |n| n =~ /^\d+$/ ? n.to_i : n }
14
+ end
15
+
16
+ def major_version;
17
+ @parts[0];
18
+ end
19
+
20
+ def minor_version;
21
+ @parts[1];
22
+ end
23
+
24
+ def tiny_version;
25
+ @parts[2];
26
+ end
27
+
28
+ def <=>(other)
29
+ other = self.class.new(other) if other.is_a? String
30
+ self.class.compare(self.parts, other.parts)
31
+ end
32
+
33
+ def to_s
34
+ @parts.join(".")
35
+ end
36
+
37
+ def hash
38
+ @parts.hash
39
+ end
40
+
41
+ def eql? other
42
+ (self <=> other) == 0
43
+ end
44
+
45
+ private
46
+
47
+ def self.compare(parts1, parts2)
48
+ a, b = parts1.first, parts2.first
49
+ case
50
+ when a.nil? && b.nil? then
51
+ 0
52
+ when a.nil? then
53
+ b.is_a?(Fixnum) ? -1 : 1
54
+ when b.nil? then
55
+ -compare(parts2, parts1)
56
+ when a.to_s == b.to_s then
57
+ compare(parts1[1..-1], parts2[1..-1])
58
+ when a.is_a?(String) then
59
+ b.is_a?(Fixnum) ? -1 : (a <=> b)
60
+ when b.is_a?(String) then
61
+ -compare(parts2, parts1)
62
+ else # they are both fixnums, not nil
63
+ a <=> b
64
+ end
65
+ end
66
+
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,118 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+
5
+ module TingYun
6
+ class TingYunService
7
+ module Connection
8
+ # Return a Net::HTTP connection object to make a call to the collector.
9
+ # We'll reuse the same handle for cases where we're using keep-alive, or
10
+ # otherwise create a new one.
11
+ def http_connection
12
+ if @in_session
13
+ establish_shared_connection
14
+ else
15
+ create_http_connection
16
+ end
17
+ end
18
+
19
+ def establish_shared_connection
20
+ unless @shared_tcp_connection
21
+ @shared_tcp_connection = create_and_start_http_connection
22
+ end
23
+ @shared_tcp_connection
24
+ end
25
+
26
+
27
+ def create_and_start_http_connection
28
+ conn = create_http_connection
29
+ start_connection(conn)
30
+ conn
31
+ end
32
+
33
+ def start_connection(conn)
34
+ TingYun::Agent.logger.debug("Opening TCP connection to #{conn.address}:#{conn.port}")
35
+ TingYun::Support::TimerLib.timeout(@request_timeout) { conn.start }
36
+ conn
37
+ end
38
+
39
+
40
+ def create_http_connection
41
+ if TingYun::Agent.config[:proxy_host]
42
+ TingYun::Agent.logger.debug("Using proxy server #{TingYun::Agent.config[:proxy_host]}:#{TingYun::Agent.config[:proxy_port]}")
43
+
44
+ proxy = Net::HTTP::Proxy(
45
+ TingYun::Agent.config[:proxy_host],
46
+ TingYun::Agent.config[:proxy_port],
47
+ TingYun::Agent.config[:proxy_user],
48
+ TingYun::Agent.config[:proxy_pass]
49
+ )
50
+ conn = proxy.new(@collector.name, @collector.port)
51
+ else
52
+ conn = Net::HTTP.new(@collector.name, @collector.port)
53
+ end
54
+
55
+ setup_connection_for_ssl(conn) if TingYun::Agent.config[:ssl]
56
+ setup_connection_timeouts(conn)
57
+ TingYun::Agent.logger.debug("Created net/http handle to #{conn.address}:#{conn.port}")
58
+
59
+ conn
60
+ end
61
+
62
+ def close_shared_connection
63
+ if @shared_tcp_connection
64
+ TingYun::Agent.logger.debug("Closing shared TCP connection to #{@shared_tcp_connection.address}:#{@shared_tcp_connection.port}")
65
+ @shared_tcp_connection.finish if @shared_tcp_connection.started?
66
+ @shared_tcp_connection = nil
67
+ end
68
+ end
69
+
70
+
71
+ def setup_connection_timeouts(conn)
72
+ # We use Timeout explicitly instead of this
73
+ conn.read_timeout = nil
74
+
75
+ if conn.respond_to?(:keep_alive_timeout) && TingYun::Agent.config[:aggressive_keepalive]
76
+ conn.keep_alive_timeout = TingYun::Agent.config[:keep_alive_timeout]
77
+ end
78
+ end
79
+
80
+ # One session with the service's endpoint. In this case the session
81
+ # represents 1 tcp connection which may transmit multiple HTTP requests
82
+ # via keep-alive.
83
+ def session(&block)
84
+ raise ArgumentError, "#{self.class}#shared_connection must be passed a block" unless block_given?
85
+
86
+ begin
87
+ t0 = Time.now
88
+ @in_session = true
89
+ if TingYun::Agent.config[:aggressive_keepalive]
90
+ session_with_keepalive(&block)
91
+ else
92
+ session_without_keepalive(&block)
93
+ end
94
+ rescue *CONNECTION_ERRORS => e
95
+ elapsed = Time.now - t0
96
+ raise TingYun::Support::Exception::ServerConnectionException, "Recoverable error connecting to #{@collector} after #{elapsed} seconds: #{e}"
97
+ ensure
98
+ @in_session = false
99
+ end
100
+ end
101
+
102
+ def session_with_keepalive(&block)
103
+ establish_shared_connection
104
+ block.call
105
+ end
106
+
107
+ def session_without_keepalive(&block)
108
+ begin
109
+ establish_shared_connection
110
+ block.call
111
+ ensure
112
+ close_shared_connection
113
+ end
114
+ end
115
+
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+ require 'zlib'
5
+ require 'net/https'
6
+ require 'net/http'
7
+ require 'ting_yun/ting_yun_service/ssl'
8
+ require 'ting_yun/ting_yun_service/request'
9
+ require 'ting_yun/ting_yun_service/connection'
10
+
11
+ module TingYun
12
+ class TingYunService
13
+ module Http
14
+
15
+ include Ssl
16
+ include Request
17
+ include Connection
18
+
19
+ def remote_method_uri(method)
20
+ params = {'licenseKey'=> @license_key,'version' => @data_version}
21
+ params[:appSessionKey] = @appSessionKey if @appSessionKey
22
+ uri = "/" + method.to_s
23
+ uri << '?' + params.map do |k,v|
24
+ next unless v
25
+ "#{k}=#{v}"
26
+ end.compact.join('&')
27
+ uri
28
+ end
29
+
30
+ # Decompresses the response from the server, if it is gzip
31
+ # encoded, otherwise returns it verbatim
32
+ def decompress_response(response)
33
+ if response['content-encoding'] == 'gzip'
34
+ Zlib::GzipReader.new(StringIO.new(response.body)).read
35
+ else
36
+ response.body
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,90 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+ require 'ting_yun/support/exception'
4
+
5
+ module TingYun
6
+ class TingYunService
7
+ module Request
8
+
9
+ #Posts to the specified server, retry every minute if ServerConnectionException
10
+ def send_request(opts)
11
+ request = Net::HTTP::Post.new(opts[:uri], 'CONTENT-ENCODING' => opts[:encoding], 'HOST' => opts[:collector].name)
12
+ request['user-agent'] = user_agent
13
+ request.content_type = "application/octet-stream"
14
+ request.body = opts[:data]
15
+ response = nil
16
+ max_attempts = 2
17
+ attempts = 0
18
+ begin
19
+ attempts += 1
20
+ conn = http_connection
21
+ TingYun::Agent.logger.debug "Sending request to #{opts[:collector]}#{opts[:uri]}"
22
+ TingYun::Support::TimerLib.timeout(@request_timeout) do
23
+ response = conn.request(request)
24
+ end
25
+ rescue *CONNECTION_ERRORS => e
26
+ close_shared_connection
27
+ if attempts < max_attempts
28
+ TingYun::Agent.logger.debug("Retrying request to #{opts[:collector]}#{opts[:uri]} after #{e}")
29
+ retry
30
+ else
31
+ raise TingYun::Support::Exception::ServerConnectionException, "Recoverable error talking to #{@collector} after #{attempts} attempts: #{e}"
32
+ end
33
+ end
34
+ TingYun::Agent.logger.debug "Received response, status: #{response.code}, encoding: '#{response['content-encoding']}'"
35
+
36
+
37
+ case response
38
+ when Net::HTTPSuccess
39
+ true # do nothing
40
+ when Net::HTTPServiceUnavailable
41
+ raise TingYun::Support::Exception::ServerConnectionException, "Service unavailable (#{response.code}): #{response.message}"
42
+ when Net::HTTPGatewayTimeOut
43
+ raise TingYun::Support::Exception::ServerConnectionException, "Gateway timeout (#{response.code}): #{response.message}"
44
+ when Net::HTTPRequestEntityTooLarge
45
+ raise TingYun::Support::Exception::UnrecoverableServerException, '413 Request Entity Too Large'
46
+ when Net::HTTPUnsupportedMediaType
47
+ raise TingYun::Support::Exception::UnsupportedMediaType, '415 Unsupported Media Type'
48
+ else
49
+ raise TingYun::Support::Exception::ServerConnectionException, "Unexpected response from server (#{response.code}): #{response.message}"
50
+ end
51
+ response
52
+ end
53
+
54
+
55
+
56
+ def compress_request_if_needed(data)
57
+ encoding = 'identity'
58
+ if data.size > 64*1024
59
+ data = TingYun::Support::Serialize::Encoders::Compressed.encode(data)
60
+ encoding = 'deflate'
61
+ end
62
+ check_post_size(data)
63
+ [data, encoding]
64
+ end
65
+
66
+ def check_post_size(post)
67
+ return if post.size < TingYun::Agent.config[:post_size_limit]
68
+ TingYun::Agent.logger.debug "Tried to send too much data: #{post.size} bytes"
69
+ raise TingYun::Support::Exception::UnrecoverableServerException.new('413 Request Entity Too Large')
70
+ end
71
+
72
+ def user_agent
73
+ ruby_description = ''
74
+ # note the trailing space!
75
+ ruby_description << "(ruby #{::RUBY_VERSION} #{::RUBY_PLATFORM}) " if defined?(::RUBY_VERSION) && defined?(::RUBY_PLATFORM)
76
+ zlib_version = ''
77
+ zlib_version << "zlib/#{Zlib.zlib_version}" if defined?(::Zlib) && Zlib.respond_to?(:zlib_version)
78
+ "NBS Newlens Agent/#{TingYun::VERSION::STRING} #{ruby_description}#{zlib_version}"
79
+ end
80
+
81
+ def valid_to_marshal?(data)
82
+ @marshaller.dump(data)
83
+ true
84
+ rescue StandardError, SystemStackError => e
85
+ TingYun::Agent.logger.warn("Unable to marshal environment report on connect.", e)
86
+ false
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+ require 'ting_yun/support/path'
4
+ require 'ting_yun/support/exception'
5
+
6
+ module TingYun
7
+ class TingYunService
8
+ module Ssl
9
+
10
+ def setup_connection_for_ssl(conn)
11
+ # Jruby 1.6.8 requires a gem for full ssl support and will throw
12
+ # an error when use_ssl=(true) is called and jruby-openssl isn't
13
+ # installed
14
+ conn.use_ssl = true
15
+ conn.verify_mode = OpenSSL::SSL::VERIFY_PEER
16
+ conn.cert_store = ssl_cert_store
17
+ rescue StandardError, LoadError
18
+ msg = "Agent is configured to use SSL, but SSL is not available in the environment. "
19
+ msg << "Either disable SSL in the agent configuration, or install SSL support."
20
+ raise TingYun::Support::Exception::UnrecoverableAgentException.new(msg)
21
+ end
22
+
23
+ def ssl_cert_store
24
+ path = cert_file_path
25
+ if !@ssl_cert_store || path != @cached_cert_store_path
26
+ TingYun::Agent.logger.debug("Creating SSL certificate store from file at #{path}")
27
+ @ssl_cert_store = OpenSSL::X509::Store.new
28
+ @ssl_cert_store.add_file(path)
29
+ @cached_cert_store_path = path
30
+ end
31
+ @ssl_cert_store
32
+ end
33
+
34
+ def cert_file_path
35
+ if path_override = TingYun::Agent.config[:ca_bundle_path]
36
+ TingYun::Agent.logger.warn("Couldn't find CA bundle from configured ca_bundle_path: #{path_override}") unless File.exist? path_override
37
+ path_override
38
+ else
39
+ File.expand_path(File.join(TingYun::Support::Path.ting_yun_root, 'cert', 'cacert.pem'))
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end