event_timeline 0.2.0 → 0.2.1

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
  SHA256:
3
- metadata.gz: e6bb353fe95dc4e1add0e9b01de0f938d1e9feb7dcffddf4501d9c4fc6d74a3d
4
- data.tar.gz: af1804a78347c235856b8a950bd843d412a5fe7724573a139653a5aef689460b
3
+ metadata.gz: 7f9b39a082143ef828a48c1ba89377103062e5fd2d356658d257964727402c22
4
+ data.tar.gz: f332374e2650e04ae7cfe4dee1ae27d98b11d268486284afbd02ddba8def7576
5
5
  SHA512:
6
- metadata.gz: 3f58e34396e514e0f4affb1f71198b14711081147618d631c82b33b2ab49b8b8e15e5efe9b5a60bcc63e5f012aad80cb6b59da7263af2ca4969f2dd924d2bebf
7
- data.tar.gz: a21b2da8e8e4a60351238484b5927b02634c37f3f49b79ea053b6b64107528931cf94cf22c825b7c781640c5b31ac6a362bc528049624099c49032701e5197b8
6
+ metadata.gz: c7ff33b22475ea362d891023c7fc942e9ee85878d13fba5cf113426e3aea0ba1b48e10ad9a6f0ea101b5dd740900beaacd65b021a2a0903fc70f8d51ba2bc9b1
7
+ data.tar.gz: 44ccc4f17fdb6e65f247a5209cec9cea0e6f458593ad113522b1da7056f9ca846db487a1f0d6cbbbcd5faca12c6be9be5ca1c917d17ae52674f23a58d43b25e3
@@ -33,9 +33,10 @@ module EventTimeline
33
33
  buffer = thread_event_buffer
34
34
  return if buffer.empty?
35
35
 
36
+ buffer_size = buffer.size
36
37
  Session.insert_all(buffer)
37
38
 
38
- RotationService.enforce_correlation_limit(correlation_id)
39
+ RotationService.enforce_correlation_limit(correlation_id, buffer_size)
39
40
  RotationService.cleanup_if_needed
40
41
  rescue StandardError => e
41
42
  Rails.logger.error "EventTimeline flush failed: #{e.message}" if defined?(Rails.logger)
@@ -100,9 +101,10 @@ module EventTimeline
100
101
  end
101
102
 
102
103
  def handle_return(tp)
103
- return unless EventTimeline.configuration&.watched?(tp.path)
104
+ # Skip watched? check - if we didn't track the call, pop_from_stack returns nil
105
+ correlation_id = CurrentCorrelation.id
106
+ return unless correlation_id
104
107
 
105
- correlation_id = CurrentCorrelation.id || determine_correlation_id
106
108
  method_info = pop_from_stack(correlation_id, tp)
107
109
  return unless method_info
108
110
 
@@ -8,6 +8,7 @@ module EventTimeline
8
8
 
9
9
  def initialize
10
10
  @watched_paths = []
11
+ @watched_cache = {} # Cache for watched? lookups
11
12
  @filtered_attributes = default_filtered_attributes
12
13
  @max_events_per_correlation = 500 # Max events per correlation_id
13
14
  @max_total_events = 10_000 # Max total events before cleanup
@@ -23,16 +24,23 @@ module EventTimeline
23
24
 
24
25
  def watch(path)
25
26
  @watched_paths << normalize_path(path)
27
+ @watched_cache.clear # Invalidate cache when paths change
26
28
  end
27
29
 
28
30
  def watched?(file_path)
29
31
  return false if @watched_paths.empty?
30
32
 
31
- @watched_paths.any? do |pattern|
32
- File.fnmatch?(pattern, file_path, File::FNM_PATHNAME)
33
+ @watched_cache.fetch(file_path) do
34
+ @watched_cache[file_path] = @watched_paths.any? do |pattern|
35
+ File.fnmatch?(pattern, file_path, File::FNM_PATHNAME)
36
+ end
33
37
  end
34
38
  end
35
39
 
40
+ def clear_watched_cache!
41
+ @watched_cache.clear
42
+ end
43
+
36
44
  def filter_pii(&block)
37
45
  @pii_filter_proc = block if block_given?
38
46
  end
@@ -2,10 +2,19 @@
2
2
 
3
3
  module EventTimeline
4
4
  class RotationService
5
+ CLEANUP_CHECK_INTERVAL = 100 # Only check every N flushes
6
+
5
7
  class << self
6
- def cleanup_if_needed
8
+ def cleanup_if_needed(force: false)
7
9
  return unless EventTimeline.configuration
8
10
 
11
+ unless force
12
+ # Probabilistic check - only run expensive Session.count every N requests
13
+ @flush_counter ||= 0
14
+ @flush_counter += 1
15
+ return unless (@flush_counter % CLEANUP_CHECK_INTERVAL).zero?
16
+ end
17
+
9
18
  total_count = Session.count
10
19
  max_total = EventTimeline.configuration.max_total_events
11
20
  threshold = (max_total * EventTimeline.configuration.cleanup_threshold).to_i
@@ -15,11 +24,23 @@ module EventTimeline
15
24
  perform_cleanup(total_count, max_total)
16
25
  end
17
26
 
18
- def enforce_correlation_limit(correlation_id)
27
+ def enforce_correlation_limit(correlation_id, buffer_size = 0, force: false)
19
28
  return unless EventTimeline.configuration
20
29
 
21
30
  max_per_correlation = EventTimeline.configuration.max_events_per_correlation
31
+
32
+ unless force
33
+ # Track in-memory counts to avoid DB query on every flush
34
+ @correlation_counts ||= {}
35
+ @correlation_counts[correlation_id] ||= 0
36
+ @correlation_counts[correlation_id] += buffer_size
37
+
38
+ # Only hit DB when we think we might be near the limit
39
+ return unless @correlation_counts[correlation_id] >= (max_per_correlation * 0.9)
40
+ end
41
+
22
42
  current_count = Session.where(correlation_id: correlation_id).count
43
+ @correlation_counts[correlation_id] = current_count if @correlation_counts # Sync with reality
23
44
 
24
45
  return unless current_count >= max_per_correlation
25
46
 
@@ -30,10 +51,16 @@ module EventTimeline
30
51
  .limit(current_count - keep_count)
31
52
 
32
53
  Session.where(id: oldest_events.pluck(:id)).delete_all
54
+ @correlation_counts[correlation_id] = keep_count if @correlation_counts
33
55
 
34
56
  Rails.logger.info "EventTimeline: Rotated #{current_count - keep_count} events for correlation #{correlation_id}" if defined?(Rails.logger)
35
57
  end
36
58
 
59
+ def reset_counters!
60
+ @flush_counter = 0
61
+ @correlation_counts = {}
62
+ end
63
+
37
64
  private
38
65
 
39
66
  def perform_cleanup(current_count, max_count)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EventTimeline
4
- VERSION = '0.2.0'
4
+ VERSION = '0.2.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: event_timeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - svn-arv