Skip to content

fix(android): match sampling regexes as substrings and skip invalid patterns - #836

Merged
Vadman97 merged 1 commit into
mainfrom
vadim/android-sampling-regex
Oct 21, 2026
Merged

Vadman97 merged 1 commit into
mainfrom
vadim/android-sampling-regex

Conversation

@Vadman97

@Vadman97 Vadman97 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes how the Android SDK handles sampling regex rules. It now matches the way the Go SDK does it and the way the Java plugin was fixed in #381, following Andrey's review comment there.

  • Substring matching: CustomSampler called Regex.matches, which only matches the whole string. Every other SDK checks whether the pattern appears anywhere in the value. It now calls containsMatchIn, so health matches GET /health-check. ^ and $ still work when a rule needs a full match.
  • Invalid patterns no longer throw: patterns were compiled lazily from inside the span/log processors. A bad pattern from the backend threw PatternSyntaxException out of EventSpanProcessor.onEnd / SamplingLogProcessor.onEmit. Nothing upstream catches it, including the OpenTelemetry SDK's SdkSpan.end / SdkLogRecordBuilder.emit, so it reached the app's span.end() or log call. Now each pattern's compile result is cached, failures included. A bad pattern logs one warning through the SDK's ObserveLogger and its rule never matches. Other rules in the same config still apply.
  • ObservabilityService passes its logger to CustomSampler through a new optional logger parameter (defaults to null, so the constructor stays source-compatible).

Note: the cache is cleared on setConfig, so a bad pattern is warned about once each time a config is loaded, not on every span or log.

How did you test this change?

  • Added Regex Matching Tests to CustomSamplerTest:
    • substring match for span names and log messages
    • ^, $ and ^...$ anchors are still respected
    • an invalid pattern doesn't throw and never matches
    • an invalid-regex rule is skipped while later rules in the same config still apply (spans and logs)
    • the warning is logged exactly once over repeated spans
    • no warning for a valid pattern
  • Ran ./gradlew :lib:testDebugUnitTest locally in sdk/@launchdarkly/observability-android (JDK 21, Android SDK platform 35): 544 tests, 0 failures, 2 skipped (already skipped before this change).
  • Checked the tests against the old behavior: with matches and no exception handling put back, 7 of the 9 new tests fail.
  • No existing tests relied on full-match semantics, so none needed changing.

🤖 Generated with Claude Code

Opened from termag


Note

Overview
Aligns Android sampling regex behavior with other LaunchDarkly observability SDKs and hardens error handling when remote rules are malformed.

CustomSampler now uses containsMatchIn instead of Regex.matches, so patterns match when they appear anywhere in span names or log messages (e.g. health matches GET /health-check); ^ / $ still enforce full-string matches when needed. Invalid patterns are compiled through a cached CompiledRegex path: compile failures log one warning via optional ObserveLogger, never throw into span/log export, and that rule never matches while later rules in the same config still apply.

ObservabilityService passes its logger into CustomSampler. Unit tests add a Regex Matching suite for substring/anchor behavior, invalid-regex safety, and one-time warnings.

Reviewed by Cursor Bugbot for commit 71a5b05. Bugbot is set up for automated code reviews on this repo. Configure here.

…atterns

CustomSampler used Regex.matches (full-string match), unlike the other
SDKs, which do substring matching. It also compiled patterns lazily
during span/log processing, so an invalid pattern from the backend threw
PatternSyntaxException out of the span processor / log processor.

Use containsMatchIn so anchors are needed for full matches, and cache
the compilation result per pattern, including failures, so an invalid
pattern logs one warning and the rule never matches. Mirrors the Java
plugin fix in #381.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Generated-by: termag
@Vadman97
Vadman97 marked this pull request as ready for review October 20, 2026 16:28
@Vadman97
Vadman97 requested a review from a team as a code owner October 20, 2026 16:28

@abelonogov-ld abelonogov-ld left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cool! It is even compiled!

@Vadman97
Vadman97 merged commit 76127ee into main Oct 21, 2026
28 checks passed
@Vadman97
Vadman97 deleted the vadim/android-sampling-regex branch October 21, 2026 02:39
Vadman97 pushed a commit that referenced this pull request Oct 21, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>launchdarkly-observability-android: 0.69.1</summary>

##
[0.69.1](launchdarkly-observability-android-0.69.0...launchdarkly-observability-android-0.69.1)
(2026-10-21)


### Bug Fixes

* **android:** match sampling regexes as substrings and skip invalid
patterns
([#836](#836))
([76127ee](76127ee))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> **Release `launchdarkly-observability-android` 0.69.1** via Release
Please: bumps the package version in `.release-please-manifest.json` and
`gradle.properties`, and adds the **0.69.1** changelog entry.
> 
> This patch release ships the bugfix from
[#836](#836):
Android custom sampling regex rules now use **substring** matching
(aligned with other LaunchDarkly observability SDKs) and **invalid
patterns are skipped** after a one-time warning instead of breaking
sampling.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e7d81fc. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants