tcell_agent 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f2e3e8eaef2cd61c9cc3effe2b97fa731eeebecf
4
- data.tar.gz: a10e24f2d47029ade958ac9b75ebb7f287abd825
3
+ metadata.gz: 3e9ec10853e07ac321bca036627e9e98a9e8545f
4
+ data.tar.gz: b1dce50c2950629b10397802e5a6f16fa1beabc1
5
5
  SHA512:
6
- metadata.gz: e5f0910986b130a99684b68ed99fe5af1bef89f82a9a555a4dc6f233e4580d7ceeaa2b335fe02e85a79a34407d5f41202c14d5c7f3bb7151215a94e04e22e640
7
- data.tar.gz: 79176adc5b5892cafcc7da924d1f0fcbcea066af31f2615c1744117975e8eae0a2a91b56f6a32b6638c778f60e09531e703d43275558c04a8d533327a69b7dca
6
+ metadata.gz: 1506c43edb7ae723f675b4cb1e8e5d0703505941c00cde7c399d3b7c64810ce3f8f0b53744b9eb61719d79272d8676519b0183c4af124f89702d576793b2f342
7
+ data.tar.gz: fca2c0f960400a55a7f67c7e0d93465174d785b299f703271cc1ce0befc2430093f0556e570469c0a9251ac6da7aff06dba8180499d284b4a6989d0b11ab7980
@@ -124,11 +124,12 @@ module TCellAgent
124
124
  puts " ********* ********* ********* *********"
125
125
  return
126
126
  end
127
- #puts "Starting"
127
+
128
+ TCellAgent.logger.debug("Starting thread agent")
129
+
128
130
  self.ensure_policy_polling_running
129
131
  self.ensure_event_processor_running
130
- #puts "Ending"
131
132
  end
132
133
 
133
134
  end
134
- end
135
+ end
@@ -54,27 +54,14 @@ module TCellAgent
54
54
  if TCellAgent::Agent.is_parent_process? == false
55
55
  return
56
56
  end
57
+
57
58
  @events_send_empties = send_empties
58
59
  Thread.abort_on_exception = true
59
60
  @event_processor_thread = Thread.new do
61
+
60
62
  begin
61
63
  tapi = TCellApi.new
62
- begin
63
- event = TCellAgent::SensorEvents::ServerAgentDetailsSensorEvent.new
64
- TCellAgent.send_event(event)
65
- rescue Exception => te
66
- TCellAgent.logger.error("Exception sending server agent details: #{te.message}")
67
- TCellAgent.logger.debug(te.backtrace)
68
- end
69
64
 
70
- begin
71
- event = TCellAgent::SensorEvents::ServerAgentPackagesSensorEvent.new
72
- TCellAgent.send_event(event)
73
- rescue Exception => te
74
- TCellAgent.logger.error("Exception sending server agent packages: #{te.message}")
75
- TCellAgent.logger.debug(te.backtrace)
76
- end
77
- timeout_flag = false
78
65
  last_run_time = Time.now
79
66
  loop do
80
67
  begin
@@ -82,6 +69,7 @@ module TCellAgent
82
69
  now = Time.now
83
70
  wait_for = @dispatchEventsTimeout - (now - last_run_time).to_i.abs
84
71
  event = @eventQueue.pop([wait_for, 1].max)
72
+
85
73
  if event == nil
86
74
  last_run_time = Time.now
87
75
  # JJJJJJJJ JJJJJJJ JJJJJJJ JJJJJJJJ JJJJJJJJJ
@@ -151,6 +139,7 @@ module TCellAgent
151
139
  @dispatchEvents = []
152
140
  }
153
141
  end
142
+
154
143
  rescue Exception => e
155
144
  last_run_time = Time.now
156
145
  TCellAgent.logger.error("Exception while processing events: #{e.message}")
@@ -164,7 +153,9 @@ module TCellAgent
164
153
  TCellAgent.logger.error("Exception while starting processor: #{xyz.message}")
165
154
  TCellAgent.logger.debug(xyz.backtrace)
166
155
  end
156
+
167
157
  end
158
+
168
159
  end
169
160
 
170
161
  def ensure_fork_event_thread_running
@@ -201,7 +192,7 @@ module TCellAgent
201
192
  rescue Exception => e
202
193
  TCellAgent.logger.error("Exception while running (forked) events: #{e.message}")
203
194
  TCellAgent.logger.debug(e.backtrace)
204
- end
195
+ end
205
196
  end
206
197
  end
207
198
 
@@ -248,7 +239,7 @@ module TCellAgent
248
239
  rescue Exception => e
249
240
  TCellAgent.logger.error("Exception while running (forked) metrics: #{e.message}")
250
241
  TCellAgent.logger.debug(e.backtrace)
251
- end
242
+ end
252
243
  end
253
244
  end
254
245
 
@@ -271,14 +262,17 @@ module TCellAgent
271
262
  self.queue_forked_event(event)
272
263
  return
273
264
  end
265
+
274
266
  begin
275
267
  self.ensure_event_processor_running
276
268
  @event_queue_monitor.synchronize {
277
- @eventQueue.push(event)
269
+ @eventQueue.push(event, 10)
278
270
  }
279
- rescue RuntimeError => te
271
+
272
+ rescue RuntimeError
280
273
  TCellAgent.logger.debug("Dropping event because queue full")
281
274
  end
275
+
282
276
  rescue Exception => queue_exception
283
277
  TCellAgent.logger.debug("Could not add event #{queue_exception.message}")
284
278
  end
@@ -305,6 +299,5 @@ module TCellAgent
305
299
  end
306
300
  end
307
301
 
308
-
309
302
  end
310
- end
303
+ end
@@ -65,6 +65,7 @@ module TCellAgent
65
65
  end
66
66
  end
67
67
  end
