Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
netuitive_ruby_api 1.1.0 (2016-10-21)
-------------------------
* caching samples/events for the purpose of batching calls to the daemon
* error proofing

netuitive_ruby_api 1.0.1 (2016-10-17)
-------------------------
* refactoring of classes into gem namespace to avoid collisions
Expand Down
24 changes: 18 additions & 6 deletions config/agent.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
#all are configurable using environment variables
logLocation: #absolute path of log file. leave blank for default location in the gem directory. environment variable: NETUITIVE_RUBY_LOG_LOCATION
logAge: daily #Number of old log files to keep, or frequency of rotation (daily, weekly or monthly). environment variable: NETUITIVE_RUBY_LOG_AGE
logSize: #Maximum logfile size in bytes (only applies when shift_age is a number). environment variable: NETUITIVE_RUBY_LOG_SIZE
debugLevel: info #options (in ascending order of debugness) are: error, info, debug. environment variable: NETUITIVE_RUBY_DEBUG_LEVEL
netuitivedAddr: localhost #environment variable: NETUITIVE_RUBY_NETUITIVED_ADDR
netuitivedPort: 8875 #environment variable: NETUITIVE_RUBY_NETUITIVED_PORT
#log properties
logLocation: #NETUITIVE_RUBY_LOG_LOCATION absolute path of log file. leave blank for default location in the gem directory.
logAge: daily #NETUITIVE_RUBY_LOG_AGE Number of old log files to keep, or frequency of rotation (daily, weekly or monthly).
logSize: #NETUITIVE_RUBY_LOG_SIZE Maximum logfile size in bytes (only applies when shift_age is a number).
debugLevel: error #NETUITIVE_RUBY_DEBUG_LEVEL options (in ascending order of debugness) are: error, info, debug.

#netuitived connection properties
netuitivedAddr: localhost #NETUITIVE_RUBY_NETUITIVED_ADDR
netuitivedPort: 8875 #NETUITIVE_RUBY_NETUITIVED_PORT

#cache properties
#the point of the cache is to be as *small* as possible while still avoiding excessive delivery thread growth.
sampleCacheEnabled: true #NETUITIVE_RUBY_SAMPLE_CACHE_ENABLED
sampleCacheSize: 50 #NETUITIVE_RUBY_SAMPLE_CACHE_SIZE maximum number of samples to be cached before being sent to netuitived
sampleCacheInterval: 10 #NETUITIVE_RUBY_SAMPLE_CACHE_INTERVAL interval (in seconds) to send cached samples to netuitived
eventCacheEnabled: false #NETUITIVE_RUBY_EVENT_CACHE_ENABLED
eventCacheSize: 50 #NETUITIVE_RUBY_SAMPLE_CACHE_SIZE maximum number of events to be cached before being sent to netuitived
eventCacheInterval: 10 #NETUITIVE_RUBY_SAMPLE_CACHE_INTERVAL interval (in seconds) to send cached events to netuitived
89 changes: 56 additions & 33 deletions lib/netuitive_ruby_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,76 +3,99 @@
require 'drb/drb'
require 'netuitive_ruby_api/config_manager'
require 'netuitive_ruby_api/netuitive_logger'
require 'netuitive_ruby_api/error_logger'
require 'netuitive_ruby_api/data_cache'
require 'netuitive_ruby_api/data_manager'
require 'netuitive_ruby_api/event_schedule'
require 'netuitive_ruby_api/sample_schedule'

class NetuitiveRubyAPI
class << self
def setup(server)
@@netuitivedServer = server
attr_accessor :data_manager
attr_accessor :netuitivedServer
attr_reader :pid
def setup
@pid = Process.pid
NetuitiveRubyApi::ConfigManager.load_config
NetuitiveRubyApi::NetuitiveLogger.setup
NetuitiveRubyApi::ConfigManager.read_config
NetuitiveRubyApi::ErrorLogger.guard('error during api setup') do
server_uri = "druby://#{NetuitiveRubyApi::ConfigManager.netuitivedAddr}:#{NetuitiveRubyApi::ConfigManager.netuitivedPort}".freeze
DRb.start_service
drb_server = DRbObject.new_with_uri(server_uri)
data_manager = NetuitiveRubyApi::DataManager.new
data_manager.data_cache = NetuitiveRubyApi::DataCache.new
data_manager.sample_cache_enabled = NetuitiveRubyApi::ConfigManager.sample_cache_enabled
data_manager.sample_cache_size = NetuitiveRubyApi::ConfigManager.sample_cache_size
data_manager.sample_cache_interval = NetuitiveRubyApi::ConfigManager.sample_cache_interval
data_manager.event_cache_enabled = NetuitiveRubyApi::ConfigManager.event_cache_enabled
data_manager.event_cache_size = NetuitiveRubyApi::ConfigManager.event_cache_size
data_manager.event_cache_interval = NetuitiveRubyApi::ConfigManager.event_cache_interval
data_manager.netuitived_server = drb_server
@netuitivedServer = drb_server
@data_manager = data_manager
NetuitiveRubyApi::SampleSchedule.stop
NetuitiveRubyApi::EventSchedule.stop
NetuitiveRubyApi::SampleSchedule.start(NetuitiveRubyApi::ConfigManager.sample_cache_interval) if NetuitiveRubyApi::ConfigManager.sample_cache_enabled
NetuitiveRubyApi::EventSchedule.start(NetuitiveRubyApi::ConfigManager.event_cache_interval) if NetuitiveRubyApi::ConfigManager.event_cache_enabled
NetuitiveRubyApi::NetuitiveLogger.log.info 'netuitive_ruby_api finished setup'
end
end

