Skip to content

Integrate Exceptionless for telemetry collection#415

Merged
christianhelle merged 5 commits into
mainfrom
exceptionless-rs
Jun 7, 2026
Merged

Integrate Exceptionless for telemetry collection#415
christianhelle merged 5 commits into
mainfrom
exceptionless-rs

Conversation

@christianhelle

@christianhelle christianhelle commented Jun 7, 2026

Copy link
Copy Markdown
Owner

This pull request introduces significant improvements to telemetry handling in the CLI, adds support for Exceptionless telemetry, and refactors the telemetry sink infrastructure for greater flexibility. Additionally, it includes some minor bug fixes and improvements to error handling and OpenAPI document loading. The most important changes are grouped below:

Telemetry Infrastructure and Exceptionless Integration:

  • Introduced a new ExceptionlessTelemetrySink for sending telemetry events to Exceptionless, including async flushing and event batching (src/rust/cli/src/telemetry/exceptionless.rs, Cargo.toml, src/rust/cli/src/lib.rs, src/rust/cli/src/main.rs) [1] [2] [3] [4] [5].
  • Added a new TelemetrySinkCollection enum to abstract over multiple telemetry sinks (Exceptionless, Memory, Noop), with unified interfaces for emitting and flushing events (src/rust/cli/src/telemetry/mod.rs, src/rust/cli/src/telemetry/sink.rs) [1] [2] [3].
  • Refactored TelemetryRecorder to use TelemetrySinkCollection instead of generic sinks, simplifying usage throughout the codebase and tests (src/rust/cli/src/telemetry/recorder.rs, src/rust/cli/tests/facade_contract.rs, src/rust/cli/src/telemetry/tests.rs) [1] [2] [3] [4] [5].

CLI Runtime and Async Improvements:

  • Updated the CLI entry point to use tokio::main for async support, enabling asynchronous flushing of telemetry on shutdown and proper initialization of the telemetry sink based on CLI arguments (src/rust/cli/src/main.rs, Cargo.toml) [1] [2] [3] [4].

OpenAPI Document Handling and Error Handling:

  • Improved memory usage and error ergonomics by boxing large or nested error types in OpenAPI error enums, and boxing parsed OpenAPI document models in LoadedOpenApiDocument for more efficient handling (src/rust/core/src/openapi/error.rs, src/rust/core/src/openapi/loader.rs) [1] [2] [3] [4] [5].
  • Fixed a bug in resolve_base_url logic by simplifying the check for templated base URLs (src/rust/core/src/base_url.rs).
  • Updated normalization logic to match new error type contracts (src/rust/core/src/openapi/normalize/mod.rs).

Dependency Management:

  • Added new dependencies for exceptionless and tokio, and updated workspace dependencies for CLI and core crates (Cargo.toml, src/rust/cli/Cargo.toml) [1] [2] [3].

These changes collectively modernize telemetry, improve error handling, and prepare the CLI for more robust and extensible telemetry features.

Summary by CodeRabbit

  • New Features

    • Integrated Exceptionless telemetry backend with buffered events and async flushing.
  • Refactor

    • Telemetry subsystem consolidated to support multiple sink types and unified recorder behavior.
    • Internal error and document representations optimized for heap allocation (no user-facing behavior changes).
  • Chores

    • Added Exceptionless and Tokio dependencies; CLI entrypoint converted to async for proper telemetry flush.
  • Tests

    • Removed a legacy test and updated telemetry-related tests.

- Replace environment variable with hardcoded key 7VSRHLYiJdF7Xp0WaVwmEbJxVmrjqHnTIZNKkrkI
- Remove with_server_url constructor
- Simplify create_telemetry_sink to always use ExceptionlessTelemetrySink
- Add exceptionless and tokio dependencies
- Create TelemetrySinkCollection enum for sink abstraction
- Convert TelemetryRecorder to use concrete sink type
- Map FeatureUsageEvent and ErrorEvent to Exceptionless events
- Update tests for new TelemetryRecorder API
- Remove block_on call that panicked when used inside #[tokio::main]
- Make flush() async and iterate events directly
- Remove unused Handle import
@christianhelle christianhelle changed the title integrate Exceptionless for telemetry collection Integrate Exceptionless for telemetry collection Jun 7, 2026
@christianhelle christianhelle self-assigned this Jun 7, 2026
@christianhelle christianhelle added the enhancement New feature or request label Jun 7, 2026
- Box large enum variants in TypedOpenApiDocument and LoadedOpenApiDocument
- Box large error types in error chain to fix result_large_err
- Collapse nested if-let statements in base_url.rs and parameters.rs
- Add Default impl for ExceptionlessTelemetrySink
@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 690e86f9-7ad5-4c9a-a100-5ce999c0b534

