Skip to content

Conversation

@philprime
Copy link
Member

@philprime philprime commented Dec 9, 2025

Overview

This PR refactors the SentryLogBatcher implementation by extracting its core batching logic into a generic, reusable Batcher component using Protocol-Oriented Programming (POP). This abstraction enables future reuse for other item types (e.g., feedback items) while maintaining type safety through Swift generics.

Key Changes

Protocol-Oriented Architecture

The refactoring uses Protocol-Oriented Programming with the following protocol hierarchy:

  • BatcherProtocol: Defines the public interface for batching operations
  • BatcherItem: Protocol for items that can be batched (must be Encodable)
  • BatcherScope: Protocol for scope objects that provide context (attributes, trace IDs, user info)
  • BatcherConfig: Protocol for batcher configuration (timeouts, limits, callbacks)
  • BatchStorage: Protocol for storage backends (in-memory, file-based, etc.)

The generic Batcher<Storage, Item, Scope> class implements BatcherProtocol and works with any types conforming to these protocols, enabling code reuse without sacrificing type safety.

Implementation Details

  1. Generic Batcher Implementation (Sources/Swift/Tools/Batcher/Batcher.swift)

    • Thread-safe batching with configurable flush triggers (item count, buffer size, timeout)
    • Scope application happens synchronously; encoding/buffering happens asynchronously
    • Proper deadlock prevention documentation for capture() method
  2. Scope Attribute Enrichment (Sources/Swift/Tools/Batcher/BatcherScope.swift)

    • Protocol extension provides default implementation for applying scope attributes
    • Adds SDK metadata, OS/device info, user attributes, replay IDs, and custom scope attributes
    • Non-overriding behavior: scope attributes don't override existing item attributes
  3. Storage Abstraction (Sources/Swift/Tools/Batcher/InMemoryBatchStorage.swift)

    • Protocol-based storage allows swapping implementations (in-memory, file-based, etc.)
    • Current implementation uses in-memory storage with JSON encoding
  4. Type Migration

    • Moved SentryLog.Attribute to SentryAttribute as a public type
    • Added backwards compatibility header for SentryLogAttribute to maintain Hybrid SDK compatibility

Bug Fixes

  • Fixed TestCurrentDateProvider.getAbsoluteTime() to properly update _absoluteTime in advance methods
  • Fixed callback to pass item count instead of byte size (batchStorage.count vs batchStorage.size)
  • Enhanced documentation for execution model and deadlock prevention
  • Added comprehensive test coverage for scope attributes

Testing

  • Added extensive unit tests for Batcher, BatcherScope, and InMemoryBatchStorage
  • Test coverage includes edge cases, thread safety, and protocol conformance
  • All existing SentryLogBatcher tests continue to pass

Backwards Compatibility

  • Public API remains unchanged
  • SentryLogBatcher maintains the same interface
  • Hybrid SDKs unaffected due to compatibility header

Related Issues

Closes #7013

#skip-changelog

@philprime philprime self-assigned this Dec 9, 2025
@philprime philprime added the ready-to-merge Use this label to trigger all PR workflows label Dec 9, 2025
@philprime philprime requested a review from denrase December 9, 2025 13:02
@codecov
Copy link

codecov bot commented Dec 9, 2025

Codecov Report

❌ Patch coverage is 95.88477% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.057%. Comparing base (47a1684) to head (d824fa6).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
Sources/Swift/Protocol/SentryAttribute.swift 92.187% 5 Missing ⚠️
.../Swift/Core/Helper/SentryCurrentDateProvider.swift 50.000% 2 Missing ⚠️
Sources/Swift/Tools/SentryLogBatcher.swift 91.666% 2 Missing ⚠️
Sources/Swift/Tools/Batcher/Batcher.swift 98.148% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##              main     #7017       +/-   ##
=============================================
+ Coverage   85.027%   85.057%   +0.030%     
=============================================
  Files          454       457        +3     
  Lines        27737     27793       +56     
  Branches     12159     12174       +15     