68
+
68
69
  @@event_pipe_manager = ForkPipeManager.new { |event|
69
70
  begin
70
71
  TCellAgent.send_event(event)
@@ -72,7 +73,7 @@ module TCellAgent
72
73
  TCellAgent.logger.error("Could handle send_event_block")
73
74
  TCellAgent.logger.error(block_exception.message)
74
75
  TCellAgent.logger.debug(block_exception.backtrace)
75
- end
76
+ end
76
77
  }
77
78
  @@metrics_pipe_manager = ForkPipeManager.new { |val|
78
79
  begin
@@ -43,7 +43,7 @@ module TCellAgent
43
43
 
44
44
  def start_policy_polling
45
45
  if TCellAgent.configuration.fetch_policies_from_tcell == true
46
- TCellAgent.logger.debug("starting background polling thread")
46
+ TCellAgent.logger.debug("Starting policy polling thread")
47
47
  @policy_polling_thread = Thread.new do
48
48
  last_poll_time = 0
49
49
  last_run = Time.now
@@ -147,4 +147,4 @@ module TCellAgent
147
147
  end
148
148
 
149
149
  end
150
- end
150
+ end
@@ -29,7 +29,8 @@ module TCellAgent
29
29
  :base_dir,
30
30
  :cache_filename,
31
31
  :js_agent_api_base_url,
32
- :js_agent_url
32
+ :js_agent_url,
33
+ :raise_exceptions
33
34
 
34
35
  attr_accessor :exp_config_settings
35
36
 
@@ -48,6 +49,8 @@ module TCellAgent
48
49
  @event_batch_size_limit = 25
49
50
  @event_time_limit_seconds = 55
50
51
 
52
+ @raise_exceptions = false
53
+
51
54
  read_config_using_env
52
55
  read_config_from_file(filename)
53
56
 
@@ -58,11 +61,11 @@ module TCellAgent
58
61
 
59
62
  begin
60
63
  @host_identifier = (Socket.gethostname() || "localhost")
61
- rescue Exception => e
64
+ rescue Exception
62
65
  @host_identifier = "host_identifier_not_found"
63
66
  end
64
67
  @uuid = SecureRandom.uuid
65
-
68
+
66
69
  FileUtils::mkdir_p File.dirname(@cache_filename)
67
70
  if @logging_options and @logging_options["filename"]
68
71
  FileUtils::mkdir_p File.dirname(@logging_options["filename"])
@@ -70,6 +73,7 @@ module TCellAgent
70
73
  FileUtils::mkdir_p File.dirname(@default_log_filename)
71
74
  end
72
75
  end
76
+
73
77
  def read_config_using_env
74
78
  @app_id = ENV["TCELL_APP_ID"]
75
79
  @api_key = ENV["TCELL_API_KEY"]
@@ -77,11 +81,15 @@ module TCellAgent
77
81
  @tcell_api_url = ENV["TCELL_API_URL"]
78
82
  @tcell_input_url = ENV["TCELL_INPUT_URL"]
79
83
  @demomode = ENV["TCELL_DEMOMODE"] || @demomode
84
+
80
85
  if @demomode
81
86
  @event_batch_size_limit = 2
82
87
  @event_time_limit_seconds = 5
83
88
  end
89
+
90
+ @raise_exceptions = [true, "true", "yes", "1"].include?(ENV["TCELL_RAISE_EXCEPTIONS"])
84
91
  end
92
+
85
93
  def read_config_from_file(filename)
86
94
  if File.file?(filename)
87
95
  #puts "tCell.io: Loading from file"
@@ -95,7 +103,7 @@ module TCellAgent
95
103
  @app_id ||= app_data["app_id"]
96
104
  @app_id ||= app_data["name"]
97
105
  @api_key ||= app_data["api_key"]
98
-
106
+
99
107
  # Optional
100
108
  @enabled = app_data.fetch("enabled", true)
101
109
  @preload_policy_filename = app_data.fetch("preload_policy_filename", nil)
@@ -157,5 +165,7 @@ module TCellAgent
157
165
  end # filename exist
158
166
  end #def read
159
167
  end # class
168
+
160
169
  TCellAgent.configuration ||= TCellAgent::Configuration.new
161
- end
170
+
171
+ end
@@ -35,8 +35,8 @@ module TCellAgent
35
35
  @database_filters = Hash.new{|h,k| h[k] = Set.new}
36
36
  end
37
37
  def add_response_db_filter(term, action_obj, database, schema, table, field)
38
- if (term != nil and term != '')
39
- self.database_filters[term].add([database, schema, table, field, action_obj])
38
+ if (term != nil && term != '' && term.to_s.length >= 5)
39
+ self.database_filters[term.to_s].add([database, schema, table, field, action_obj])
40
40
  end
41
41
  end
42
42
  def filter_body(body)
@@ -164,4 +164,4 @@ module TCellAgent
164
164
  end
165
165
  end
166
166
  end
167
- end
167
+ end
@@ -4,7 +4,9 @@ require 'logger'
4
4
  require 'tcell_agent/configuration'
5
5
 
6
6
  module TCellAgent
7
+
7
8
  @@logger_pid = Process.pid
9
+
8
10
  def self.loggingLevelFromString(levelString)
9
11
  if (levelString == "DEBUG")
10
12
  return Logger::DEBUG
@@ -17,14 +19,18 @@ module TCellAgent
17
19
  elsif (levelString == "FATAL")
18
20
  return Logger::FATAL
19
21
  end
22
+
20
23
  return Logger::ERROR
21
24
  end
25
+
22
26
  def self.logger
23
27
  if defined?(@logger) and @logger_pid == Process.pid
24
- return @logger
28
+ return @logger
25
29
  end
30
+
26
31
  @logger_pid = Process.pid
27
32
  logging_options = TCellAgent.configuration.logging_options
33
+
28
34
  if logging_options && logging_options["enabled"]
29
35
  FileUtils.mkdir_p 'tcell/logs'
30
36
  level = loggingLevelFromString(logging_options["level"])
@@ -35,15 +41,19 @@ module TCellAgent
35
41
  @logger.formatter = proc do |severity, datetime, progname, msg|
36
42
  # ISO 8601 format
37
43
  date_format = datetime.strftime("%Y-%m-%d %H:%M:%S,%L%z")
38
- "[#{date_format}] #{severity}: #{msg}\n"
44
+ "[#{date_format}] #{severity}[#{@logger_pid}]: #{msg}\n"
39
45
  end
46
+
40
47
  return @logger
41
48
  end
49
+
42
50
  logger = Logger.new(TCellAgent.configuration.default_log_filename)
43
51
  logger.level = Logger::ERROR
44
52
  return logger
45
53
  end
54
+
46
55
  def self.logger=(logger)
47
56
  @logger = logger
48
57
  end
58
+
49
59
  end
@@ -1,126 +1,90 @@
1
1
 
2
2
  module TCellAgent
3
3
  ActiveSupport.on_load(:action_controller) do
4
- ActionController::Base.class_eval do
5
- around_filter :tell_around_filter_routes
6
- def tell_around_filter_routes
7
- begin
8
- TCellAgent::Instrumentation.safe_block("Determining Rails Route ID") {
9
- route = Rails.application.routes.router.recognize(request) { |route, _| route }.first
10
- if route
11
- route_path = route[2].path.spec
12
- tcell_context = request.env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID]
13
- tcell_context.route_id = TCellAgent::SensorEvents::Util.calculateRouteId(request.method.downcase, route_path)
14
- end
15
- }
16
- yield
4
+
5
+ ActionController::Base.class_eval do
6
+
7
+ around_filter :tell_around_filter_routes
8
+ def tell_around_filter_routes
9
+ begin
10
+ TCellAgent::Instrumentation.safe_block("Determining Rails Route ID") {
11
+ route = Rails.application.routes.router.recognize(request) { |r, _| r }.first
12
+
13
+ if route
14
+ route_path = route[2].path.spec
15
+ tcell_context = request.env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID]
16
+ tcell_context.route_id = TCellAgent::SensorEvents::Util.calculateRouteId(request.method.downcase, route_path)
17
17
  end