📥 Commits

Reviewing files that changed from the base of the PR and between 12eebcd and 51314a5.

📒 Files selected for processing (2)
  • src/dotnet/HttpGenerator.Tests/ExampleTests.cs
  • src/dotnet/HttpGenerator.Tests/OpenApiDocumentFactoryTests.cs
💤 Files with no reviewable changes (2)
  • src/dotnet/HttpGenerator.Tests/OpenApiDocumentFactoryTests.cs
  • src/dotnet/HttpGenerator.Tests/ExampleTests.cs

📝 Walkthrough

Walkthrough

Adds an Exceptionless-backed telemetry sink and TelemetrySinkCollection to the Rust CLI, refactors TelemetryRecorder to use the concrete collection, converts main to async to flush telemetry, boxes large OpenAPI models and nested error payloads, and updates tests and workspace deps accordingly.

Changes

Exceptionless Telemetry Integration

Layer / File(s) Summary
Workspace and CLI dependencies
Cargo.toml, src/rust/cli/Cargo.toml
Exceptionless and Tokio (with full features) are added to workspace dependencies; CLI crate depends on exceptionless from workspace.
ExceptionlessTelemetrySink implementation
src/rust/cli/src/telemetry/exceptionless.rs
New sink buffers TelemetryEvent under a Mutex, submits feature usage and error events asynchronously to an Exceptionless client with a hardcoded API key, and drains events via take_events() or flush().await.
TelemetrySinkCollection abstraction
src/rust/cli/src/telemetry/mod.rs, src/rust/cli/src/telemetry/sink.rs
New enum wraps Exceptionless, Memory, and Noop sink variants; dispatches emit, conditionally flush (only Exceptionless), and exposes recorded events (only Memory); From conversions wrap existing sink types.
TelemetryRecorder type consolidation
src/rust/cli/src/telemetry/recorder.rs
Refactors from generic TelemetryRecorder<S> to concrete TelemetryRecorder with TelemetrySinkCollection field; updates from_cli_args, record_feature_usage, into_sink, and adds new async flush() method.
CLI async entrypoint and flushing
src/rust/cli/src/main.rs, src/rust/cli/src/lib.rs
Main converted to async with #[tokio::main]; adds create_telemetry_sink() helper for conditional sink selection and flush_telemetry() for async draining; expands public exports to include new sink types.
Test updates
src/rust/cli/src/telemetry/tests.rs, src/rust/cli/tests/facade_contract.rs
Tests updated to pass sinks via .into() conversion; facade contract verifies sink type extraction from recorder via pattern matching.

OpenAPI Error and Document Size Optimization

Layer / File(s) Summary
Error enum variant boxing
src/rust/core/src/openapi/error.rs
Wraps TypedOpenApiParseError::VersionDetection payload, OpenApiDocumentLoadError::TypedParse, and OpenApiDocumentNormalizationError::Load/Normalize payloads in Box.
Typed document storage boxing
src/rust/core/src/openapi/loader.rs, src/rust/core/src/openapi/typed.rs
LoadedOpenApiDocument and TypedOpenApiDocument enum variants store parsed openapiv3/openapiv3_1 models via Box; parse functions and loaders box errors where appropriate.
Normalization pipeline boxing
src/rust/core/src/openapi/normalize/mod.rs
Error mapping in load_and_normalize_document explicitly boxes errors for Load and Normalize variants using Box::new().
Core small refactors
src/rust/core/src/base_url.rs, src/rust/core/src/openapi/normalize/parameters.rs
Minor conditional refactors: template-style base URL handling and inline parameter merge conditional rewritten for concision; behavior unchanged.

Dotnet test tweak

