Skip to content
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
53e7a92
base impl for JNI
buenaflor Jul 29, 2025
a3b9557
base impl for cocoa -> maybe improve perf
buenaflor Jul 29, 2025
8ebbb99
update
buenaflor Jul 29, 2025
55e7802
update
buenaflor Jul 29, 2025
a048625
update
buenaflor Jul 29, 2025
6a637d6
update
buenaflor Jul 29, 2025
5fa2e5f
update
buenaflor Jul 29, 2025
fcdc0a0
Remove method channels for captureEnvelope
buenaflor Jul 29, 2025
a60b98b
Update
buenaflor Jul 29, 2025
8243b86
Update
buenaflor Jul 29, 2025
4d265af
Merge branch 'main' into enh/ffi-jni-capture-envelope
buenaflor Aug 5, 2025
2cc00d2
Merge branch 'main' into enh/ffi-jni-capture-envelope
buenaflor Aug 6, 2025
53412e6
Merge branch 'main' into enh/ffi-jni-capture-envelope
buenaflor Aug 7, 2025
e1b0fc1
Update
buenaflor Aug 7, 2025
42ee582
Update
buenaflor Aug 7, 2025
021872e
Update
buenaflor Aug 7, 2025
fe5f773
Update
buenaflor Aug 7, 2025
7ff132b
Update
buenaflor Aug 11, 2025
9d4755a
Update
buenaflor Aug 11, 2025
14b68d5
Update
buenaflor Aug 11, 2025
94e033c
Merge branch 'main' into enh/ffi-jni-capture-envelope
buenaflor Aug 11, 2025
01ae22f
Merge branch 'main' into enh/ffi-jni-capture-envelope
buenaflor Aug 11, 2025
3c78cc9
Update sentry_native_channel_test.dart
buenaflor Aug 11, 2025
3619290
Update
buenaflor Aug 11, 2025
c8d73c0
Update
buenaflor Aug 11, 2025
2b698f2
Update
buenaflor Aug 12, 2025
5b670ff
Update
buenaflor Aug 12, 2025
ad83af2
Update
buenaflor Aug 12, 2025
a5e54cd
Update test
buenaflor Aug 12, 2025
1105eb8
Merge branch 'main' into deps/bump-ffigen
buenaflor Aug 12, 2025
fd3d9c1
Update test
buenaflor Aug 12, 2025
acc40d1
Update CHANGELOG
buenaflor Aug 12, 2025
bd2c9cc
Update CHANGELOG
buenaflor Aug 12, 2025
01e7c23
Update native bindings
buenaflor Aug 12, 2025
3d1e5a6
Test not verbose
buenaflor Aug 12, 2025
64f9a5c
fix test
buenaflor Aug 12, 2025
9a84ffe
Merge branch 'deps/bump-ffigen' into enh/ffi-jni-capture-envelope
buenaflor Aug 12, 2025
6985094
Update
buenaflor Aug 13, 2025
162f88b
Update
buenaflor Aug 13, 2025
95dde11
Update
buenaflor Aug 13, 2025
f13ed42
Update tests
buenaflor Aug 13, 2025
2867ece
Fix analyze
buenaflor Aug 13, 2025
3da86cd
Fix tests
buenaflor Aug 13, 2025
1d6c314
Merge branch 'main' into deps/bump-ffigen
buenaflor Aug 13, 2025
dc051c6
Fix tests
buenaflor Aug 13, 2025
314c17b
Merge branch 'deps/bump-ffigen' into enh/ffi-jni-capture-envelope
buenaflor Aug 13, 2025
303cf57
Fix linux tests
buenaflor Aug 13, 2025
4fd5e5f
Merge branch 'main' into enh/ffi-jni-capture-envelope
buenaflor Aug 14, 2025
0863972
Fix imports
buenaflor Aug 14, 2025
31f6d9c
Merge branch 'main' into enh/ffi-jni-capture-envelope
buenaflor Aug 25, 2025
d9c139e
Merge branch 'main' into enh/ffi-jni-capture-envelope
buenaflor Aug 26, 2025
5692bba
Ignore coverage for ffi/jni captureEnvelope paths
buenaflor Aug 26, 2025
f61db9e
Fix potential memory leak
buenaflor Aug 26, 2025
0e52c38
Update
buenaflor Aug 26, 2025
128fa36
Fix
buenaflor Aug 26, 2025
782dc54
Fix
buenaflor Aug 26, 2025
2c2996d
Update
buenaflor Aug 27, 2025
95625ea
Analyze
buenaflor Aug 27, 2025
d9df09c
Merge branch 'main' into enh/ffi-jni-capture-envelope
buenaflor Aug 27, 2025
28a9665
Revert github workflow
buenaflor Aug 27, 2025
cca108c
Update
buenaflor Aug 27, 2025
23ae401
Update
buenaflor Aug 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
- Add `sentry.origin` to logs created by `LoggingIntegration` ([#3153](https://github.com/getsentry/sentry-dart/pull/3153))
- Tag all spans with thread info on non-web platforms ([#3101](https://github.com/getsentry/sentry-dart/pull/3101), [#3144](https://github.com/getsentry/sentry-dart/pull/3144))

### Enhancements

- Use FFI/JNI for `captureEnvelope` on iOS and Android ([#3115](https://github.com/getsentry/sentry-dart/pull/3115))

## 9.7.0-beta.1

### Features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ class SentryFlutterPlugin :
) {
when (call.method) {
"initNativeSdk" -> initNativeSdk(call, result)
"captureEnvelope" -> captureEnvelope(call, result)
"loadImageList" -> loadImageList(call, result)
"closeNativeSdk" -> closeNativeSdk(result)
"fetchNativeAppStart" -> fetchNativeAppStart(result)
Expand Down Expand Up @@ -368,32 +367,6 @@ class SentryFlutterPlugin :

result.success("")
}

private fun captureEnvelope(
call: MethodCall,
result: Result,
) {
if (!Sentry.isEnabled()) {
result.error("1", "The Sentry Android SDK is disabled", null)
return
}
val args = call.arguments() as List<Any>? ?: listOf()
if (args.isNotEmpty()) {
val event = args.first() as ByteArray?
val containsUnhandledException = args[1] as Boolean
if (event != null && event.isNotEmpty()) {
val id = InternalSentrySdk.captureEnvelope(event, containsUnhandledException)
if (id != null) {
result.success("")
} else {
result.error("2", "Failed to capture envelope", null)
}
return
}
}
result.error("3", "Envelope is null or empty", null)
}

private fun loadImageList(
call: MethodCall,
result: Result,
Expand Down
1 change: 1 addition & 0 deletions packages/flutter/ffi-jni.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ output:
log_level: all

classes:
- io.sentry.android.core.InternalSentrySdk
- io.sentry.android.replay.ReplayIntegration
- io.sentry.flutter.SentryFlutterPlugin
- android.graphics.Bitmap
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ public class SentryFlutterPlugin: NSObject, FlutterPlugin {
case "closeNativeSdk":
closeNativeSdk(call, result: result)

case "captureEnvelope":
captureEnvelope(call, result: result)

case "fetchNativeAppStart":
fetchNativeAppStart(result: result)

Expand Down Expand Up @@ -412,24 +409,6 @@ public class SentryFlutterPlugin: NSObject, FlutterPlugin {
return !name.isEmpty
}

private func captureEnvelope(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
guard let arguments = call.arguments as? [Any],
!arguments.isEmpty,
let data = (arguments.first as? FlutterStandardTypedData)?.data else {
print("Envelope is null or empty!")
result(FlutterError(code: "2", message: "Envelope is null or empty", details: nil))
return
}
guard let envelope = PrivateSentrySDKOnly.envelope(with: data) else {
print("Cannot parse the envelope data")
result(FlutterError(code: "3", message: "Cannot parse the envelope data", details: nil))
return
}
PrivateSentrySDKOnly.capture(envelope)
result("")
return
}

struct TimeSpan {
var startTimestampMsSinceEpoch: NSNumber
var stopTimestampMsSinceEpoch: NSNumber
Expand Down
39 changes: 39 additions & 0 deletions packages/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'dart:async';
import 'dart:ffi';

import 'package:ffi/ffi.dart';
import 'package:flutter/foundation.dart';
import 'package:meta/meta.dart';

import '../../../sentry_flutter.dart';
Expand Down Expand Up @@ -52,6 +54,43 @@ class SentryNativeCocoa extends SentryNativeChannel {
return super.init(hub);
}

@override
FutureOr<void> captureEnvelope(
Uint8List envelopeData, bool containsUnhandledException) {
// Use a safe copy-based conversion to avoid crashes due to memory issues observed
// when relying on `dataWithBytesNoCopy:length:freeWhenDone:`.
final length = envelopeData.length;
final buffer = malloc<Uint8>(length);
cocoa.NSData? nsData;
cocoa.SentryEnvelope? envelope;
try {
buffer.asTypedList(length).setAll(0, envelopeData);
nsData = cocoa.NSData.dataWithBytes_length_(_lib, buffer.cast(), length);
envelope = cocoa.PrivateSentrySDKOnly.envelopeWithData_(_lib, nsData);
cocoa.PrivateSentrySDKOnly.captureEnvelope_(_lib, envelope);
} catch (exception, stackTrace) {
options.log(SentryLevel.error, 'Failed to capture envelope',
exception: exception, stackTrace: stackTrace);

if (options.automatedTestMode) {
rethrow;
}
} finally {
// Release ObjC wrappers promptly and free the temporary C buffer.
if (envelope != null) {
try {
envelope.release();
} catch (_) {}
}
if (nsData != null) {
try {
nsData.release();
} catch (_) {}
}
malloc.free(buffer);
}
}

@override
FutureOr<void> setReplayConfig(ReplayConfig config) {
// Note: unused on iOS.
Expand Down
Loading
Loading