Class: ShieldPressTracker::Tracker
- Inherits:
-
Object
- Object
- ShieldPressTracker::Tracker
- Defined in:
- lib/shieldpress_tracker/tracker.rb
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#error_collector ⇒ Object
readonly
Returns the value of attribute error_collector.
-
#http_collector ⇒ Object
readonly
Returns the value of attribute http_collector.
-
#security_collector ⇒ Object
readonly
Returns the value of attribute security_collector.
Instance Method Summary collapse
- #analyze_request(url:, method: "GET", headers: {}, body: nil, ip: nil, query: nil) ⇒ Object
- #capture_error(error, meta = {}) ⇒ Object
- #flush ⇒ Object
- #ignored?(path) ⇒ Boolean
-
#initialize(config = {}) ⇒ Tracker
constructor
A new instance of Tracker.
- #record_auth_failure(ip: nil, url: nil, method: nil, reason: nil) ⇒ Object
- #record_cors_violation(ip: nil, origin: nil, url: nil) ⇒ Object
- #record_rate_limit(ip: nil, url: nil, method: nil, limit: nil) ⇒ Object
- #record_request(path:, method: "GET", status_code: 200, duration_ms: 0) ⇒ Object
- #record_security_event(type:, severity:, message:, **data) ⇒ Object
- #start ⇒ Object
- #stop(flush: true) ⇒ Object
Constructor Details
#initialize(config = {}) ⇒ Tracker
Returns a new instance of Tracker.
9 10 11 12 13 |
# File 'lib/shieldpress_tracker/tracker.rb', line 9 def initialize(config = {}) @config = Config.new(config); @http_collector = HttpCollector.new @error_collector = ErrorCollector.new(@config.max_error_buffer); @security_collector = SecurityCollector.new(@config.max_security_buffer) @reporter = Reporter.new(@config.api_url, @config.api_key, @config.debug); @stopped = false; @last_audit = Time.at(0) end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
8 9 10 |
# File 'lib/shieldpress_tracker/tracker.rb', line 8 def config @config end |
#error_collector ⇒ Object (readonly)
Returns the value of attribute error_collector.
8 9 10 |
# File 'lib/shieldpress_tracker/tracker.rb', line 8 def error_collector @error_collector end |
#http_collector ⇒ Object (readonly)
Returns the value of attribute http_collector.
8 9 10 |
# File 'lib/shieldpress_tracker/tracker.rb', line 8 def http_collector @http_collector end |
#security_collector ⇒ Object (readonly)
Returns the value of attribute security_collector.
8 9 10 |
# File 'lib/shieldpress_tracker/tracker.rb', line 8 def security_collector @security_collector end |
Instance Method Details
#analyze_request(url:, method: "GET", headers: {}, body: nil, ip: nil, query: nil) ⇒ Object
32 33 34 |
# File 'lib/shieldpress_tracker/tracker.rb', line 32 def analyze_request(url:, method: "GET", headers: {}, body: nil, ip: nil, query: nil) @security_collector.analyze(url: url, method: method, headers: headers, body: body, ip: ip, query: query) if @config.security_tracking && !ignored?(url) end |
#capture_error(error, meta = {}) ⇒ Object
35 |
# File 'lib/shieldpress_tracker/tracker.rb', line 35 def capture_error(error, = {}); @error_collector.capture(error, ) if @config.error_tracking end |
#flush ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/shieldpress_tracker/tracker.rb', line 48 def flush c = @config payload = { siteId: c.site_id, appName: c.app_name, appVersion: c.app_version, environment: c.environment, tags: c., timestamp: Time.now.utc.iso8601 } payload[:system] = Metrics.system if c.system_metrics http = @http_collector.flush if c.http_tracking; payload[:http] = http if http errors = @error_collector.flush if c.error_tracking; payload[:errors] = errors unless errors.nil? || errors.empty? security = @security_collector.flush if c.security_tracking; payload[:security] = security if security payload[:runtime] = Metrics.runtime if c.runtime_metrics; payload[:envSecurity] = Metrics.environment if c.env_security if c.dep_audit && Time.now - @last_audit >= c.dep_audit_interval.to_i; payload[:depAudit] = Metrics.dependencies; @last_audit = Time.now; end payload[:heartbeat] = true if c.heartbeat @reporter.send(payload) rescue StandardError false end |
#ignored?(path) ⇒ Boolean
25 26 27 28 |
# File 'lib/shieldpress_tracker/tracker.rb', line 25 def ignored?(path) path = URI.parse(path).path rescue path @config.ignore_paths.any? { |pattern| pattern.end_with?("/*") ? path.start_with?(pattern[0..-2]) : path == pattern } end |
#record_auth_failure(ip: nil, url: nil, method: nil, reason: nil) ⇒ Object
36 37 38 |
# File 'lib/shieldpress_tracker/tracker.rb', line 36 def record_auth_failure(ip: nil, url: nil, method: nil, reason: nil) @security_collector.record(type: :auth_failure, severity: :medium, message: "Authentication failed#{reason ? ": #{reason}" : ""}", ip: ip, url: url, method: method) end |
#record_cors_violation(ip: nil, origin: nil, url: nil) ⇒ Object
42 43 44 |
# File 'lib/shieldpress_tracker/tracker.rb', line 42 def record_cors_violation(ip: nil, origin: nil, url: nil) @security_collector.record(type: :cors_violation, severity: :medium, message: "CORS policy blocked request from origin: #{origin || 'unknown'}", ip: ip, url: url) end |
#record_rate_limit(ip: nil, url: nil, method: nil, limit: nil) ⇒ Object
39 40 41 |
# File 'lib/shieldpress_tracker/tracker.rb', line 39 def record_rate_limit(ip: nil, url: nil, method: nil, limit: nil) @security_collector.record(type: :rate_limit_hit, severity: :low, message: "Rate limit triggered", ip: ip, url: url, method: method, meta: { limit: limit }) end |
#record_request(path:, method: "GET", status_code: 200, duration_ms: 0) ⇒ Object
29 30 31 |
# File 'lib/shieldpress_tracker/tracker.rb', line 29 def record_request(path:, method: "GET", status_code: 200, duration_ms: 0) @http_collector.record(path: path, method: method, status_code: status_code, duration_ms: duration_ms) if @config.http_tracking && !ignored?(path) end |
#record_security_event(type:, severity:, message:, **data) ⇒ Object
45 46 47 |
# File 'lib/shieldpress_tracker/tracker.rb', line 45 def record_security_event(type:, severity:, message:, **data) @security_collector.record(type: type, severity: severity, message: , **data) end |
#start ⇒ Object
14 15 16 17 18 19 20 21 22 23 |
# File 'lib/shieldpress_tracker/tracker.rb', line 14 def start return self if @thread&.alive? @stopped = false @thread = Thread.new do Thread.current.name = "shieldpress-reporter" if Thread.current.respond_to?(:name=) until @stopped; sleep(@config.report_interval.to_i); flush unless @stopped; end end @thread.abort_on_exception = false self end |
#stop(flush: true) ⇒ Object
24 |
# File 'lib/shieldpress_tracker/tracker.rb', line 24 def stop(flush: true); @stopped = true; @thread&.kill; self.flush if flush; self end |