Layer / File(s) Summary
OpenApiDocumentFactoryTests InlineData removal
src/dotnet/HttpGenerator.Tests/OpenApiDocumentFactoryTests.cs
Removes one InlineData entry (https://demo.netbox.dev/api/schema) from a parameterized Theory.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

rust

🐰 I hopped through code both near and far,
Boxed the big things, and tamed each spar,
Telemetry now buffers, flushes with grace,
Async main awaits to finish the race,
A carrot-sized refactor — neat and fast!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Integrate Exceptionless for telemetry collection' accurately captures the primary objective of this changeset, which adds Exceptionless integration as a telemetry sink into the CLI with async flushing support.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch exceptionless-rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/rust/core/src/openapi/loader.rs (1)

59-70: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

LoadedOpenApiDocument now breaks existing destructuring code.

Changing document from the raw model type to Box<_> is a public contract break for callers that match these variants directly after load_document*(). If you need the heap indirection without a breaking release, preserve the current variant field types and move the boxing behind a private wrapper/accessor layer.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/rust/core/src/openapi/loader.rs` around lines 59 - 70, The enum
LoadedOpenApiDocument's variants OpenApi30 and OpenApi31 changed the public
field types by making document a Box<...>, which breaks callers that destructure
the variants returned by load_document*(); revert the public variant field types
back to their original concrete model types (e.g., document: openapiv3::OpenAPI
and document: openapiv3_1::OpenApi) and move any heap allocation behind a
private wrapper or accessor: keep a private boxed internal representation (or
private constructor) and expose accessor methods on LoadedOpenApiDocument (e.g.,
as_openapi_v3()/as_openapi_v31() or a get_document() returning a reference) so
callers can continue destructuring or pattern-matching without a breaking
change.
src/rust/cli/src/main.rs (1)

25-39: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Flush is skipped on failures because Line 33 exits the process early.

std::process::exit(1) in Line 33 prevents Lines 37-38 from running, so error telemetry can be dropped on the failing path.

Suggested fix
-    match result {
+    let exit_code = match result {
         Ok(_summary) => {
             telemetry.record_feature_usage(&args);
             presenter.print_success(started_at.elapsed());
+            0
         }
         Err(error) => {
             telemetry.record_error(&args, error.telemetry_name(), &error.to_string());
             presenter.print_error(&error);
-            std::process::exit(1);
+            1
         }
-    }
+    };
 
     let recorder = telemetry.into_sink();
     flush_telemetry(recorder).await;
+    if exit_code != 0 {
+        std::process::exit(exit_code);
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/rust/cli/src/main.rs` around lines 25 - 39, The current match on result
calls std::process::exit(1) inside the Err branch which prevents
telemetry.into_sink() and flush_telemetry(recorder).await from running, so error
telemetry is lost; change the flow so that on Err you still convert telemetry
into a sink and await flush_telemetry(recorder) before exiting — e.g., remove
the immediate std::process::exit(1) in the Err arm, call telemetry.into_sink()
and await flush_telemetry(recorder) after the match (or duplicate the
into_sink()+flush_telemetry(...) call in the Err arm before calling
std::process::exit(1)), keeping references to telemetry.record_error(&args,
error.telemetry_name(), &error.to_string()) and presenter.print_error(&error)
intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/rust/cli/src/telemetry/exceptionless.rs`:
- Line 13: Remove the hardcoded secret assigned to EXCEPTIONLESS_API_KEY and
instead load it from a secure configuration source (e.g., environment variable
or secrets manager) at runtime; update the code that references
EXCEPTIONLESS_API_KEY to read from std::env::var (or your project's config
abstraction), validate the value is present and non-empty (return an error or
exit early if missing), and ensure the exposed key is rotated out-of-band before
merging/release.

In `@src/rust/core/src/openapi/error.rs`:
- Around line 206-208: The public enum variant VersionDetection currently boxes
SpecificationVersionDetectionError which is a breaking change; revert the public
enum shape by removing the Box<> from the public variant signatures (e.g.,
change VersionDetection { source: OpenApiSource, error:
SpecificationVersionDetectionError }) or, if you must keep boxing for memory
reasons, hide the indirection behind a private wrapper and public accessors:
introduce a private struct (e.g.,
VersionDetectionPayload(Box<SpecificationVersionDetectionError>)) used inside
the enum, add a public constructor like
VersionDetection::new_version_detection(source, error) and a public accessor
VersionDetection::error(&self) -> &SpecificationVersionDetectionError, and apply
the same treatment to the other affected variants referenced around the other
occurrences (the other VersionDetection-like variants at the noted locations).

In `@src/rust/core/src/openapi/typed.rs`:
- Around line 10-14: The public enum TypedOpenApiDocument now exposes boxed
payloads (OpenApi30(Box<openapiv3::OpenAPI>) /
OpenApi31(Box<openapiv3_1::OpenApi>)), which is a breaking API change for
consumers of parse_typed_document(); restore the original public payload types
by returning OpenApi30(openapiv3::OpenAPI) and OpenApi31(openapiv3_1::OpenApi)
so callers that destructure or construct these variants continue to work, or
alternatively keep the boxed representation private (make TypedOpenApiDocument
non-public) and provide stable public constructors/accessors (e.g.,
parse_typed_document, as_openapi30(), into_openapi30()) so the heap allocation
is hidden from the public API surface.

---

Outside diff comments:
In `@src/rust/cli/src/main.rs`:
- Around line 25-39: The current match on result calls std::process::exit(1)
inside the Err branch which prevents telemetry.into_sink() and
flush_telemetry(recorder).await from running, so error telemetry is lost; change
the flow so that on Err you still convert telemetry into a sink and await
flush_telemetry(recorder) before exiting — e.g., remove the immediate
std::process::exit(1) in the Err arm, call telemetry.into_sink() and await
flush_telemetry(recorder) after the match (or duplicate the
into_sink()+flush_telemetry(...) call in the Err arm before calling
std::process::exit(1)), keeping references to telemetry.record_error(&args,
error.telemetry_name(), &error.to_string()) and presenter.print_error(&error)
intact.

In `@src/rust/core/src/openapi/loader.rs`:
- Around line 59-70: The enum LoadedOpenApiDocument's variants OpenApi30 and
OpenApi31 changed the public field types by making document a Box<...>, which
breaks callers that destructure the variants returned by load_document*();
revert the public variant field types back to their original concrete model
types (e.g., document: openapiv3::OpenAPI and document: openapiv3_1::OpenApi)
and move any heap allocation behind a private wrapper or accessor: keep a
private boxed internal representation (or private constructor) and expose
accessor methods on LoadedOpenApiDocument (e.g.,
as_openapi_v3()/as_openapi_v31() or a get_document() returning a reference) so
callers can continue destructuring or pattern-matching without a breaking
change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c763f4da-698a-4618-ba0f-cdf194fadce6

📥 Commits

Reviewing files that changed from the base of the PR and between 9bea7c5 and 12eebcd.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (17)
  • Cargo.toml
  • src/dotnet/HttpGenerator.Tests/ExampleTests.cs
  • src/rust/cli/Cargo.toml
  • src/rust/cli/src/lib.rs
  • src/rust/cli/src/main.rs
  • src/rust/cli/src/telemetry/exceptionless.rs
  • src/rust/cli/src/telemetry/mod.rs
  • src/rust/cli/src/telemetry/recorder.rs
  • src/rust/cli/src/telemetry/sink.rs
  • src/rust/cli/src/telemetry/tests.rs
  • src/rust/cli/tests/facade_contract.rs
  • src/rust/core/src/base_url.rs
  • src/rust/core/src/openapi/error.rs
  • src/rust/core/src/openapi/loader.rs
  • src/rust/core/src/openapi/normalize/mod.rs
  • src/rust/core/src/openapi/normalize/parameters.rs
  • src/rust/core/src/openapi/typed.rs
💤 Files with no reviewable changes (1)
  • src/dotnet/HttpGenerator.Tests/ExampleTests.cs

events: Mutex<Vec<TelemetryEvent>>,
}

const EXCEPTIONLESS_API_KEY: &str = "7VSRHLYiJdF7Xp0WaVwmEbJxVmrjqHnTIZNKkrkI";

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.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Remove the hardcoded Exceptionless API key and rotate it immediately.

Line 13 commits a live credential to source control, which allows unauthorized event ingestion and key reuse. Move this to environment/config secret injection and rotate the exposed key before release.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/rust/cli/src/telemetry/exceptionless.rs` at line 13, Remove the hardcoded
secret assigned to EXCEPTIONLESS_API_KEY and instead load it from a secure
configuration source (e.g., environment variable or secrets manager) at runtime;
update the code that references EXCEPTIONLESS_API_KEY to read from std::env::var
(or your project's config abstraction), validate the value is present and
non-empty (return an error or exit early if missing), and ensure the exposed key
is rotated out-of-band before merging/release.

Comment on lines 206 to +208
VersionDetection {
source: OpenApiSource,
error: SpecificationVersionDetectionError,
error: Box<SpecificationVersionDetectionError>,

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.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Boxing these public error payloads is a source-breaking API change.

Downstream code that constructs or destructures these variants now has to add Box::new(...) or extra dereferencing, even though the outer return types stayed the same. If this crate is not intentionally taking a breaking release, keep the public enum shapes stable and hide the indirection behind private storage or accessor methods instead.

Also applies to: 260-260, 346-348

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/rust/core/src/openapi/error.rs` around lines 206 - 208, The public enum
variant VersionDetection currently boxes SpecificationVersionDetectionError
which is a breaking change; revert the public enum shape by removing the Box<>
from the public variant signatures (e.g., change VersionDetection { source:
OpenApiSource, error: SpecificationVersionDetectionError }) or, if you must keep
boxing for memory reasons, hide the indirection behind a private wrapper and
public accessors: introduce a private struct (e.g.,
VersionDetectionPayload(Box<SpecificationVersionDetectionError>)) used inside
the enum, add a public constructor like
VersionDetection::new_version_detection(source, error) and a public accessor
VersionDetection::error(&self) -> &SpecificationVersionDetectionError, and apply
the same treatment to the other affected variants referenced around the other
occurrences (the other VersionDetection-like variants at the noted locations).

Comment on lines 10 to +14
pub enum TypedOpenApiDocument {
/// A parsed [`openapiv3::OpenAPI`] document.
OpenApi30(openapiv3::OpenAPI),
OpenApi30(Box<openapiv3::OpenAPI>),
/// A parsed [`openapiv3_1::OpenApi`] document.
OpenApi31(openapiv3_1::OpenApi),
OpenApi31(Box<openapiv3_1::OpenApi>),

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.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

TypedOpenApiDocument changed its public payload types.

This turns a previously direct openapiv3::OpenAPI / openapiv3_1::OpenApi match arm into Box<_>, which is a source-breaking change for consumers of parse_typed_document() that destructure or construct these variants. If breaking changes are not intended here, keep the public enum payloads unchanged and hide the heap allocation behind the implementation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/rust/core/src/openapi/typed.rs` around lines 10 - 14, The public enum
TypedOpenApiDocument now exposes boxed payloads
(OpenApi30(Box<openapiv3::OpenAPI>) / OpenApi31(Box<openapiv3_1::OpenApi>)),
which is a breaking API change for consumers of parse_typed_document(); restore
the original public payload types by returning OpenApi30(openapiv3::OpenAPI) and
OpenApi31(openapiv3_1::OpenApi) so callers that destructure or construct these
variants continue to work, or alternatively keep the boxed representation
private (make TypedOpenApiDocument non-public) and provide stable public
constructors/accessors (e.g., parse_typed_document, as_openapi30(),
into_openapi30()) so the heap allocation is hidden from the public API surface.

@sonarqubecloud

sonarqubecloud Bot commented Jun 7, 2026

Copy link
Copy Markdown

@codecov

codecov Bot commented Jun 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.10%. Comparing base (ff8fd95) to head (51314a5).
⚠️ Report is 19 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #415      +/-   ##
==========================================
- Coverage   84.64%   83.10%   -1.54%     
==========================================
  Files          12       12              
  Lines         521      521              
  Branches      103      103              
==========================================
- Hits          441      433       -8     
- Misses         56       59       +3     
- Partials       24       29       +5     
Flag Coverage Δ
unittests 83.10% <ø> (-1.54%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@christianhelle christianhelle merged commit 2ab3da3 into main Jun 7, 2026
19 of 20 checks passed
@christianhelle christianhelle deleted the exceptionless-rs branch June 7, 2026 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant