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,116 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+ require 'ting_yun/configuration/dotted_hash'
5
+
6
+
7
+ module TingYun
8
+ module Configuration
9
+ class EnvironmentSource < DottedHash
10
+ SUPPORTED_PREFIXES = /^ting_yun_|^tingyun_/i
11
+ SPECIAL_CASE_KEYS = [
12
+ 'TING_YUN_ENV',
13
+ 'TING_YUN_LOG' # read by set_log_file
14
+ ]
15
+
16
+ attr_accessor :alias_map, :type_map
17
+
18
+ def initialize
19
+ set_config_file
20
+ set_log_file
21
+
22
+ @alias_map = {}
23
+ @type_map = {}
24
+
25
+ DEFAULTS.each do |config_setting, value|
26
+ self.type_map[config_setting] = value[:type]
27
+ set_aliases(config_setting, value)
28
+ end
29
+
30
+ set_values_from_ting_yun_environment_variables
31
+ end
32
+
33
+ def set_aliases(config_setting, value)
34
+ set_dotted_alias(config_setting)
35
+
36
+ return unless value[:aliases]
37
+ value[:aliases].each do |alise|
38
+ self.alias_map[alise] = config_setting
39
+ end
40
+ end
41
+
42
+ def set_dotted_alias(original_config_setting)
43
+ config_setting = original_config_setting.to_s
44
+
45
+
46
+ if config_setting.include? '.'
47
+ config_alias = config_setting.gsub(/\./, '_').to_sym
48
+ self.alias_map[config_alias] = original_config_setting
49
+ end
50
+ end
51
+
52
+ def set_config_file
53
+ self[:config_path] = ENV['NRCONFIG'] if ENV['NRCONFIG']
54
+ end
55
+
56
+
57
+ def set_log_file
58
+ if ENV['TING_YUN_LOG']
59
+ if ENV['TING_YUN_LOG'].upcase == 'STDOUT'
60
+ self[:log_file_path] = self[:log_file_name] = 'STDOUT'
61
+ else
62
+ self[:log_file_path] = File.dirname(ENV['TING_YUN_LOG'])
63
+ self[:log_file_name] = File.basename(ENV['TING_YUN_LOG'])
64
+ end
65
+ end
66
+ end
67
+
68
+ def set_values_from_ting_yun_environment_variables
69
+ env_var_keys = collect_ting_yun_environment_variable_keys
70
+ env_var_keys.each do |key|
71
+ next if SPECIAL_CASE_KEYS.include?(key.upcase)
72
+ set_value_from_environment_variable(key)
73
+ end
74
+ end
75
+
76
+ def set_value_from_environment_variable(key)
77
+ config_key = convert_environment_key_to_config_key(key)
78
+ set_key_by_type(config_key, key)
79
+ end
80
+
81
+ def set_key_by_type(config_key, environment_key)
82
+ value = ENV[environment_key]
83
+ type = self.type_map[config_key]
84
+
85
+ if type == String
86
+ self[config_key] = value
87
+ elsif type == Fixnum
88
+ self[config_key] = value.to_i
89
+ elsif type == Float
90
+ self[config_key] = value.to_f
91
+ elsif type == Symbol
92
+ self[config_key] = value.to_sym
93
+ elsif type == TingYun::Configuration::Boolean
94
+ if value =~ /false|off|no/i
95
+ self[config_key] = false
96
+ elsif value != nil
97
+ self[config_key] = true
98
+ end
99
+ else
100
+ # TingYun::Agent.logger.info("#{environment_key} does not have a corresponding configuration setting (#{config_key} does not exist).")
101
+ self[config_key] = value
102
+ end
103
+
104
+ end
105
+
106
+ def convert_environment_key_to_config_key(key)
107
+ stripped_key = key.gsub(SUPPORTED_PREFIXES, '').downcase.to_sym
108
+ self.alias_map[stripped_key] || stripped_key
109
+ end
110
+
111
+ def collect_ting_yun_environment_variable_keys
112
+ ENV.keys.select { |key| key.match(SUPPORTED_PREFIXES) }
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,232 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+ require 'ting_yun/configuration/default_source'
4
+ require 'ting_yun/configuration/environment_source'
5
+ require 'ting_yun/configuration/yaml_source'
6
+ require 'ting_yun/configuration/server_source'
7
+ require 'ting_yun/configuration/manual_source'
8
+
9
+
10
+ module TingYun
11
+ module Configuration
12
+ class Manager
13
+
14
+ def initialize
15
+ reset_to_defaults
16
+ end
17
+
18
+ def [](key)
19
+ @cache[key]
20
+ end
21
+
22
+ def has_key?(key)
23
+ @cache.has_key?(key)
24
+ end
25
+
26
+ def keys
27
+ @cache.keys
28
+ end
29
+
30
+ def app_names
31
+ if TingYun::Agent.config[:'nbs.auto_app_naming']
32
+ begin
33
+ [::TingYun::Frameworks.framework.root.split('/').last]
34
+ rescue Exception => e
35
+ get_name
36
+ end
37
+ else
38
+ get_name
39
+ end
40
+
41
+ end
42
+
43
+ def get_name
44
+ case TingYun::Agent.config[:app_name]
45
+ when Array then
46
+ TingYun::Agent.config[:app_name]
47
+ when String then
48
+ TingYun::Agent.config[:app_name].split(';')
49
+ else
50
+ []
51
+ end
52
+ end
53
+
54
+ def reset_to_defaults
55
+ @default_source = DefaultSource.new
56
+ @environment_source = EnvironmentSource.new
57
+ @yaml_source = nil
58
+ @server_source = nil
59
+ @manual_source = nil
60
+ # @callbacks = Hash.new {|hash,key| hash[key] =[]}#存放需要merge本地和服务端配置的info'
61
+
62
+ @configs_for_testing = []
63
+
64
+ reset_cache
65
+ end
66
+
67
+ def reset_cache
68
+ @cache = Hash.new { |hash, key| hash[key] = self.fetch(key) }
69
+ end
70
+
71
+ def fetch(key)
72
+ config_stack.each do |config|
73
+ next unless config
74
+ accessor = key.to_sym
75
+
76
+ if config.has_key?(accessor)
77
+ return evaluated = evaluate_procs(config[accessor]) #if it's proc
78
+ end
79
+ end
80
+ nil
81
+ end
82
+
83
+ def evaluate_procs(value)
84
+ if value.respond_to?(:call)
85
+ instance_eval(&value)
86
+ else
87
+ value
88
+ end
89
+ end
90
+
91
+ def add_config_for_testing(source, level=0)
92
+ raise 'Invalid config type for testing' unless [Hash, DottedHash].include?(source.class)
93
+ @configs_for_testing << [source.freeze, level]
94
+ reset_cache
95
+ log_config(:add, source)
96
+ end
97
+
98
+ def remove_config_type(sym)
99
+ source = case sym
100
+ when :environment then @environment_source
101
+ when :server then @server_source
102
+ when :manual then @manual_source
103
+ when :yaml then @yaml_source
104
+ when :default then @default_source
105
+ end
106
+ remove_config(source)
107
+ end
108
+
109
+
110
+ def remove_config(source)
111
+ case source
112
+ when YamlSource then @yaml_source = nil
113
+ when DefaultSource then @default_source = nil
114
+ when EnvironmentSource then @environment_source = nil
115
+ when ManualSource then @manual_source = nil
116
+ when ServerSource then @server_source = nil
117
+ else
118
+ @configs_for_testing.delete_if { |src, lvl| src == source }
119
+ end
120
+
121
+ reset_cache
122
+
123
+ #invoke_callbacks(:remove,source)
124
+
125
+ log_config(:remove, source)
126
+
127
+ end
128
+
129
+ def replace_or_add_config(source)
130
+ source.freeze
131
+
132
+ was_finished = finished_configuring?
133
+
134
+ case source
135
+ when YamlSource then @yaml_source = source
136
+ when DefaultSource then @default_source = source
137
+ when EnvironmentSource then @environment_source = source
138
+ when ServerSource then @server_source = source
139
+ when ManualSource then @manual_source = source
140
+ else
141
+ TingYun::Agent.logger.warn("Invalid config format; config will be ignored: #{source}")
142
+ end
143
+ reset_cache
144
+
145
+ log_config(:add, source)
146
+
147
+ notify_finished_configuring if !was_finished && finished_configuring?
148
+ end
149
+
150
+ def notify_finished_configuring
151
+ TingYun::Agent.instance.events.notify(:finished_configuring)
152
+ end
153
+
154
+ def finished_configuring?
155
+ !@server_source.nil?
156
+ end
157
+
158
+
159
+ def source(key)
160
+ config_stack.each do |config|
161
+ if config.respond_to?(key.to_sym) || config.has_key?(key.to_sym)
162
+ return config
163
+ end
164
+ end
165
+ end
166
+
167
+ def log_config(direction, source)
168
+ # Just generating this log message (specifically calling
169
+ # flattened.inspect) is expensive enough that we don't want to do it
170
+ # unless we're actually going to be logging the message based on our
171
+ # current log level.
172
+ ::TingYun::Agent.logger.debug do
173
+ "Updating config (#{direction}) from #{source.class}. Results: #{flattened.inspect}"
174
+ end
175
+ end
176
+
177
+ def flattened
178
+ config_stack.reverse.inject({}) do |flat, layer|
179
+ thawed_layer = layer.to_hash.dup
180
+ thawed_layer.each do |k, v|
181
+ begin
182
+ thawed_layer[k] = instance_eval(&v) if v.respond_to?(:call)
183
+ rescue => e
184
+ ::TingYun::Agent.logger.debug("#{e.class.name} : #{e.message} - when accessing config key #{k}")
185
+ thawed_layer[k] = nil
186
+ end
187
+ thawed_layer.delete(:config)
188
+ end
189
+ flat.merge(thawed_layer.to_hash)
190
+ end
191
+ end
192
+
193
+ def config_classes_for_testing
194
+ config_stack.map(&:class)
195
+ end
196
+
197
+
198
+
199
+
200
+ def to_collector_hash
201
+ DottedHash.new(flattened).to_hash.delete_if do |k, v|
202
+ default = DEFAULTS[k]
203
+ if default
204
+ default[:exclude_from_reported_settings]
205
+ else
206
+ # In our tests, we add totally bogus configs, because testing.
207
+ # In those cases, there will be no default. So we'll just let
208
+ # them through.
209
+ false
210
+ end
211
+ end
212
+ end
213
+
214
+ private
215
+
216
+ def config_stack
217
+ stack = [@environment_source, @server_source, @manual_source, @yaml_source, @default_source]
218
+
219
+ stack.compact!
220
+ @configs_for_testing.each do |config, at_start|
221
+ if at_start
222
+ stack.insert(0, config)
223
+ else
224
+ stack.push(config)
225
+ end
226
+ end
227
+
228
+ stack
229
+ end
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+ require 'ting_yun/configuration/dotted_hash'
5
+
6
+ module TingYun
7
+ module Configuration
8
+ class ManualSource < DottedHash
9
+ def initialize(hash)
10
+ super(hash, true)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,88 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+ require 'ting_yun/configuration/dotted_hash'
5
+
6
+ module TingYun
7
+ module Configuration
8
+ class ServerSource < DottedHash
9
+ # These keys appear *outside* of the agent_config hash in the connect
10
+ # response, but should still be merged in as config settings to the
11
+ # main agent configuration.
12
+ TOP_LEVEL_KEYS = [
13
+ "applicationId",
14
+ "tingyunIdSecret",
15
+ "enabled",
16
+ "appSessionKey",
17
+ "dataSentInterval",
18
+ "apdex_t",
19
+ "config"
20
+ ]
21
+
22
+ def self.add_top_level_keys_for_testing(add_array)
23
+ TOP_LEVEL_KEYS.concat add_array
24
+ end
25
+
26
+ def self.remove_top_level_keys_for_testing(remove_arry)
27
+ remove_arry.each{|i| TOP_LEVEL_KEYS.delete(i)}
28
+ end
29
+
30
+ def initialize(connect_reply)
31
+ merged_settings = {}
32
+
33
+ merge_top_level_keys(merged_settings, connect_reply)
34
+ merge_agent_config_hash(merged_settings, connect_reply)
35
+ filter_keys(merged_settings)
36
+ # apply_feature_gates(merged_settings, connect_reply, existing_config)
37
+
38
+ # The value under this key is a hash mapping transaction name strings
39
+ # to apdex_t values. We don't want the nested hash to be flattened
40
+ # as part of the call to super below, so it skips going through
41
+ # merged_settings.
42
+ # self[:web_transactions_apdex] = connect_reply['web_transactions_apdex']
43
+
44
+ # This causes keys in merged_settings to be symbolized and flattened
45
+ super(merged_settings)
46
+ end
47
+
48
+ def merge_top_level_keys(merged_settings, connect_reply)
49
+ TOP_LEVEL_KEYS.each do |key_name|
50
+ if connect_reply[key_name]
51
+ merged_settings[key_name] = connect_reply[key_name]
52
+ end
53
+ end
54
+ end
55
+
56
+ def merge_agent_config_hash(merged_settings, connect_reply)
57
+ if connect_reply['config']
58
+ merged_settings.merge!(connect_reply['config'])
59
+ end
60
+ end
61
+
62
+ def fix_transaction_threshold(merged_settings)
63
+ # when value is "apdex_f" remove the config and defer to default
64
+ if merged_settings['transaction_tracer.transaction_threshold'] =~ /apdex_f/i
65
+ merged_settings.delete('transaction_tracer.transaction_threshold')
66
+ end
67
+ end
68
+
69
+ def filter_keys(merged_settings)
70
+ merged_settings.delete_if do |key, _|
71
+ setting_spec = DEFAULTS[key.to_sym]
72
+ if setting_spec
73
+ if setting_spec[:allowed_from_server]
74
+ false # it's allowed, so don't delete it
75
+ else
76
+ TingYun::Agent.logger.warn("Ignoring server-sent config for '#{key}' - this setting cannot be set from the server")
77
+ true # delete it
78
+ end
79
+ else
80
+ TingYun::Agent.logger.debug("Ignoring unrecognized config key from server: '#{key}'")
81
+ true
82
+ end
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,136 @@
1
+ # encoding: utf-8
2
+ require 'ting_yun/configuration/dotted_hash'
3
+ require 'ting_yun/support/language_support'
4
+ require 'erb'
5
+
6
+ module TingYun
7
+ module Configuration
8
+ class YamlSource < DottedHash
9
+ attr_accessor :file_path, :failures
10
+
11
+ def initialize(path, env)
12
+ config = {}
13
+ @failures = []
14
+
15
+ begin
16
+ @file_path = vaildate_config_file_path(path)
17
+ return unless @file_path
18
+
19
+ ::TingYun::Agent.logger.info("Reading configuration from #{path} (#{Dir.pwd})")
20
+
21
+ raw_file = File.read(@file_path)
22
+ erb_file = process_erb(raw_file)
23
+ config = process_yaml(erb_file, env, config, @file_path)
24
+ rescue ScriptError, StandardError => e
25
+ log_failure("Failed to read or parse configuration file at #{path}", e)
26
+ end
27
+ booleanify_values(config, 'nbs.agent_enabled', 'enabled')
28
+ super(config, true)
29
+ end
30
+
31
+ def failed?
32
+ !@failures.empty?
33
+ end
34
+
35
+ protected
36
+
37
+ def vaildate_config_file_path(path)
38
+ expanded_path = File.expand_path(path)
39
+
40
+ if path.empty? || !File.exist?(expanded_path)
41
+ warn_missing_config_file(expanded_path)
42
+ return
43
+ end
44
+ expanded_path
45
+ end
46
+
47
+ def warn_missing_config_file(path)
48
+ based_on = 'unknown'
49
+ source = ::TingYun::Agent.config.source(:config_path)
50
+ candidate_paths = [path]
51
+
52
+ case source
53
+ when DefaultSource
54
+ based_on = "default"
55
+ candidate_paths = TingYun::Agent.config[:config_search_paths].map do |p|
56
+ File.expand_path(p)
57
+ end
58
+ when EnvironmentSource
59
+ based_on = "environment_source"
60
+ when ManualSource
61
+ based_on = 'API call'
62
+ end
63
+
64
+ TingYun::Agent.logger.warn(
65
+ "No configuration file found. Working directory = #{Dir.pwd}",
66
+ "Looked in these locations (based on #{based_on}): #{candidate_paths.join(", ")}"
67
+ )
68
+ end
69
+
70
+ def process_erb(file)
71
+ begin
72
+ # Exclude lines that are commented out so failing Ruby code in an
73
+ # ERB template commented at the YML level is fine. Leave the line,
74
+ # though, so ERB line numbers remain correct.
75
+ file.gsub!(/^\s*#.*$/, '#')
76
+
77
+ # Next two are for populating the tingyun.yml via erb binding, necessary
78
+ # when using the default tingyun.yml file
79
+ generated_for_user = ''
80
+ license_key = ''
81
+
82
+ ERB.new(file).result(binding)
83
+ rescue ScriptError, StandardError => e
84
+ log_failure("Failed ERB processing configuration file. This is typically caused by a Ruby error in <% %> templating blocks in your tingyun.yml file.", e)
85
+ nil
86
+ ensure
87
+ # Avoid warnings by using these again
88
+ generated_for_user = nil
89
+ license_key = nil
90
+ end
91
+ end
92
+
93
+ def process_yaml(file, env, config, path)
94
+ if file
95
+ confighash = with_yaml_engine { YAML.load(file) }
96
+ unless confighash.key?(env)
97
+ log_failure("Config file at #{path} doesn't include a '#{env}' section!")
98
+ end
99
+
100
+ config = confighash[env] || {}
101
+ end
102
+ config
103
+ end
104
+
105
+ def with_yaml_engine
106
+ return yield unless TingYun::Support::LanguageSupport.needs_syck?
107
+
108
+ yamler = ::YAML::ENGINE.yamler
109
+ ::YAML::ENGINE.yamler = 'syck'
110
+ result = yield
111
+ ::YAML::ENGINE.yamler = yamler
112
+ result
113
+ end
114
+
115
+ def booleanify_values(config, *keys)
116
+ # auto means defer ro default
117
+ keys.each do |option|
118
+ if config[option] == 'auto'
119
+ config.delete(option)
120
+ elsif !config[option].nil? && !is_boolean?(config[option])
121
+ config[option] = !!(config[option] =~ /yes|on|true/i)
122
+ end
123
+ end
124
+ end
125
+
126
+ def is_boolean?(value)
127
+ value == !!value
128
+ end
129
+
130
+ def log_failure(*messages)
131
+ ::TingYun::Agent.logger.error(*messages)
132
+ @failures << messages
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under Ting Yun's license terms.
3
+
4
+
5
+ module TingYun
6
+ module Configuration
7
+
8
+ end
9
+ end