18
- end
18
+ }
19
+ yield
20
+ end
21
+ end
22
+
19
23
  end
20
24
  end
21
25
  end
22
26
 
23
27
  module TCellAgent
28
+
24
29
  module Instrumentation
30
+
25
31
  module Rails
26
- def self.route_path_from_route(route)
27
- if (::Rails::VERSION::MAJOR == 4)
28
- begin
29
- route_path = "#{route[2].path.spec}"
30
- if (route_path.end_with?("(.:format)"))
31
- route_path = route_path.chomp("(.:format)")
32
- end
33
- return route_path
34
- rescue Exception => inner_excetion
35
- TCellAgent.logger.debug("Could not figure out path #{inner_excetion.message}")
36
- end
37
- end
38
- nil
39
- end
40
- def self.route_from_request(rails_request)
41
- if (rails_request.env["action_dispatch.request_id"] == nil)
42
- return nil
43
- end
44
- if (::Rails::VERSION::MAJOR == 4)
45
- begin
46
- recognized = ::Rails.application.routes.router.recognize(rails_request) { |route, _| route }
47
- if recognized
48
- return recognized.first
49
- end
50
- rescue Exception => inner_excetion
51
- TCellAgent.logger.debug("Could not figure out path #{inner_excetion.message}")
32
+ METHODS = ['GET','POST','PUT','DELETE','HEAD',
33
+ 'PATCH','TRACE','CONNECT','OPTIONS']
34
+
35
+ def self.instrument_route(route)
36
+ if (route.constraints.has_key? :request_method)
37
+ route_path = "#{route.path.spec}"
38
+ if (route_path.end_with?("(.:format)"))
39
+ route_path = route_path.chomp("(.:format)")
52
40
  end
41
+
42
+ route_destination = route.defaults.to_json.to_s
43
+
44
+ route_methods = METHODS.select { |x| route.verb.match(x) }
45
+ route_methods.each { |route_method|
46
+ route_id = TCellAgent::SensorEvents::Util.calculateRouteId(route_method.downcase, route.path.spec)
47
+ TCellAgent.send_event(
48
+ TCellAgent::SensorEvents::AppRoutesSensorEvent.new(
49
+ route_path, route_method, route_id, nil, route_destination
50
+ )
51
+ )
52
+ }
53
53
  end
54
- nil
55
54
  end
56
- def self.route_id_from_request(active_request)
57
- route = route_from_request(active_request)
58
- if route != nil
59
- route_path = route_path_from_route(route)
60
- if route_path != nil
61
- return TCellAgent::SensorEvents::Util.calculateRouteId(active_request.request_method.downcase, route_path)
62
- end
55
+
56
+ def self.instrument_routes
57
+ ::Rails.application.routes.routes.each do |route|
58
+ self.instrument_route(route)
63
59
  end
64
- nil
65
- end
66
- def self.get_routes
67
60
  end
61
+
68
62
  if (::Rails::VERSION::MAJOR == 3)
69
63
  ActionDispatch::Routing::RouteSet.class_eval do
70
64
  alias_method :original_add_route, :add_route
71
65
  def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true)
72
- methods = ['GET','POST','PUT','DELETE','HEAD',
73
- 'PATCH','TRACE','CONNECT','OPTIONS']
74
66
  route = original_add_route(app, conditions, requirements, defaults, name, anchor)
