Repository navigation
Commit 23e3bed
DEMRUM-6211: Release 2.4.1 (#709)
* DEMRUM-577: Implement explicit stack Error tracking API (#702)
* DEMRUM-5771: Implement custom raw error tracking API
* DEMRUM-5771: Fix lint & format
* DEMRUM-5771: Address code review remarks 1
* DEMRUM-5771: Fix map lining format
* DEMRUM-5369: Update attribute to development.environment.name (#701)
* DEMRUM-5369: Update to development.environment.name
* DEMRUM-5369: Reorganize unit tests
* DEMRUM-6055: Rewrite RELEASING.md with current release process (#693)
* DEMRUM-6055: Rewrite RELEASING.md with current release process
* DEMRUM-6055: Restore SPM tag note, build/test steps, and VERSION placeholder convention
* DEMRUM-6055: Refine release workflow and recovery guidance
* DEMRUM-6055: Add post-upload XCFramework asset verification
* DEMRUM-6055: Clarify Swift Package and XCFramework distribution
* DEMRUM-6028: Slow frame detection accuracy (#696)
* DEMRUM-6028: Improve iOS slowRenders/frozenRenders detection accuracy
* Derive expected cadence per frame from targetTimestamp - timestamp instead
before slow
* Count one continuous freeze episode once instead of once per 700ms tick,
coordinated between the watchdog and handleFrame via an inFreezeEpisode flag
* Preserve the existing slowRenders/frozenRenders/count telemetry contract
* DEMRUM-6028: Ignore frames delivered while inactive
* Add an actor-owned isActive flag to SlowFrameLogic, gated in
handleFrame and toggled by the lifecycle handlers
* Closes a race between the frame-consuming AsyncStream task and the
lifecycle-notification task: a frame already in flight when the app
resigns active could previously re-arm the heartbeat after
appWillResignActive had reset it, letting the watchdog count a
spurious frozen frame while backgrounded
* DEMRUM-6028: Fix stale doc comment and copyright years
* Correct the slowFrameTolerance doc comment: it avoids false
negatives on a frame that missed its deadline by only a jitter
margin, not false positives
* Update copyright year to 2026 on two new test support files
* DEMRUM-6028: Add watchdog recovery test; split logic test file
* Add testWatchdogCountsSecondDistinctFreezeAfterRecovery, proving a
recovery frame clears inFreezeEpisode so a second distinct freeze is
counted independently by the watchdog.
* Move the four wall-clock/watchdog-dependent tests and the polling
helper into a new SlowFrameLogicWatchdogTests, mirroring the existing
deterministic/integration test split, keeping each file under the
400-line limit.
* Use a generous 4.0s poll timeout since the watchdog phase is
independent of the heartbeat and detection can exceed one threshold
interval under CI scheduling jitter.
* DEMRUM-6028: Fix watchdog recovery test flush race
* Poll the total frozen episode count (buffered plus flushed) instead
of the actor's buffered count alone. The one-second flush loop drains
the buffered count, so it oscillated and never reached 2, timing out
the second-episode wait.
* DEMRUM-6028: Update slow/frozen frame documentation
* Update the DocC page to state that the module reports periodic
aggregated slow and frozen frame counts, not one span per frame.
* Note that the deprecated slowRenderingDetectionEnabled builder method
toggles both slow and frozen frame spans, not slow frames only.
* DEMRUM-6028: Split watchdog tests and fix doc accuracy
* Move the four wall-clock watchdog tests into a new
SlowFrameLogicWatchdogTests class, resolving the file_length
violation and isolating timing-dependent tests from the
deterministic handleFrame suite.
* Drop start() from the deterministic suite's setUp so those tests
run without the background watchdog and flush timers.
* Raise the watchdog poll timeout to 4.0s for CI robustness.
* Correct docs to describe cadence-based slow classification and
aggregated-count flushing, and fix a garbled MARK comment in the
agent-level proxy.
* DEMRUM-6028: Fix watchdog test flake and docc accuracy
* Reverse the read order in the frozen-episode polling helper so a
flushed count is read before the buffered count. Reading buffered
first let an event that migrated from the buffer to the destination
between the two reads appear in both, double-counting one episode
and making the recovery test flake.
* Rewrite testFrozenFrameIsDetectedWhenFramesStop to reuse that helper
instead of spawning its own unretained polling task, so the poll loop
is cancelled on both success and failure rather than surviving a
failed test.
* Correct the Slow & Frozen Frame Detection docc: each flush emits a
span only for a nonzero count, not always both types. Add the missing
final newline.
* DEMRUM-6028: Rename slowFrameTolerance to cadenceJitterMargin
* Rename the internal slow-frame slack constant to break the naming
echo of the removed slowFrameTolerancePercentage, which could read as
though the value were still a configurable tolerance.
The new name states the constant's role: a small margin absorbing
floating-point and measurement jitter in the per-frame cadence
comparison. Behavior and value (0.001s) are unchanged.
* DEMRUM-6028: Classify threshold-length stalls consistently as frozen
* Measure the frozen-frame threshold against the previous frame's
timestamp (the inter-frame gap) instead of the target-relative
lateness. The watchdog already measures elapsed time since the last
frame, so a stall in the [700ms, 700ms + one cadence) window was
classified slow or frozen depending on watchdog timing phase. Both
paths now share the 700ms boundary on the same timebase.
* Keep target-relative lateness for the slow-frame test, which is about
missed presentation deadlines rather than main-thread unresponsiveness.
* Add two deterministic boundary tests constructed so the inter-frame
gap (not the target lateness) hits the threshold: one at exactly
700ms asserting frozen, one just below asserting slow.
* Correct a stale comment in the watchdog test helper about the polled
total being monotonic.
* DEMRUM-6028: Discard buffered pre-background ticks after foregrounding
* Add an activation-timestamp fence in SlowFrameLogic so a CADisplayLink
tick produced before backgrounding, but delivered to the actor only
after appDidBecomeActive, is rejected instead of seeding the baseline.
* Capture CACurrentMediaTime() at foreground and reset the logic before
resuming the ticker, so a stale tick is fenced by timestamp while a
fresh post-resume tick is still accepted.
* Prevents the next real frame's gap from spanning the whole background
interval and emitting a spurious frozenRenders event; the isActive
guard alone could not catch this, since it reflects when a tick is
processed rather than when it was produced.
* Add a deterministic regression test for the stale-tick ordering.
* DEMRUM-6028: Consolidate duplicate Unreleased Fixed heading
* Merge the two DEMRUM-6028 bullets into the single [Unreleased] Fixed
section and drop the duplicate heading.
* DEMRUM-6028: Move changelog entries to Unreleased
* DEMRUM-6028: Add lifecycle integration coverage
* DEMRUM-5269: Add userActivity timestamps to session replay metadata for timeline visualization (#646)
* Add userActivity timestamps to session replay metadata for timeline visualization
* Fix lint, format, and build failures in userActivity PR
- Make activityStream public so SplunkAgent can access it across modules
- Refactor fallback JSON path in SessionReplayDataEvent to stay within line length limit
- Collapse sendEvent trailing closure in DefaultEventManager to reduce closure body length
- Add blank line after #if in switch to satisfy vertical_whitespace_between_cases
- Fix import order in SpanExtensionsTests to satisfy swift-format OrderedImports
* Fix import order in test files to satisfy swift-format OrderedImports
* Add swift-format-ignore-file to test files with @_spi/@testable imports
* Suppress sorted_imports in test files with mixed @testable/@_spi imports
* Fix swiftformat and swiftlint sorted_imports in test files after develop merge
* DEMRUM-5269: Fix format check and address review feedback
- Fix swift-format indentation/brace style in customizeInteractions()
- Restrict activityStream to @_spi(SplunkInternal) to prevent external consumers from draining the stream
- Cap activityStream buffer to 1000 entries (bufferingNewest) to avoid unbounded memory growth when replay is inactive
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Fix JSON escaping in fallbackJSON and clarify flush doc comment
- Use JSONSerialization for fallbackJSON so metadata.source is properly
escaped instead of interpolated directly into the string
- Clarify flush(startMs:endMs:) doc comment: timestamps after endMs
are retained, not discarded
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Fix swift-format doc comment warning in UserActivityCollector
Add blank line after one-line summary in flush(startMs:endMs:) doc comment.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Fix swiftformat blankLinesAfterGuardStatements in fallbackJSON
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Address PR review findings
- Fix test cast from [NSNumber] instead of [Int] when deserializing userActivity via JSONSerialization
- Fix last-resort fallback JSON missing source field and add proper escaping
- Restore CrashReportKeys to public access level (was accidentally narrowed from public)
- Move swift-format-ignore-file directives before import statements so they are recognized
- Clarify UserActivityCollector.flush doc comment to reflect that pre-window timestamps are discarded
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Fix last-resort fallback JSON line length
Split long interpolation into local variables to satisfy swift-format
LineLength rule (160 char limit).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Remove superfluous swiftlint disable comment
The line is within the 160-char limit so the disable comment triggers
superfluous_disable_command violation.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Address vaclav-halik-smartlook review findings
- Fix flush() to remove only timestamps in [startMs,endMs] window; previously
`timestamps.filter { $0 > endMs }` also discarded pre-startMs timestamps that
could belong to a concurrent segment flush
- Add maxBufferSize=10_000 cap to UserActivityCollector to prevent unbounded
growth when recording is paused or stopped for extended periods
- Clarify activityStream doc comment to document best-effort delivery semantics
(.bufferingNewest(1_000) can drop oldest timestamps under backpressure)
- Add reset() to UserActivityCollector for callers that need an explicit clear
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Fix doc comment format in UserActivityCollector
swift-format requires a blank line after the one-line summary sentence.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Address Codex review — retry restore, cap, escaping, access level
- Revert CrashReportKeys to internal (was mistakenly made public in response
to an outdated Copilot comment; on develop it has been internal since #658)
- Restore flushed timestamps to collector on sendEvent failure so they are
included when the segment is retried (fixes silent loss on processed==false)
- Add restore() to UserActivityCollector for the retry path
- Fix buffer cap: append first, then batch-trim with removeFirst(_:) instead
of calling removeFirst() per-record (O(n) shift on hot path)
- Fix last-resort JSON fallback to escape all JSON control characters
(newline, tab, backspace, etc.) not just backslash and quote
- Add UserActivityCollectorTests covering window partitioning, concurrent
segment flushes, retry restore, buffer cap, and reset
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Eliminate yield→record race via synchronous onActivity callback
Replace the async activityStream+Task pipeline with a direct synchronous
callback on Interactions.onActivity. Previously, yield() and record() ran
on separate tasks so a segment flush could drain the collector before an
already-yielded timestamp was written — silently losing it.
With onActivity the timestamp is recorded inside handleEvent(), atomically
before the event is forwarded to the destination. No async hop, no race.
Changes:
- Interactions: replace AsyncStream+Continuation with `onActivity: ((Date)->Void)?`
called synchronously in handleEvent
- UserActivityCollector: convert from actor to NSLock-guarded final class so it
can be called from any context without await
- SplunkRum+Modules: wire collector.record via onActivity closure; remove the
now-unnecessary userActivityTask and its Task wrapper
- SplunkRum: remove userActivityTask property and empty deinit
- DefaultEventManager: flush/restore are now synchronous — remove await
- UserActivityCollectorTests: remove async/await (not needed for sync class)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Fix lint/format violations after develop merge
- UserActivityCollectorTests: rename loop var 'i' to 'idx' (identifier_name)
- UserActivityCollector/DefaultEventManager/SessionReplayDataEvent: fix
swiftformat issues (elseOnSameLine, blankLinesAfterGuardStatements,
wrapConditionalBodies, switch_case_on_newline, blankLineAfterSwitchCase,
consecutiveSpaces, numberFormatting)
- OTLPSpan/SpanEvent/SpanLink/Resource/InstrumentationScope/LogRecord: rename
shadowed 'count' local vars to use the optional directly — fixes
empty_count swiftlint violations introduced by DEMRUM-5867 merge
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Wire collector.reset() to sessionReplay.stop() lifecycle
Add onStop callback to SessionReplay proxy and call collector.reset() when
the user (or the module itself on app exit) stops recording. Without this,
timestamps accumulated during a recording session would bleed into segments
produced after the next start(), and the buffer would grow unboundedly while
recording was paused.
Add two lifecycle tests: verify that reset() clears pre-stop timestamps and
that they do not reappear after recording restarts.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Address post-review findings
- Guard `Interactions.onActivity` with an NSLock so the host-app install
path and the detector task cannot race on read/write.
- Add explicit recording gate to `UserActivityCollector`: `record(at:)`
is a no-op unless Session Replay has entered the recording state,
preventing unbounded growth when SR is sampled out or not installed.
- Amortize the buffer cap: drop `trimSlack` (1024) entries at once
instead of shifting ~10 000 elements on every event at the cap.
- Preserve the final segment's activity on `stop()`: no longer eager-
reset the collector before `module.stop()` — publish still flushes
buffered events for the last record.
- Add a generation token returned by `flush()` and consumed by
`restore()`; a stop/reset invalidates the token, so a delayed failure
callback cannot leak the previous session's activity into a new one.
- Reset the collector on `start()` rather than on `stop()`, and prime it
at install time (Cisco SR auto-starts recording on install).
- Attach `onActivity` wiring regardless of `InteractionsConfiguration
.isEnabled`; document that when the Interactions detector is disabled
the collector receives no events (source of truth is the detector).
- Flush semantics: include timestamps `<= endMs` in the current segment
so late-arriving events whose timestamp falls in a past window are
attached to the next segment rather than orphaned.
- Update tests to cover: recording gate default-off, late-arrival, retry
restore with generation, restore after reset dropped, sequential
flushes, cap trim behavior, and concurrent onActivity read/write.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Drive UserActivityCollector state from Cisco SR isRecording publisher
Address post-review codex findings on b09a005:
- Redundant SessionReplay.start() calls no longer discard the current
segment's buffered activity. The collector is reset only on a real
stopped->recording transition, driven by Cisco SR's @published
isRecording property (deduplicated at the publisher level).
- Autonomous SR state changes (diskCacheCapacityOverreached, internal
errors) that stop recording without going through our proxy now flip
the collector's recording gate, so the hot append path is disabled
instead of relying solely on the buffer cap.
The proxy-level onStart/onStop callback hooks are removed; the Combine
subscription in wireUserActivityCollector is the single source of truth.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-5269: Filter flush timestamps by both startMs and endMs bounds
Segment ownership was ambiguous when publish tasks ran concurrently: a
later-started segment could consume the earlier segment's activity
because flush() only checked endMs and swept every timestamp <= endMs
into the current batch. When two segments' publish tasks overlapped
(e.g. B prepared before A's failure retry) B silently absorbed A's
timestamps.
Filter strictly by [startMs, endMs] so each segment picks up exactly
the events that occurred inside its own window, and retain everything
else for whichever segment actually owns it. Tests cover reverse-order
flushes, failure-then-neighbour scenarios, and events outside any
active window.
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* DEMRUM-6211: Prepare 2.4.1 version
---------
Co-authored-by: Aditi Sharma <aditis3@cisco.com>
Co-authored-by: mbudinsky <23032136+mbudinsky@users.noreply.github.com>
Co-authored-by: Stephen Mickelsen <122052675+SMickelsn@users.noreply.github.com>
Co-authored-by: Carlos McEvilly <12955+carlosmcevilly@users.noreply.github.com>
Co-authored-by: Filip Růžička <58311864+froseio@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>51 files changed
Lines changed: 2257 additions & 367 deletions
File tree
- .github/ISSUE_TEMPLATE
- Applications/DevelApp/DevelApp/CustomTrackingDemo
- SplunkAgent
- Sources
- SplunkAgentObjC/Modules/Custom Tracking/Public API
- SplunkAgent
- Agent
- Events
- Event Manager
- Events
- Utils
- Modules
- Public API
- Deprecated/Model
- Modules
- Custom Tracking
- Proxies
- Module
- Non-Operational
- Public API
- Session Replay/Proxies/Module
- SlowFrameDetector/Proxies/Module
- SplunkAgent.docc/Modules
- Tests
- SplunkAgentObjCTests/PublicAPI/Modules/CustomTracking
- SplunkAgentTests
- Agent
- Events
- Resources
- Public API/Modules/CustomTracking
- Testing Support/Builders
- SplunkCommon/Tests/SplunkCommonTests
- Persistent Cache
- Span
- SplunkCustomTracking
- Sources/SplunkCustomTracking
- DataTypes/ErrorData
- Protocols
- Tests/SplunkCustomTrackingTests
- SplunkInteractions
- Sources/SplunkInteractions/Module
- Tests/SplunkInteractionsTests
- SplunkOpenTelemetryBackgroundExporter/Sources/SplunkOpenTelemetryBackgroundExporter/OTLPEncoder/Models
- Common
- Logs
- Trace
- SplunkOpenTelemetry/Sources/SplunkOpenTelemetry/Resources
- SplunkSlowFrameDetector
- Sources/SplunkSlowFrameDetector
- Tests/SplunkSlowFrameDetectorTests
- Testing Support
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
77 | 77 | | |
78 | 78 | | |
79 | 79 | | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
80 | 87 | | |
81 | 88 | | |
82 | 89 | | |
| |||
136 | 143 | | |
137 | 144 | | |
138 | 145 | | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
139 | 173 | | |
140 | 174 | | |
141 | 175 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
10 | 26 | | |
11 | 27 | | |
12 | 28 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | | - | |
10 | | - | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
| 82 | + | |
82 | 83 | | |
83 | 84 | | |
84 | 85 | | |
| |||
149 | 150 | | |
150 | 151 | | |
151 | 152 | | |
| 153 | + | |
152 | 154 | | |
153 | 155 | | |
154 | 156 | | |
| |||
196 | 198 | | |
197 | 199 | | |
198 | 200 | | |
| 201 | + | |
| 202 | + | |
199 | 203 | | |
200 | 204 | | |
201 | 205 | | |
202 | 206 | | |
203 | 207 | | |
204 | | - | |
| 208 | + | |
| 209 | + | |
205 | 210 | | |
206 | 211 | | |
207 | | - | |
208 | | - | |
209 | | - | |
210 | | - | |
211 | | - | |
212 | | - | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
220 | 215 | | |
221 | | - | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
222 | 224 | | |
223 | 225 | | |
224 | 226 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
54 | | - | |
| 54 | + | |
| 55 | + | |
55 | 56 | | |
56 | 57 | | |
57 | 58 | | |
| |||
64 | 65 | | |
65 | 66 | | |
66 | 67 | | |
67 | | - | |
| 68 | + | |
68 | 69 | | |
69 | 70 | | |
70 | 71 | | |
| |||
80 | 81 | | |
81 | 82 | | |
82 | 83 | | |
83 | | - | |
| 84 | + | |
84 | 85 | | |
85 | 86 | | |
86 | 87 | | |
87 | | - | |
| 88 | + | |
88 | 89 | | |
89 | 90 | | |
90 | | - | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
91 | 122 | | |
92 | 123 | | |
93 | 124 | | |
94 | 125 | | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
95 | 162 | | |
0 commit comments