def flush_samples
@data_manager.flush_samples
end

def check_restart
NetuitiveRubyApi::NetuitiveLogger.log.debug "stored pid: #{@pid}, process pid: #{Process.pid}"
return if @pid == Process.pid
Thread.new { NetuitiveRubyAPI.setup }
end

def netuitivedServer
@@netuitivedServer
def flush_events
@data_manager.flush_events
end

def send_metrics
server_interaction { netuitivedServer.sendMetrics }
netuitivedServer.sendMetrics
end

def add_sample(metric_id, val)
server_interaction { netuitivedServer.addSample(metric_id, val) }
@data_manager.add_sample(metric_id, val)
end

def add_counter_sample(metric_id, val)
server_interaction { netuitivedServer.addCounterSample(metric_id, val) }
@data_manager.add_counter_sample(metric_id, val)
end

def aggregate_metric(metric_id, val)
server_interaction { netuitivedServer.aggregateMetric(metric_id, val) }
@data_manager.aggregate_metric(metric_id, val)
end

def aggregate_counter_metric(metric_id, val)
server_interaction { netuitivedServer.aggregateCounterMetric(metric_id, val) }
@data_manager.aggregate_counter_metric(metric_id, val)
end

def clear_metrics
server_interaction { netuitivedServer.clearMetrics }
netuitivedServer.clearMetrics
end

def interval
netuitivedServer.interval # synchronous for return value
end

def event(message, timestamp = Time.new, title = 'Ruby Event', level = 'Info', source = 'Ruby Agent', type = 'INFO', tags = nil)
server_interaction { netuitivedServer.event(message, timestamp, title, level, source, type, tags) }
@data_manager.event(message, timestamp, title, level, source, type, tags)
end

def exception_event(exception, klass = nil, tags = nil)
server_interaction do
hash = { message: exception.message }
hash[:backtrace] = exception.backtrace.join("\n\t") if (defined? exception.backtrace) && !exception.backtrace.nil?
netuitivedServer.exceptionEvent(hash, klass, tags)
end
@data_manager.exception_event(exception, klass, tags)
end

def stop_server
server_interaction { netuitivedServer.stopServer }
end

def server_interaction
Thread.new do
begin
yield
rescue => e
NetuitiveRubyApi::NetuitiveLogger.log.error "unable to connect to netuitived: message:#{e.message} backtrace:#{e.backtrace}"
end
end
netuitivedServer.stopServer
end
end
end

NetuitiveRubyApi::ConfigManager.load_config
NetuitiveRubyApi::NetuitiveLogger.setup
NetuitiveRubyApi::ConfigManager.read_config
SERVER_URI = "druby://#{NetuitiveRubyApi::ConfigManager.netuitivedAddr}:#{NetuitiveRubyApi::ConfigManager.netuitivedPort}".freeze
DRb.start_service
NetuitiveRubyAPI.setup(DRbObject.new_with_uri(SERVER_URI))
NetuitiveRubyAPI.setup
37 changes: 26 additions & 11 deletions lib/netuitive_ruby_api/config_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ module NetuitiveRubyApi
class ConfigManager
class << self
attr_reader :netuitivedAddr

attr_reader :netuitivedPort

attr_reader :data
attr_reader :sample_cache_enabled
attr_reader :sample_cache_size
attr_reader :sample_cache_interval
attr_reader :event_cache_enabled
attr_reader :event_cache_size
attr_reader :event_cache_interval

def property(name, var, default = nil)
prop = ENV[var]
Expand All @@ -26,12 +30,11 @@ def boolean_property(name, var)
end

def float_property(name, var)
prop = ENV[var].nil? ? nil : ENV[var]
if prop.nil? || (prop == '')
data[name].to_f
else
prop.to_f
end
property(name, var).to_f
end