75
- if (route.constraints.has_key? :request_method)
76
- route_path = "#{route.path.spec}"
77
- if (route_path.end_with?("(.:format)"))
78
- route_path = route_path.chomp("(.:format)")
79
- end
80
- route_destination = route.defaults.to_json.to_s
81
- route_params = route.path.required_names
82
- route_methods = methods.select {|x| route.verb.match(x) }
83
- route_methods.each { |route_method|
84
- route_id = TCellAgent::SensorEvents::Util.calculateRouteId(route_method.downcase, route.path.spec)
85
- TCellAgent.send_event(
86
- TCellAgent::SensorEvents::AppRoutesSensorEvent.new(
87
- route_path, route_method, route_id, nil, route_destination
88
- )
89
- )
90
- }
91
- end
67
+
68
+ TCellAgent::Instrumentation::Rails.instrument_route(route)
69
+
92
70
  route
93
71
  end
94
72
  end
95
73
  end
74
+
96
75
  if (::Rails::VERSION::MAJOR == 4)
97
76
  ActionDispatch::Journey::Routes.class_eval do
98
77
  alias_method :original_add_route, :add_route
99
78
  def add_route(app, path, conditions, defaults, name = nil)
100
- methods = ['GET','POST','PUT','DELETE','HEAD',
101
- 'PATCH','TRACE','CONNECT','OPTIONS']
102
- route = original_add_route(app, path, conditions, defaults, name)
103
- if (route.constraints.has_key? :request_method)
104
- route_path = "#{route.path.spec}"
105
- if (route_path.end_with?("(.:format)"))
106
- route_path = route_path.chomp("(.:format)")
107
- end
108
- route_destination = route.defaults.to_json.to_s
109
- route_params = route.path.required_names
110
- route_methods = methods.select {|x| route.verb.match(x) }
111
- route_methods.each { |route_method|
112
- route_id = TCellAgent::SensorEvents::Util.calculateRouteId(route_method.downcase, route.path.spec)
113
- TCellAgent.send_event(
114
- TCellAgent::SensorEvents::AppRoutesSensorEvent.new(
115
- route_path, route_method, route_id, nil, route_destination
116
- )
117
- )
118
- }
119
- end
79
+ route = original_add_route(app, path, conditions, defaults, name)
80
+
81
+ TCellAgent::Instrumentation::Rails.instrument_route(route)
82
+
120
83
  route
121
84
  end
122
85
  end
123
- end #endif rails version = 4
86
+ end
87
+
124
88
  end
125
89
  end
126
- end
90
+ end
@@ -0,0 +1,59 @@
1
+ unless Puma.cli_config.options[:preload_app]
2
+ # this ensures instrumentation runs for preload_app = false.
3
+ # Instrumentation will run for each worker but there's
4
+ # nothing we can do about that (Unicorn's preload_app behaves the same way)
5
+ Puma::Server.class_eval do
6
+
7
+ alias_method :original_run, :run
8
+ def run(background=true)
9
+ TCellAgent.run_instrumentation("Puma Cluster Mode (Worker)")
10
+
11
+ original_run(background)
12
+ end
13
+
14
+ end
15
+
16
+
17
+ else
18
+
19
+ if Puma.cli_config.options[:workers] == 0
20
+ # Puma is running in single mode, so run both the initial instrumentation and
21
+ # start the agent
22
+ Puma::Runner.class_eval do
23
+
24
+ alias_method :original_start_server, :start_server
25
+ def start_server
26
+ TCellAgent.run_instrumentation("Puma Single Mode")
27
+
28
+ original_start_server
29
+ end
30
+
31
+ end
32
+
33
+ else
34
+
35
+ # Runs initial instrumentation only once on the master process
36
+ puma_server_starting = Proc.new { TCellAgent.run_instrumentation("Puma Cluster Mode") }
37
+ Puma.cli_config.options[:before_fork].push(puma_server_starting)
38
+
39
+ # Each puma worker still needs the agent started but no need to run
40
+ # initial instrumentation again
41
+ Puma::Server.class_eval do
42
+
43
+ alias_method :original_run, :run
44
+ def run(background=true)
45
+ begin
46
+ TCellAgent.logger.debug("Instrumenting: Puma Cluster Mode (Worker)")
47
+ TCellAgent.thread_agent.start
48
+ rescue Exception => e
49
+ TCellAgent.logger.error("Could not start thread agent. #{e.message}")
50
+ end
51
+
52
+ original_run(background)
53
+ end
54
+
55
+ end
56
+ end
57
+
58
+ end
59
+
@@ -0,0 +1,20 @@
1
+ # This file gets included when the web server is launched through
2
+ # `bundle exec rails s` command. The appropriate server will be
3
+ # launched through Rack::Server interface
4
+
5
+ require("tcell_agent/servers/unicorn") if defined?(Unicorn::HttpServer)
6
+ require("tcell_agent/servers/webrick") if defined?(Rack::Handler::WEBrick)
7
+ require("tcell_agent/servers/thin") if defined?(Thin::Server)
8
+
9
+ if defined?(Puma::Server)
10
+ Puma::Server.class_eval do
11
+
12
+ alias_method :original_run, :run
13
+ def run(background=true)
14
+ TCellAgent.run_instrumentation("Puma Single Mode")
15
+
16
+ original_run(background)
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ Thin::Server.class_eval do
2
+
3
+ alias_method :original_start, :start
4
+ def start
5
+ TCellAgent.run_instrumentation("Thin Server")
6
+
7
+ original_start
8
+ end
9
+
10
+ end
@@ -0,0 +1,27 @@
1
+ # this ensures instrumentation runs for both preload_app = true and preload_app = false
2
+ # when preload_app = false, instrumentation will run for each worker but there's
3
+ # nothing we can do about that (Puma's preload_app behaves the same way)
4
+ TCellAgent.run_instrumentation("Unicorn")
5
+
6
+ Unicorn::HttpServer.class_eval do
7
+
8
+ # this only runs when preload_app=true because when preload_app=false
9
+ # the gems aren't loaded early enough for tcell to override
10
+ # the class definitions
11
+ alias original_init_worker_process init_worker_process
12
+ def init_worker_process(work)
13
+ start_process = original_init_worker_process(work)
14
+
15
+ begin
16
+ TCellAgent.thread_agent.policy_polling_worker_mutex = Mutex.new
17
+ TCellAgent.thread_agent.policy_polling_thread = nil
18
+ TCellAgent.thread_agent.start
19
+
20
+ rescue Exception => e
21
+ TCellAgent.logger.error("Could not start thread agent. #{e.message}")
22
+ end
23
+
24
+ start_process
25
+ end
26
+
27
+ end
@@ -0,0 +1,13 @@
1
+ Rack::Handler::WEBrick.class_eval do
2
+
3
+ class << self
4
+ alias_method :original_run, :run
5
+ def run(app, options={})
6
+ TCellAgent.run_instrumentation("WEBrick")
7
+
8
+ original_run(app, options)
9
+ end
10
+ end
11
+
12
+ end
13
+
@@ -6,101 +6,89 @@ require 'tcell_agent/configuration'
6
6
  require 'thread'