=============================================
+ Hits         23584     23640       +56     
+ Misses        4107      4106        -1     
- Partials        46        47        +1     
Files with missing lines Coverage Δ
SentryTestUtils/Sources/TestClient.swift 85.585% <100.000%> (+0.264%) ⬆️
...tryTestUtils/Sources/TestCurrentDateProvider.swift 100.000% <100.000%> (ø)
Sources/Sentry/SentryClient.m 97.610% <100.000%> (+0.198%) ⬆️
...rces/Swift/Helper/SentryDispatchQueueWrapper.swift 100.000% <ø> (ø)
Sources/Swift/Protocol/SentryLog.swift 78.378% <ø> (ø)
Sources/Swift/Tools/Batcher/BatcherScope.swift 100.000% <100.000%> (ø)
...rces/Swift/Tools/Batcher/InMemoryBatchBuffer.swift 100.000% <100.000%> (ø)
Sources/Swift/Tools/Batcher/Batcher.swift 98.148% <98.148%> (ø)
.../Swift/Core/Helper/SentryCurrentDateProvider.swift 71.428% <50.000%> (-8.572%) ⬇️
Sources/Swift/Tools/SentryLogBatcher.swift 95.238% <91.666%> (-3.303%) ⬇️
... and 1 more

... and 9 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 47a1684...d824fa6. Read the comment docs.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 9, 2025

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1208.75 ms 1243.28 ms 34.53 ms
Size 24.14 KiB 1.03 MiB 1.00 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
2e79f5f 1220.53 ms 1249.35 ms 28.82 ms
6502818 1229.08 ms 1245.46 ms 16.37 ms
1a4afd3 1224.39 ms 1246.16 ms 21.77 ms
82f60cf 1218.65 ms 1238.52 ms 19.87 ms
4b6052d 1221.04 ms 1241.74 ms 20.70 ms
f4f94f5 1216.24 ms 1247.94 ms 31.70 ms
94a6b1a 1213.39 ms 1231.55 ms 18.17 ms
e58d7bf 1219.98 ms 1242.39 ms 22.41 ms
8fd192f 1202.10 ms 1220.19 ms 18.09 ms
56f9cc6 1209.47 ms 1236.84 ms 27.37 ms

App size

Revision Plain With Sentry Diff
2e79f5f 23.75 KiB 928.87 KiB 905.12 KiB
6502818 23.75 KiB 959.45 KiB 935.70 KiB
1a4afd3 23.75 KiB 997.18 KiB 973.43 KiB
82f60cf 23.75 KiB 913.63 KiB 889.88 KiB
4b6052d 24.14 KiB 1.02 MiB 1019.77 KiB
f4f94f5 23.75 KiB 988.02 KiB 964.27 KiB
94a6b1a 23.75 KiB 902.48 KiB 878.74 KiB
e58d7bf 24.15 KiB 1.01 MiB 1014.91 KiB
8fd192f 23.74 KiB 872.75 KiB 849.01 KiB
56f9cc6 23.75 KiB 913.63 KiB 889.88 KiB

Previous results on branch: philprime/log-batcher-abstraction

Startup times

Revision Plain With Sentry Diff
c4a716d 1206.94 ms 1252.17 ms 45.23 ms
ca6b1c2 1210.87 ms 1238.04 ms 27.17 ms
52fdb30 1221.07 ms 1253.44 ms 32.37 ms
a15ffdb 1227.70 ms 1259.98 ms 32.28 ms
30f25b8 1188.75 ms 1239.15 ms 50.40 ms
27163ba 1228.75 ms 1257.19 ms 28.44 ms

App size

Revision Plain With Sentry Diff
c4a716d 24.14 KiB 1.02 MiB 1021.64 KiB
ca6b1c2 24.14 KiB 1.03 MiB 1.00 MiB
52fdb30 24.14 KiB 1.02 MiB 1021.64 KiB
a15ffdb 24.14 KiB 1.03 MiB 1.00 MiB
30f25b8 24.14 KiB 1.03 MiB 1.00 MiB
27163ba 24.14 KiB 1.03 MiB 1.00 MiB

- Introduced new test file `SentryItemBatcherTests.swift` to validate the behavior of the `SentryItemBatcher`.
- Added tests for various scenarios including item addition, buffer size limits, timeout handling, and attribute enrichment.
- Updated project configuration to include the new test file in the build settings.
@philprime philprime removed the ready-to-merge Use this label to trigger all PR workflows label Dec 9, 2025
@philprime philprime marked this pull request as draft December 9, 2025 14:19
@philprime
Copy link
Member Author

