Repository navigation
Conversation
…an error A session missed by sessionSampleRate can now be kept in memory and uploaded only when it reports an error of its own: - RumConfigurationBuilder.setSessionOnError (default false) and the remote configuration key rum.sessionOnError (absent keeps the init value). A rate the beforeSampling hook sets to 0 turns it off. - Such a session runs its scopes as usual, but writes through a withholding writer: a rolling 60 s buffer (64 KiB / 200 detail events, 50 views), eviction by tier (successful requests first, errors last and newest first), released views oldest first, then errors, then the rest. - The first error that survives the event mapper releases the buffer after a per-session jitter of up to 3 s; the window freezes when the release is scheduled. A flush (backgrounding, Flashcat.flush, a crash policy exit) releases a scheduled release at once; a terminating ArkTS crash and setForcedSession release immediately. - A session that ends without an error is discarded, including the late writes of its still-draining views. A refused consent drops the buffer. - View documents of such sessions carry session.sampled_for_error and report _dd.configuration.session_sample_rate 0. - The session counts as sampled for crash attribution, and its views are still snapshotted locally, so a native crash or freeze reported on the next launch is delivered with its last view. - Remote configuration: rate 0 does not stop a session the switch kept while the switch stays on; a dark session drawn at rate 0 is redrawn when the switch turns on.
Launch parameter `soe 1` enables sessionOnError; scenarios soe, soe-quiet, soe-secret (error dropped by the mapper) and native-crash drive the release, discard, mapper and crash paths from the command line. The demo mapper now also drops error events whose message contains "secret".
…ssionOnError edge cases - Release every held detail whether or not its view document is in the buffer: views only decide the order. An error raised before the first view, with view tracking off, or whose view document the event mapper dropped was otherwise lost together with the release it triggered. - An `immediate` remote change ends a sampled session only when the rate moved; a change to sessionOnError alone no longer ends a session the rate kept. - SDK stop drops what a withheld session holds and cancels a release still waiting on its jitter, so it never fires through a stopped core (the pre-stop flush that would release it is skipped under a refused consent). - Remove the unused WithholdingFeatureScope.isWithholding().
…serialized A refused tracking consent wiped the batches on disk and the last-view snapshot, but never reached the events a sessionOnError session still held in memory: they were cleared only when a RUM write happened while consent was refused. Consent refused and granted again with no write in between let a later error release the history collected before the refusal; the opposite timing (an error scheduled, then a refusal before its jitter ran out) detached the buffer through a writer that rejects everything, after which the session wrote straight through with its error gone. The core now announces the refusal to RUM, and the session forgets what it held, cancels the pending release and goes back to waiting for an error. The buffer now keeps the serialized form of each event, measured once at the write, instead of the live object: the app may keep changing the attribute values it passed in, and a collected session uploads what the values were at the write, so an on-error session must release the same. The held size is now exactly the released size. A switch-only change under `immediate` activation no longer redraws a dark session that lost a fair nonzero draw: the dark branch now requires the rate to have moved, as the sampled branch already did.
An app's event mapper runs inside the write of the event it maps, and may end the session from there — on an authentication error, say. For a sessionOnError session the end came before the error reached the buffer: the buffer was thrown away as un-errored, and the error the mapper had just kept was then refused as a straggler of a discarded session. When a write is in progress, the end now waits for it to land and decides on what it left behind. An error too large for the buffer earns the release only once storage has accepted it. A history uploaded for an error the backend never receives is a session nobody can explain.
…e it A rate the console announced for the next session, republished under `immediate` beside a changed `sessionOnError`, was re-decided as if the rate had moved in that publication: a collected session ended, and a session kept on error threw its history away. The settings guard is a pair now, so a changed switch reached the decision that previously stopped at the rate alone. The decision now asks whether this publication is the one that moved the rate — different from both the previous resolution and the draw — before `immediate` re-decides. The remote configuration cache moves to format 2. An entry written by an SDK that never read `session_on_error` carries a validator for a response this SDK has not seen; a 304 against it would keep the switch unknown for as long as the console left the configuration alone.
…ld view document A crash reaches a live session only as a replay of a process that already died, and the crash feature drops its own copy once RUM has taken it. In a sessionOnError session that copy sat in memory behind the jitter, and a process that died before the jitter ran out lost the crash for good. Crashes are spread across the fleet by app launches, not by a jitter, so a withheld session releases on one at once. A view document is assembled before its mapper runs; a mapper that reports into the SDK has the next version written first, and the buffer then replaced it with the older document. The newest document version now wins whatever order they arrive in. The remote configuration entry carries its format so an entry written by an SDK that never read `session_on_error` keeps its rate but retires its validator: the next request asks for the whole body instead of earning a 304 that would leave the switch unknown. The key no longer changes, so a stored emergency stop stays in force across the upgrade.
A session kept only on error has nothing on the backend until it is released, so an id handed to the app before then could never be looked up — a ticket correlated with it would point at a session that may never exist. getCurrentSessionId reports undefined while the session withholds its events, and the real id from the release on, as the other platforms report a session that is not yet collected.
…eplay A sessionOnError session thrown away without an error left its last view on file, and a crash replayed on the next launch rebuilt the session from it: one view and the crash, for a session the backend was promised never to see. The snapshot of a session that is thrown away — at its end, or at SDK stop — is deleted with it; a released session's, and any other session's, stays. A crash of a dead process that nothing attributes to a session is no longer written into a session that withholds its events either: it is not that session's error, and it goes nowhere, as it does when the current session was not drawn. An uncaught ArkTS exception now meets the app's event mapper before the crash feature persists it. The error itself is only assembled on the next launch, but what the crash does to the session — counting it, releasing what the session held — happens in the dying process, and an error the mapper drops must do neither. A dropped crash is remembered as consumed so the watcher's copy does not come back, and is never replayed. Without the crash feature, an uncaught exception released a withheld session behind its jitter, which a dying process may not live out; it releases at once now. Unhandled promise rejections keep the jitter. An immediate rate change away from zero no longer ends a session the switch kept: that is not an emergency stop, and the re-draw threw away the minute the session was holding for an error. The release log reports the writes storage accepted and refused; the discard log reports what was thrown away.
…rash promise The configuration doc now says what an uncaught exception the mapper drops does (nothing), that a thrown-away session is never rebuilt by a later crash, and names the eviction rule plainly. getCurrentSessionId's doc says a session the rate did not draw still reports its id. The demo gains two runs: a session thrown away and then a native crash, and a crash the demo mapper drops.
The event the app's mapper was asked about at crash time was assembled on its own — untruncated text, the current time, none of the fields the replay adds — so the mapper could keep it now and drop the replayed one later: a session released and counted for an error that never arrived. The crash feature now builds the question from the persisted incident through the same path the replay uses, and RUM answers through the same assembly, so the mapper judges one event twice rather than two events. The question is only asked where its answer changes something in the dying process: a terminating policy, for a session that withholds its events. A session the rate collects, and OBSERVE_ONLY, run the mapper once through the paths they always had — the crash-time check had been dropping an OBSERVE_ONLY error whose mapper refuses crashes but keeps errors, and marking the fault consumed, for customers who never turned the switch on. The crash storage hands back the file name it wrote, so a crash the mapper drops is removed again. The consent log no longer claims a refused consent for a mapper decision; the release log names the session; the inherited-crash log says the crash is not reported.
The changelog states that an unattributable crash replayed on a later launch is not reported while the current session withholds, and that the event mapper must be pure because a terminating crash is mapped at crash time and again at replay. The demo gains a crash_policy launch parameter to run the crash feature's OBSERVE_ONLY policy.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
sessionOnErrorto the RUM SDK. Sessions that the regularsessionSampleRatedraw does not pick are still assembled, but their events are held in memory instead of being written. If the session reports an error, the last 60 seconds of events are released once, after a 0–3 s delay derived from a hash of the session id. After that, the session is collected normally. Sessions that never error are discarded and never reach the intake.Configuration
RumConfiguration.Builder.setSessionOnError(boolean), default off.rum.sessionOnError(boolean). When it is absent or not a boolean, the init value is kept.beforeSamplingreturns0, the switch is turned off for that session.Buffer (
internal/scope/WithheldEvents.ets)When a session is released or discarded
setForcedSession()and terminating ArkTS crashes release immediately.Reporting
session.sampled_for_error: true, and every event reports_dd.configuration.session_sample_rate: 0.Remote configuration
0with the switch on does not stop a session kept on error.0stops it.0is redrawn when the switch turns on.immediateactivation only when the rate actually changes.Customers who don't enable the switch keep their current behaviour: no buffer is created, and every new parameter has a default.
The demo app gets e2e hooks: an
soelaunch parameter, an error-dropping mapper rule, and a native-crash scenario.Testing
SessionOnError.test.ets).