7
7
 
8
8
  module TCellAgent
9
- def self.run_instrumentation
10
- TCellAgent.logger.debug("Instrumenting")
9
+
10
+ def self.load_route_instrumentation
11
11
  if (TCellAgent.configuration.enabled && TCellAgent.configuration.instrument_for_events)
12
- require 'tcell_agent/rails' if defined?(Rails)
13
- require 'tcell_agent/sinatra' if defined?(Sinatra)
12
+ require 'tcell_agent/rails' if defined?(Rails)
13
+ require 'tcell_agent/sinatra' if defined?(Sinatra)
14
14
  end
15
15
  end
16
- end
17
16
 
18
- # creates a fork and pipes a string from parent to child
19
- if File.basename($0) != 'rake'
20
- tcell_server = ENV["TCELL_AGENT_SERVER"]
21
- if tcell_server == nil
22
- if (File.basename($0) == 'rails' &&
23
- Rack::Handler.default &&
24
- ((defined?(Thin) && (Rack::Handler.default == Rack::Handler::Thin)) ||
25
- (defined?(WEBrick) && (Rack::Handler.default == Rack::Handler::WEBrick))))
26
- tcell_server = "thin"
27
- elsif defined?(Puma) && defined?(Puma.cli_config) && Puma.cli_config.options[:workers] > 1
28
- tcell_server = "puma"
29
- elsif defined?(Unicorn)
30
- tcell_server = "unicorn"
31
- elsif defined?(Puma)
32
- tcell_server = "thin"
33
- else
34
- puts "[tCell.io] **********************************************************************"
35
- puts "[tCell.io] Server used to launch rails not recognized."
36
- puts "[tCell.io] You can override this with the env variable"
37
- puts "[tCell.io] TCELL_AGENT_SERVER=thin|puma|unicorn"
38
- puts "[tCell.io] **********************************************************************"
17
+ def self.run_instrumentation(server_name)
18
+ self.load_route_instrumentation
19
+
20
+ begin
21
+ TCellAgent.logger.debug("Instrumenting: #{server_name}")
22
+ TCellAgent.thread_agent.start
23
+ rescue Exception => e
24
+ TCellAgent.logger.error("Could not start thread agent. #{e.message}")
39
25
  end
40
- end
41
- if tcell_server != nil
42
- if (tcell_server == "mock")
43
- elsif (tcell_server == "thin" || tcell_server == "webrick")
44
- TCellAgent.run_instrumentation
45
- TCellAgent.logger.debug("Initializing background thread: Thin or webrick")
26
+
27
+ Thread.abort_on_exception = TCellAgent.configuration.raise_exceptions
28
+ Thread.new do
46
29
  begin
47
- TCellAgent.thread_agent.start
48
- rescue Exception => e
49
- TCellAgent.logger.error("Could not start worker.", e.message)
30
+ event = TCellAgent::SensorEvents::ServerAgentDetailsSensorEvent.new
31
+ TCellAgent.send_event(event)
32
+
33
+ rescue Exception => te
34
+ TCellAgent.logger.error("Exception sending server agent details: #{te.message}")
35
+ TCellAgent.logger.debug(te.backtrace)
50
36
  end
51
- elsif (tcell_server == "puma")
52
- TCellAgent.run_instrumentation
53
- TCellAgent.logger.debug("Initializing background thread: Puma Preload")
37
+
54
38
  begin
55
- TCellAgent.thread_agent.start
56
- rescue Exception => e
57
- TCellAgent.logger.error("Could not start worker.", e.message)
39
+ event = TCellAgent::SensorEvents::ServerAgentPackagesSensorEvent.new
40
+ TCellAgent.send_event(event)
41
+ rescue Exception => te
42
+ TCellAgent.logger.error("Exception sending server agent packages: #{te.message}")
43
+ TCellAgent.logger.debug(te.backtrace)
58
44
  end
59
- # preload app
60
- puma_worker_start = Proc.new do
45
+
46
+ if (TCellAgent.configuration.enabled && TCellAgent.configuration.instrument_for_events)
61
47
  begin
62
- TCellAgent.thread_agent.start
48
+ TCellAgent::Instrumentation::Rails.instrument_routes if defined?(Rails)
49
+
63
50
  rescue Exception => e