Moving back to draft to explore protocol-based implementation.

Also I noticed that my implementation changed the requirements of options not changing after the batcher is created. Need to double-check if that is an issue.

@philprime
Copy link
Member Author

philprime commented Dec 9, 2025

@philprime philprime requested a review from Copilot December 11, 2025 12:36
@philprime
Copy link
Member Author

@sentry review

@philprime philprime added the ready-to-merge Use this label to trigger all PR workflows label Dec 11, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the SentryLogBatcher into a generic batching infrastructure to prepare for future features (#6960). The refactoring extracts SentryLog.Attribute to a new public type SentryAttribute, introduces generic batching components (Batcher, BatchStorage, BatcherScope, etc.), and updates SentryLogBatcher to use the new generic implementation.

Key changes:

  • Introduces generic batching infrastructure with protocol-oriented design
  • Moves SentryLog.Attribute to standalone SentryAttribute class with backward compatibility
  • Adds comprehensive test coverage for the new generic components

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
Sources/Swift/Protocol/SentryAttribute.swift New standalone SentryAttribute class extracted from SentryLog.Attribute
Sources/Swift/Protocol/SentryLog.swift Adds type alias for backward compatibility
Sources/Sentry/Public/SentryDefines.h Adds @compatibility_alias for Objective-C compatibility
Sources/Swift/Tools/Batcher/Batcher.swift Core generic batcher implementation with batch storage and timer management
Sources/Swift/Tools/Batcher/BatcherScope.swift Protocol and extension for applying scope attributes to batched items
Sources/Swift/Tools/Batcher/BatcherItem.swift Protocol defining requirements for items that can be batched
Sources/Swift/Tools/Batcher/BatcherConfig.swift Protocol for batcher configuration
Sources/Swift/Tools/Batcher/BatchStorage.swift Protocol for batch storage implementations
Sources/Swift/Tools/Batcher/InMemoryBatchStorage.swift In-memory implementation of batch storage
Sources/Swift/Tools/SentryLogBatcher.swift Refactored to delegate to generic Batcher
Sources/Swift/Helper/SentryDispatchQueueWrapper.swift Adds protocol for dispatch queue wrapper
Sources/Swift/Core/Helper/SentryCurrentDateProvider.swift Adds getAbsoluteTime() method
Tests/SentryTests/Batcher/*.swift Comprehensive test coverage for new generic components
Tests/SentryTests/SentryLogBatcherTests.swift Updated tests with improved structure and date provider
sdk_api.json API documentation changes reflecting the type rename

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

philprime and others added 2 commits December 11, 2025 13:50
- Updated `TestCurrentDateProvider` to include `_absoluteTime` tracking during date advancements.
- Modified `Batcher` to clarify synchronous behavior in documentation and ensure correct item count is passed to the callback.
- Added tests to verify scope attribute application and item count during capture in `BatcherScopeTests` and `BatcherTests`.
@philprime philprime marked this pull request as ready for review December 11, 2025 13:11
@philprime philprime requested a review from Copilot December 11, 2025 15:10
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@itaybre itaybre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@philprime
Copy link
Member Author

philprime commented Dec 12, 2025

BLOCKED BY #7036

Copy link
Collaborator

@denrase denrase left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, makes it easier to test all the individual responsibilities that were inside the batcher. Just some general questions and feedback regarding naming. 🙇‍♂️

Copy link
Member

@philipphofmann philipphofmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, I think we should have a quick call about this to ensure if the still WIP concept for the TelemetryProcessor / Buffer would work for us, and then align if we still want to do some changes in this PR or follow up.

@philprime philprime enabled auto-merge (squash) December 12, 2025 13:18
Copy link
Member

@philipphofmann philipphofmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more minor comments.

@philprime philprime merged commit 5255ced into main Dec 12, 2025
192 checks passed
@philprime philprime deleted the philprime/log-batcher-abstraction branch December 12, 2025 14:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Use this label to trigger all PR workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Metrics] Extract generic item batcher from SentryLogBatcher and use it for SentryMetricBatcher

6 participants