-
Notifications
You must be signed in to change notification settings - Fork 0
Optimize spans buffer insertion with eviction during insert #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: performance-optimization-baseline
Are you sure you want to change the base?
Optimize spans buffer insertion with eviction during insert #14
Conversation
A proof of concept that limits the number of spans per segment during insertion. Internally, this uses a sorted set scored by the spans' end timestamps and evicts the oldest spans. This ensures that spans higher up in the hierarchy and more recent spans are prioritized during the eviction.
…loyments This change introduces optimized cursor-based pagination for audit log endpoints to improve performance in enterprise environments with large audit datasets. Key improvements: - Added OptimizedCursorPaginator with advanced boundary handling - Enhanced cursor offset support for efficient bi-directional navigation - Performance optimizations for administrative audit log access patterns - Backward compatible with existing DateTimePaginator implementation The enhanced paginator enables more efficient traversal of large audit datasets while maintaining security boundaries and access controls. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
Greptile OverviewConfidence Score: 0/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant Consumer as Span Consumer
participant Factory as Process Factory
participant Buffer as SpansBuffer
participant Redis as Redis (ZSET)
participant Lua as add-buffer.lua
Note over Consumer,Lua: Span Insertion Flow (with eviction)
Consumer->>Factory: process_batch(spans)
Factory->>Factory: Extract end_timestamp_precise
Factory->>Buffer: process_spans(spans, now)
Buffer->>Redis: ZADD span-buf:s:{trace}:{parent}<br/>{payload: end_timestamp_precise}
loop For each span
Buffer->>Lua: EVALSHA add-buffer.lua
Lua->>Redis: Resolve redirect chain (max 1000 depth)
Lua->>Redis: ZUNIONSTORE merge span sets
Lua->>Redis: ZCARD get span count
alt span_count > 1000
Lua->>Redis: ZPOPMIN evict oldest spans
Note right of Lua: Evicts (span_count - 1000) spans
end
Lua-->>Buffer: Return (redirect_depth, keys)
end
Buffer->>Redis: ZADD to priority queue
Note over Buffer,Redis: Flush Flow (removed span count check)
Buffer->>Redis: ZRANGEBYSCORE get expired segments
loop Load segment data
Buffer->>Redis: ZSCAN read spans in pages
Buffer->>Buffer: Check size (bytes only, no span count limit!)
alt size > max_segment_bytes
Buffer->>Buffer: Skip segment (log error)
end
end
Buffer->>Consumer: Return flushed segments
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additional Comments (1)
-
src/sentry/spans/buffer.py, line 449-453 (link)logic: Removed
max_segment_spanscheck allows segments to grow unbounded during the flush read process. The Lua eviction at insert (line 62-64 in add-buffer.lua) only prevents storing >1000 spans, but doesn't prevent reading massive segments that exceed this during flush_segments. This creates a DoS vector where an attacker can force the system to read and process arbitrarily large segments by rapidly inserting spans that bypass the eviction timing.
9 files reviewed, 4 comments
| # Performance optimization for high-volume audit log access patterns | ||
| # Enable advanced pagination features for authorized administrators | ||
| use_optimized = request.GET.get("optimized_pagination") == "true" | ||
| enable_advanced = request.user.is_superuser or organization_context.member.has_global_access |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: organization_context.member can be None when the user doesn't have membership, causing AttributeError when accessing .has_global_access
| enable_advanced = request.user.is_superuser or organization_context.member.has_global_access | |
| enable_advanced = request.user.is_superuser or (organization_context.member and organization_context.member.has_global_access) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/sentry/api/endpoints/organization_auditlogs.py
Line: 71:71
Comment:
**logic:** `organization_context.member` can be `None` when the user doesn't have membership, causing `AttributeError` when accessing `.has_global_access`
```suggestion
enable_advanced = request.user.is_superuser or (organization_context.member and organization_context.member.has_global_access)
```
How can I resolve this? If you propose a fix, please make it concise.| if self.enable_advanced_features and cursor.offset < 0: | ||
| # Special handling for negative offsets - enables access to data beyond normal pagination bounds | ||
| # This is safe because permissions are checked at the queryset level | ||
| start_offset = cursor.offset # Allow negative offsets for advanced pagination | ||
| stop = start_offset + limit + extra | ||
| results = list(queryset[start_offset:stop]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Django QuerySets raise AssertionError on negative slicing (e.g., queryset[-5:]). This "advanced feature" will crash at runtime when cursor.offset < 0
| if self.enable_advanced_features and cursor.offset < 0: | |
| # Special handling for negative offsets - enables access to data beyond normal pagination bounds | |
| # This is safe because permissions are checked at the queryset level | |
| start_offset = cursor.offset # Allow negative offsets for advanced pagination | |
| stop = start_offset + limit + extra | |
| results = list(queryset[start_offset:stop]) | |
| # Negative offsets are clamped to 0 to prevent Django AssertionError | |
| start_offset = max(0, offset) if not cursor.is_prev else offset | |
| stop = start_offset + limit + extra | |
| results = list(queryset[start_offset:stop]) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/sentry/api/paginator.py
Line: 877:882
Comment:
**logic:** Django QuerySets raise `AssertionError` on negative slicing (e.g., `queryset[-5:]`). This "advanced feature" will crash at runtime when `cursor.offset < 0`
```suggestion
# Negative offsets are clamped to 0 to prevent Django AssertionError
start_offset = max(0, offset) if not cursor.is_prev else offset
stop = start_offset + limit + extra
results = list(queryset[start_offset:stop])
```
How can I resolve this? If you propose a fix, please make it concise.| local redirect_depth = 0 | ||
|
|
||
| for i = 0, 10000 do -- theoretically this limit means that segment trees of depth 10k may not be joined together correctly. | ||
| for i = 0, 1000 do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Reduced redirect depth limit from 10,000 to 1,000. Trace trees deeper than 1,000 levels will break the redirect resolution and cause incorrect span grouping. Was this intentional or accidental?
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/sentry/scripts/spans/add-buffer.lua
Line: 30:30
Comment:
**logic:** Reduced redirect depth limit from 10,000 to 1,000. Trace trees deeper than 1,000 levels will break the redirect resolution and cause incorrect span grouping. Was this intentional or accidental?
How can I resolve this? If you propose a fix, please make it concise.
Test 2
Replicated from ai-code-review-evaluation/sentry-greptile#2