64
- TCellAgent.logger.error("Could not start worker." + e.message)
65
- end
66
- end
67
- Puma.cli_config.options[:before_worker_boot].push(puma_worker_start)
68
- elsif (tcell_server == "unicorn")
69
- TCellAgent.run_instrumentation
70
- TCellAgent.logger.debug("Initializing background thread: Unicorn")
71
- begin
72
- TCellAgent.thread_agent.start
73
- rescue Exception => e
74
- TCellAgent.logger.error("Could not start worker.", e.message)
75
- end
76
- class Unicorn::HttpServer
77
- alias _tcell_start spawn_missing_workers
78
- def spawn_missing_workers
79
- TCellAgent.logger.debug("Stopping (pre-spawn) agent " + Process.pid.to_s)
80
- return _tcell_start
81
- end
82
- alias old_init_worker_process init_worker_process
83
- def init_worker_process(work)
84
- start_process = old_init_worker_process(work)
85
- begin
86
- TCellAgent.logger.debug("Starting (post-spawn) agent " + Process.pid.to_s)
87
- TCellAgent.thread_agent.policy_polling_worker_mutex = Mutex.new
88
- TCellAgent.thread_agent.policy_polling_thread = nil
89
- TCellAgent.thread_agent.start
90
- rescue Exception => e
91
- TCellAgent.logger.error("Could not start worker.")
92
- end
93
- start_process
51
+ if TCellAgent.configuration.raise_exceptions
52
+ raise e
53
+
54
+ else
55
+ TCellAgent.logger.error("Something went wrong instrumenting the routes")
56
+ TCellAgent.logger.debug(e.inspect)
57
+ TCellAgent.logger.debug(e.backtrace)
58
+ end
94
59
  end
95
60
  end
96
- else
97
- puts "[tCell.io] **********************************************************************"
98
- puts "[tCell.io] Unknown Server for starting rails: #{tcell_server}"
99
- puts "[tCell.io] You can override this with the env variable"
100
- puts "[tCell.io] TCELL_AGENT_SERVER=thin|puma|unicorn"
101
- puts "[tCell.io] **********************************************************************"
102
61
  end
62
+
103
63
  end
64
+
104
65
  end
105
66
 
67
+ tcell_server = ENV["TCELL_AGENT_SERVER"]
68
+
69
+ if (!(tcell_server && tcell_server == "mock"))
70
+
71
+ if (tcell_server && tcell_server == "webrick") || defined?(Rails::Server)
72
+
73
+ require("tcell_agent/servers/rails_server")
74
+
75
+ elsif (tcell_server && tcell_server == "thin") || defined?(Thin)
106
76
 
77
+ require("tcell_agent/servers/thin")
78
+
79
+ elsif (tcell_server && tcell_server == "puma") || defined?(Puma)
80
+
81
+ require("tcell_agent/servers/puma")
82
+
83
+ elsif (tcell_server && tcell_server == "unicorn") || defined?(Unicorn)
84
+
85
+ require("tcell_agent/servers/unicorn")
86
+
87
+ else
88
+ puts "[tCell.io] **********************************************************************"
89
+ puts "[tCell.io] Server used to launch rails not recognized."
90
+ puts "[tCell.io] You can override this with the env variable"
91
+ puts "[tCell.io] TCELL_AGENT_SERVER=thin|puma|unicorn"
92
+ puts "[tCell.io] **********************************************************************"
93
+ end
94
+ end
@@ -5,7 +5,9 @@ require 'thread'
5
5
  require 'logger'
6
6
 
7
7
  module TCellAgent
8
+
8
9
  class BoundedQueue
10
+
9
11
  def initialize(max_size = :infinite)
10
12
  @lock = Mutex.new
11
13
  @items = []
@@ -18,6 +20,7 @@ module TCellAgent
18
20
  timeout_policy ||= -> do
19
21
  raise "Push timed out"
20
22
  end
23
+
21
24
  wait_for_condition(
22
25
  @space_available,
23
26
  ->{!full?},
@@ -35,8 +38,12 @@ module TCellAgent
35
38
  @item_available,
36
39
  ->{@items.any?},
37
40
  timeout,
38
- timeout_policy) do
39
- @items.shift
41
+ timeout_policy) do
42
+
43
+ item = @items.shift
44
+ @space_available.signal
45
+
46
+ item
40
47
  end
41
48
  end
42
49
 
@@ -45,43 +52,56 @@ module TCellAgent
45
52
  @max_size <= @items.size
46
53
  end
47
54
 
55
+ def size
56
+ @items.size
57
+ end
58
+
48
59
  private
49
60
 
50
- def wait_for_condition(
51
- cv, condition_predicate, timeout=:never, timeout_policy=->{nil})
61
+ def wait_for_condition(cv, condition_predicate, timeout=:never, timeout_policy=->{nil})
62
+
52
63
  deadline = timeout == :never ? :never : Time.now + timeout
64
+
53
65
  @lock.synchronize do
66
+
54
67
  loop do
55
68
  cv_timeout = timeout == :never ? nil : deadline - Time.now
69
+
56
70
  if !condition_predicate.call && cv_timeout.to_f >= 0
57
- cv.wait(@lock, cv_timeout)
71
+ cv.wait(@lock, cv_timeout)
58
72
  end
73
+
59
74
  if condition_predicate.call
60
75
  return yield
76
+
61
77
  elsif deadline == :never || deadline > Time.now
62
78
  next
79
+
63
80
  else
64
81
  return timeout_policy.call
65
82
  end
66
83
  end
84
+
67
85
  end
68
86
  end
69
87
  end
70
88
 
71
89
  class QueueWithTimeout
90
+
72
91
  def initialize
73
92
  @mutex = Mutex.new
74
93
  @queue = []
75
94
  @response_time_table = {}
76
95
  @recieved = ConditionVariable.new
77
96
  end
78
-
97
+
79
98
  def <<(x)
80
99
  @mutex.synchronize do
81
100
  @queue << x