def int_property(name, var)
property(name, var).to_i
end

def string_list_property(name, var)
Expand All @@ -52,6 +55,12 @@ def load_config
end

def read_config
@sample_cache_enabled = boolean_property('sampleCacheEnabled', 'NETUITIVE_RUBY_SAMPLE_CACHE_ENABLED')
@sample_cache_size = int_property('sampleCacheSize', 'NETUITIVE_RUBY_SAMPLE_CACHE_SIZE')
@sample_cache_interval = int_property('sampleCacheInterval', 'NETUITIVE_RUBY_SAMPLE_CACHE_INTERVAL')
@event_cache_enabled = boolean_property('eventCacheEnabled', 'NETUITIVE_RUBY_EVENT_CACHE_ENABLED')
@event_cache_size = int_property('eventCacheSize', 'NETUITIVE_RUBY_SAMPLE_CACHE_SIZE')
@event_cache_interval = int_property('eventCacheInterval', 'NETUITIVE_RUBY_SAMPLE_CACHE_INTERVAL')
@netuitivedAddr = property('netuitivedAddr', 'NETUITIVE_RUBY_NETUITIVED_ADDR')
@netuitivedPort = property('netuitivedPort', 'NETUITIVE_RUBY_NETUITIVED_PORT')
debugLevelString = property('debugLevel', 'NETUITIVE_RUBY_DEBUG_LEVEL')
Expand All @@ -64,12 +73,18 @@ def read_config
else
Logger::ERROR
end
NetuitiveRubyApi::NetuitiveLogger.log.info "port: #{@netuitivedPort}"
NetuitiveRubyApi::NetuitiveLogger.log.info "addr: #{@netuitivedAddr}"
NetuitiveRubyApi::NetuitiveLogger.log.info "netuitived port: #{@netuitivedPort}"
NetuitiveRubyApi::NetuitiveLogger.log.info "netuitived addr: #{@netuitivedAddr}"
NetuitiveRubyApi::NetuitiveLogger.log.debug "read config file. Results:
netuitivedAddr: #{@netuitivedAddr}
netuitivedPort: #{@netuitivedPort}
debugLevel: #{debugLevelString}"
debugLevel: #{debugLevelString}
sample_cache_enabled: #{@sample_cache_enabled}
sample_cache_size: #{@sample_cache_size}
sample_cache_interval: #{@sample_cache_interval}
event_cache_enabled: #{@event_cache_enabled}
event_cache_size: #{@event_cache_size}
event_cache_interval: #{@event_cache_interval}"
end
end
end
Expand Down
104 changes: 104 additions & 0 deletions lib/netuitive_ruby_api/data_cache.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
module NetuitiveRubyApi
class DataCache
def initialize
@sample_count_mutex = Mutex.new
@event_count_mutex = Mutex.new
reset_samples
reset_events
end

def sample_added
@sample_count += 1
end

def event_added
@event_count += 1
end

def add_sample(value)
@sample_count_mutex.synchronize do
@samples.push(value)
sample_added
end
end

def add_counter_sample(value)
@sample_count_mutex.synchronize do
@counter_samples.push(value)
sample_added
end
end

def add_aggregate_metric(value)
@sample_count_mutex.synchronize do
@aggregate_metrics.push(value)
sample_added
end
end

def add_aggregate_counter_metric(value)
@sample_count_mutex.synchronize do
@aggregate_counter_metrics.push(value)
sample_added
end
end

def add_event(value)
@event_count_mutex.synchronize do
@events.push(value)
event_added
end
end

def add_exception_event(value)
@event_count_mutex.synchronize do
@exception_events.push(value)
event_added
end
end

def clear_sample_cache
NetuitiveRubyApi::ErrorLogger.guard('error during clear_sample_cache') do
@sample_count_mutex.synchronize do
NetuitiveRubyApi::NetuitiveLogger.log.debug 'clearing sample cache'
ret = {
samples: @samples.dup,
counter_samples: @counter_samples.dup,
aggregate_metrics: @aggregate_metrics.dup,
aggregate_counter_metrics: @aggregate_counter_metrics.dup
}
reset_samples
ret
end
end
end

def clear_event_cache
NetuitiveRubyApi::ErrorLogger.guard('error during clear_event_cache') do
@event_count_mutex.synchronize do
NetuitiveRubyApi::NetuitiveLogger.log.debug 'clearing event cache'
ret = {
events: @events.dup,
exception_events: @exception_events.dup
}
reset_events
ret
end
end
end

def reset_samples
@samples = []
@counter_samples = []
@aggregate_metrics = []
@aggregate_counter_metrics = []
@sample_count = 0
end

def reset_events
@events = []
@exception_events = []
@event_count = 0
end
end
end
Loading