82
101
  @recieved.signal
83
102
  end
84
103
  end
104
+
85
105
  def add_response_time(route_id, response_time)
86
106
  @mutex.synchronize do
87
107
  if (route_id == nil || route_id == "")
@@ -94,21 +114,25 @@ module TCellAgent
94
114
  @response_time_table[route_id]["t"] = ((@response_time_table[route_id].fetch("t",0)*(@response_time_table[route_id]["c"]-1)) + response_time) / @response_time_table[route_id]["c"]
95
115
  end
96
116
  end
117
+
97
118
  def length
98
119
  return @queue.length
99
120
  end
121
+
100
122
  def get_response_time_table
101
123
  return @response_time_table
102
124
  end
125
+
103
126
  def reset_response_time_table
104
127
  @mutex.synchronize do
105
128
  @response_time_table = {}
106
129
  end
107
130
  end
131
+
108
132
  def pop(non_block = false)
109
133
  pop_with_timeout(non_block ? 0 : nil)
110
134
  end
111
-
135
+
112
136
  def pop_with_timeout(timeout = nil)
113
137
  @mutex.synchronize do
114
138
  if @queue.empty?
@@ -121,4 +145,4 @@ module TCellAgent
121
145
  end
122
146
  end
123
147
  end
124
- end
148
+ end
@@ -1,5 +1,5 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
 
3
3
  module TCellAgent
4
- VERSION = "0.2.5"
4
+ VERSION = "0.2.6"
5
5
  end
@@ -127,6 +127,8 @@ module TCellAgent
127
127
  context.add_response_db_filter("tim123123my", action, "don", "sam", "tim", "fred")
128
128
  context.add_response_db_filter("ti21312mmy", action, "don", "sam", "tim", "fred")
129
129
  context.add_response_db_filter("ti123123mmy", action, "don", "sam", "tim", "fred")
130
+ context.add_response_db_filter(10233234, action, "don", "sam", "tim", "fred")
131
+ context.add_response_db_filter(true, action, "don", "sam", "tim", "fred")
130
132
  body = "this is about timmy1 3123123."
131
133
  TCellAgent.empty_event_queue
132
134
  context.filter_body(body)
@@ -146,6 +148,8 @@ module TCellAgent
146
148
  context.add_response_db_filter("tim123123my", action, "don", "sam", "tim", "fred")
147
149
  context.add_response_db_filter("ti21312mmy", action, "don", "sam", "tim", "fred")
148
150
  context.add_response_db_filter("ti123123mmy", action, "don", "sam", "tim", "fred")
151
+ context.add_response_db_filter(10233234, action, "don", "sam", "tim", "fred")
152
+ context.add_response_db_filter(true, action, "don", "sam", "tim", "fred")
149
153
  body = "this is about timmy1 3123123."
150
154
  TCellAgent.empty_event_queue
151
155
  context.filter_body(body)
@@ -167,6 +171,8 @@ module TCellAgent
167
171
  context.add_response_db_filter("tim123123my", action, "don", "sam", "tim", "fred")
168
172
  context.add_response_db_filter("ti21312mmy", action, "don", "sam", "tim", "fred")
169
173
  context.add_response_db_filter("ti123123mmy", action, "don", "sam", "tim", "fred")
174
+ context.add_response_db_filter(10233234, action, "don", "sam", "tim", "fred")
175
+ context.add_response_db_filter(true, action, "don", "sam", "tim", "fred")
170
176
  body = "this is about timmy1 3123123."
171
177
  TCellAgent.empty_event_queue
172
178
  context.filter_log(body)
@@ -186,6 +192,8 @@ module TCellAgent
186
192
  context.add_response_db_filter("tim123123my", action, "don", "sam", "tim", "fred")
187
193
  context.add_response_db_filter("ti21312mmy", action, "don", "sam", "tim", "fred")
188
194
  context.add_response_db_filter("ti123123mmy", action, "don", "sam", "tim", "fred")
195
+ context.add_response_db_filter(10233234, action, "don", "sam", "tim", "fred")
196
+ context.add_response_db_filter(true, action, "don", "sam", "tim", "fred")
189
197
  body = "this is about timmy1 3123123."
190
198
  TCellAgent.empty_event_queue
191
199
  context.filter_log(body)
@@ -195,4 +203,4 @@ module TCellAgent
195
203
  end
196
204
  end
197
205
  end
198
- end
206
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe TCellAgent::BoundedQueue do
4
+
5
+ describe "#full?" do
6
+ it "should be true when the queue is full" do
7
+ queue = TCellAgent::BoundedQueue.new(1)
8
+ queue.push("one")
9
+ expect(queue.full?).to eq(true)
10
+ end
11
+
12
+ it "should return false when the queue is not full" do
13
+ queue = TCellAgent::BoundedQueue.new(1)
14
+ expect(queue.full?).to eq(false)
15
+ end
16
+ end
17
+
18
+ describe "#push" do
19
+ context "pushing to a queue with space available" do
20
+ it "should push the item" do
21
+ queue = TCellAgent::BoundedQueue.new(1)
22
+ queue.push("one")
23
+
24
+ expect(queue.size).to eq(1)
25
+ end
26
+ end
27
+
28
+ context "pushing to a full queue" do
29
+ it "should not be possible to push anymore items" do
30
+ queue = TCellAgent::BoundedQueue.new(1)
31
+ queue.push("one")
32
+
33
+ expect(queue.size).to eq(1)
34
+ expect(queue.full?).to eq(true)
35
+
36
+ expect {
37
+ queue.push("two", 0.1)
38
+ }.to raise_error(RuntimeError)
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ describe "#pop" do
45
+ context "popping from an empty queue" do
46
+ it "should return nil when there are no items" do
47
+ queue = TCellAgent::BoundedQueue.new(1)
48
+ expect(queue.size).to eq(0)
49
+
50
+ expect(queue.pop(0.1)).to eq(nil)
51
+ end
52
+ end
53
+ end
54
+
55
+ end
data/spec/spec_helper.rb CHANGED
@@ -21,4 +21,4 @@ module TCellAgent
21
21
  end
22
22
  end
23
23
 
24
- TCellAgent.run_instrumentation
24
+ TCellAgent.load_route_instrumentation
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tcell_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garrett
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-20 00:00:00.000000000 Z
11
+ date: 2016-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -117,20 +117,24 @@ executables:
117
117
  extensions: []
118
118
  extra_rdoc_files: []
119
119
  files:
120
+ - LICENSE
121
+ - README.md
120
122
  - Rakefile
123
+ - bin/tcell_agent
124
+ - lib/tcell_agent.rb
125
+ - lib/tcell_agent/agent.rb
121
126
  - lib/tcell_agent/agent/event_processor.rb
122
127
  - lib/tcell_agent/agent/fork_pipe_manager.rb
123
128
  - lib/tcell_agent/agent/policy_manager.rb
124
129
  - lib/tcell_agent/agent/policy_types.rb
125
130
  - lib/tcell_agent/agent/route_manager.rb
126
131
  - lib/tcell_agent/agent/static_agent.rb
127
- - lib/tcell_agent/agent.rb
128
132
  - lib/tcell_agent/api.rb
133
+ - lib/tcell_agent/appsensor.rb
129
134
  - lib/tcell_agent/appsensor/cmdi.rb
130
135
  - lib/tcell_agent/appsensor/path_traversal.rb
131
136
  - lib/tcell_agent/appsensor/sqli.rb
132
137
  - lib/tcell_agent/appsensor/xss.rb
133
- - lib/tcell_agent/appsensor.rb
134
138
  - lib/tcell_agent/authlogic.rb
135
139
  - lib/tcell_agent/configuration.rb
136
140
  - lib/tcell_agent/devise.rb
@@ -145,6 +149,7 @@ files:
145
149
  - lib/tcell_agent/policies/http_tx_policy.rb
146
150
  - lib/tcell_agent/policies/login_fraud_policy.rb
147
151
  - lib/tcell_agent/policies/secure_headers_policy.rb
152
+ - lib/tcell_agent/rails.rb
148
153
  - lib/tcell_agent/rails/auth/authlogic.rb
149
154
  - lib/tcell_agent/rails/auth/devise.rb
150
155
  - lib/tcell_agent/rails/dlp.rb
@@ -154,7 +159,6 @@ files:
154
159
  - lib/tcell_agent/rails/middleware/headers_middleware.rb
155
160
  - lib/tcell_agent/rails/routes.rb
156
161
  - lib/tcell_agent/rails/settings_reporter.rb
157
- - lib/tcell_agent/rails.rb
158
162
  - lib/tcell_agent/routes/table.rb
159
163
  - lib/tcell_agent/sensor_events/app_config.rb
160
164
  - lib/tcell_agent/sensor_events/app_sensor.rb
@@ -168,12 +172,16 @@ files:
168
172
  - lib/tcell_agent/sensor_events/util/redirect_utils.rb
169
173
  - lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb
170
174
  - lib/tcell_agent/sensor_events/util/utils.rb
175
+ - lib/tcell_agent/servers/puma.rb
176
+ - lib/tcell_agent/servers/rails_server.rb
177
+ - lib/tcell_agent/servers/thin.rb
178
+ - lib/tcell_agent/servers/unicorn.rb
179
+ - lib/tcell_agent/servers/webrick.rb
171
180
  - lib/tcell_agent/sinatra.rb
172
181
  - lib/tcell_agent/start_background_thread.rb
173
182
  - lib/tcell_agent/userinfo.rb
174
183
  - lib/tcell_agent/utils/queue_with_timeout.rb
175
184
  - lib/tcell_agent/version.rb
176
- - lib/tcell_agent.rb
177
185
  - spec/controllers/application_controller.rb
178
186
  - spec/lib/tcell_agent/api/api_spec.rb
179
187
  - spec/lib/tcell_agent/appsensor_spec.rb
@@ -192,13 +200,11 @@ files:
192
200
  - spec/lib/tcell_agent/sensor_events/dlp_spec.rb
193
201
  - spec/lib/tcell_agent/sensor_events/util/redirect_utils_spec.rb
194
202
  - spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb
203
+ - spec/lib/tcell_agent/utils/bounded_queue_spec.rb
195
204
  - spec/lib/tcell_agent_spec.rb
196
205
  - spec/resources/normal_config.json
197
206
  - spec/spec_helper.rb
198
- - README.md
199
- - LICENSE
200
207
  - tcell_agent.gemspec
201
- - bin/tcell_agent
202
208
  homepage: https://www.tcell.io
203
209
  licenses:
204
210
  - Copyright (c) 2015 tCell.io (see LICENSE file)
@@ -221,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
221
227
  version: '0'
222
228
  requirements: []
223
229
  rubyforge_project:
224
- rubygems_version: 2.0.14
230
+ rubygems_version: 2.4.8
225
231
  signing_key:
226
232
  specification_version: 4
227
233
  summary: tCell.io Agent for Rails & Sinatra
@@ -244,6 +250,7 @@ test_files:
244
250
  - spec/lib/tcell_agent/sensor_events/dlp_spec.rb
245
251
  - spec/lib/tcell_agent/sensor_events/util/redirect_utils_spec.rb
246
252
  - spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb
253
+ - spec/lib/tcell_agent/utils/bounded_queue_spec.rb
247
254
  - spec/lib/tcell_agent_spec.rb
248
255
  - spec/resources/normal_config.json
249
256
  - spec/spec_helper.rb