Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
55fa42a
Add `unknown` map to `Breadcrumb`
denrase Jul 9, 2024
e227762
move unknown reading to helper function
denrase Jul 9, 2024
bb7feb6
Move unknown test data to mocks.dart
denrase Jul 9, 2024
35bff66
Add `unknown` map to `DebugImage`
denrase Jul 9, 2024
6b6ebf7
Add `unknown` map to `DebugMeta`
denrase Jul 9, 2024
c071d10
Add `unknown` map to `Mechanism`
denrase Jul 9, 2024
d07dbd4
Add `unknown` map to `MetricSummary`
denrase Jul 9, 2024
7f87af9
Add `unknown` map to `SdkInfo `
denrase Jul 9, 2024
0cd7479
Add `unknown` map to `SdkVersion`
denrase Jul 9, 2024
7c1ba85
Add `unknown` map to `SentryApp`
denrase Jul 9, 2024
f42d993
Add `unknown` map to `SentryBrowser `
denrase Jul 9, 2024
6a2449e
Add `unknown` map to `SentryCulture`
denrase Jul 9, 2024
ca57838
Add `unknown` map to `SentryDevice `
denrase Jul 9, 2024
333b302
Add `unknown` map to `SentryEvent`
denrase Jul 9, 2024
f27e586
Add `unknown` map to `SentryException`
denrase Jul 9, 2024
d5f92f2
Add `unknown` map to `SentryGpu`
denrase Jul 9, 2024
1924e07
Add `unknown` map to `SentryMessage `
denrase Jul 9, 2024
1dc46f7
Add `unknown` map to `SentryOperatingSystem`
denrase Jul 9, 2024
f8def7f
Add `unknown` map to `SentryPackage`
denrase Jul 9, 2024
8a2bff2
Add `unknown` map to `SentryRequest`
denrase Jul 15, 2024
2aef9e9
Add `unknown` map to `SentryRuntime`
denrase Jul 15, 2024
50b21c1
Add `unknown` map to `SentryStackFrame`
denrase Jul 15, 2024
afb78d0
Add `unknown` map to `SentryStackFrame`
denrase Jul 15, 2024
7ef8109
Add `unknown` map to `SentryThread`
denrase Jul 15, 2024
ee6494a
Add `unknown` map to `SentryTraceContext`
denrase Jul 15, 2024
33ea294
Add `unknown` map to `SentryTraceContextHeader`
denrase Jul 15, 2024
934004e
Add `unknown` map to `SentryTransactionInf`
denrase Jul 15, 2024
fbb0fad
Add `unknown` map to `SentryUser`
denrase Jul 15, 2024
7953f45
Add `unknown` map to `SentryUserFeedback`
denrase Jul 15, 2024
cf6e461
Add missing u param
denrase Jul 15, 2024
42e7388
Merge branch 'main' into feat/unknown-serialization
denrase Jul 15, 2024
41026d2
add changelog entry
denrase Jul 15, 2024
6d7dd33
run dart fix
denrase Jul 15, 2024
49341c1
add missing properties to SentryStackTrace copyWith
denrase Jul 15, 2024
7a2dc8b
fix test
denrase Jul 15, 2024
14588ad
add missing field
denrase Jul 15, 2024
71a021e
Merge branch 'main' into feat/unknown-serialization
denrase Jul 15, 2024
1aab0d4
Use spread operator to add unknown fields
denrase Jul 16, 2024
c5abedc
Keep track of unknwon keys via AccessAwareMap
denrase Jul 16, 2024
565b780
Merge branch 'main' into feat/unknown-serialization
denrase Jul 16, 2024
f7ad96e
fix changelog
denrase Jul 16, 2024
a60c74c
early return for access aware map
denrase Jul 29, 2024
91458ee
add tests for mapbase
denrase Jul 29, 2024
ef0d966
Merge branch 'main' into feat/unknown-serialization
denrase Jul 29, 2024
294c0b2
fix cl
denrase Jul 29, 2024
8471ec5
only track accessed keys with values, add unknown before other keys
denrase Jul 29, 2024
2e5479c
Merge branch 'main' into feat/unknown-serialization
buenaflor Jul 30, 2024
cc0ac0f
Merge branch 'main' into feat/unknown-serialization
denrase Aug 5, 2024
7171ae6
fix cl
denrase Aug 5, 2024
3634f02
Merge branch 'main' into feat/unknown-serialization
denrase Aug 6, 2024
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 @@ -6,6 +6,10 @@

- Add support for span level measurements. ([#2214](https://github.com/getsentry/sentry-dart/pull/2214))

### Improvements

- Deserialize and serialize unknown fields ([#2153](https://github.com/getsentry/sentry-dart/pull/2153))

## 8.6.0

### Improvements
Expand Down
53 changes: 53 additions & 0 deletions dart/lib/src/protocol/access_aware_map.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import 'dart:collection';

import 'package:meta/meta.dart';

@internal
class AccessAwareMap<String, V> extends MapBase<String, V> {
AccessAwareMap(this._map);

final Map<String, V> _map;
final Set<String> _accessedKeysWithValues = {};

Set<String> get accessedKeysWithValues => _accessedKeysWithValues;

@override
V? operator [](Object? key) {
if (key is String && _map.containsKey(key)) {
_accessedKeysWithValues.add(key);
}
return _map[key];
}

@override
void operator []=(String key, V value) {
_map[key] = value;
}

@override
void clear() {
_map.clear();
_accessedKeysWithValues.clear();
}

@override
Iterable<String> get keys => _map.keys;

@override
V? remove(Object? key) {
return _map.remove(key);
}

Map<String, dynamic>? notAccessed() {
if (_accessedKeysWithValues.length == _map.length) {
return null;
}
Map<String, dynamic> unknown = _map.keys
.where((key) => !_accessedKeysWithValues.contains(key))
.fold<Map<String, dynamic>>({}, (map, key) {
map[key] = _map[key];
return map;
});
return unknown.isNotEmpty ? unknown : null;
}
}
13 changes: 11 additions & 2 deletions dart/lib/src/protocol/breadcrumb.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:meta/meta.dart';

import '../utils.dart';
import '../protocol.dart';
import 'access_aware_map.dart';

/// Structured data to describe more information prior to the event captured.
/// See `Sentry.captureEvent()`.
Expand Down Expand Up @@ -30,6 +31,7 @@ class Breadcrumb {
this.data,
SentryLevel? level,
this.type,
this.unknown,
}) : timestamp = timestamp ?? getUtcDateTime(),
level = level ?? SentryLevel.info;

Expand Down Expand Up @@ -156,30 +158,36 @@ class Breadcrumb {
/// The value is submitted to Sentry with second precision.
final DateTime timestamp;

@internal
final Map<String, dynamic>? unknown;

/// Deserializes a [Breadcrumb] from JSON [Map].
factory Breadcrumb.fromJson(Map<String, dynamic> json) {
factory Breadcrumb.fromJson(Map<String, dynamic> jsonData) {
final json = AccessAwareMap(jsonData);

final levelName = json['level'];
final timestamp = json['timestamp'];

var data = json['data'];
if (data != null) {
data = Map<String, dynamic>.from(data as Map);
}

return Breadcrumb(
timestamp: timestamp != null ? DateTime.tryParse(timestamp) : null,
message: json['message'],
category: json['category'],
data: data,
level: levelName != null ? SentryLevel.fromName(levelName) : null,
type: json['type'],
unknown: json.notAccessed(),
);
}

/// Converts this breadcrumb to a map that can be serialized to JSON according
/// to the Sentry protocol.
Map<String, dynamic> toJson() {
return {
...?unknown,
'timestamp': formatDateAsIso8601WithMillisPrecision(timestamp),
if (message != null) 'message': message,
if (category != null) 'category': category,
Expand All @@ -204,5 +212,6 @@ class Breadcrumb {
level: level ?? this.level,
type: type ?? this.type,
timestamp: timestamp ?? this.timestamp,
unknown: unknown,
);
}
12 changes: 11 additions & 1 deletion dart/lib/src/protocol/debug_image.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:meta/meta.dart';

import 'access_aware_map.dart';

/// The list of debug images contains all dynamic libraries loaded into
/// the process and their memory addresses.
/// Instruction addresses in the Stack Trace are mapped into the list of debug
Expand Down Expand Up @@ -51,6 +53,9 @@ class DebugImage {
/// MachO CPU type identifier.
final int? cpuType;

@internal
final Map<String, dynamic>? unknown;

const DebugImage({
required this.type,
this.name,
Expand All @@ -65,10 +70,12 @@ class DebugImage {
this.codeId,
this.cpuType,
this.cpuSubtype,
this.unknown,
});

/// Deserializes a [DebugImage] from JSON [Map].
factory DebugImage.fromJson(Map<String, dynamic> json) {
factory DebugImage.fromJson(Map<String, dynamic> data) {
final json = AccessAwareMap(data);
return DebugImage(
type: json['type'],
name: json['name'],
Expand All @@ -83,12 +90,14 @@ class DebugImage {
codeId: json['code_id'],
cpuType: json['cpu_type'],
cpuSubtype: json['cpu_subtype'],
unknown: json.notAccessed(),
);
}

/// Produces a [Map] that can be serialized to JSON.
Map<String, dynamic> toJson() {
return {
...?unknown,
'type': type,
if (uuid != null) 'uuid': uuid,
if (debugId != null) 'debug_id': debugId,
Expand Down Expand Up @@ -134,5 +143,6 @@ class DebugImage {
codeId: codeId ?? this.codeId,
cpuType: cpuType ?? this.cpuType,
cpuSubtype: cpuSubtype ?? this.cpuSubtype,
unknown: unknown,
);
}
15 changes: 12 additions & 3 deletions dart/lib/src/protocol/debug_meta.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:meta/meta.dart';

import '../protocol.dart';
import 'access_aware_map.dart';

/// The debug meta interface carries debug information for processing errors and crash reports.
@immutable
Expand All @@ -16,10 +17,15 @@ class DebugMeta {
/// images in order to retrieve debug files for symbolication.
List<DebugImage> get images => List.unmodifiable(_images ?? const []);

DebugMeta({this.sdk, List<DebugImage>? images}) : _images = images;
DebugMeta({this.sdk, List<DebugImage>? images, this.unknown})
: _images = images;

@internal
final Map<String, dynamic>? unknown;

/// Deserializes a [DebugMeta] from JSON [Map].
factory DebugMeta.fromJson(Map<String, dynamic> json) {
factory DebugMeta.fromJson(Map<String, dynamic> data) {
final json = AccessAwareMap(data);
final sdkInfoJson = json['sdk_info'];
final debugImagesJson = json['images'] as List<dynamic>?;
return DebugMeta(
Expand All @@ -28,19 +34,21 @@ class DebugMeta {
?.map((debugImageJson) =>
DebugImage.fromJson(debugImageJson as Map<String, dynamic>))
.toList(),
unknown: json.notAccessed(),
);
}

/// Produces a [Map] that can be serialized to JSON.
Map<String, dynamic> toJson() {
final sdkInfo = sdk?.toJson();
return {
...?unknown,
if (sdkInfo?.isNotEmpty ?? false) 'sdk_info': sdkInfo,
if (_images?.isNotEmpty ?? false)
'images': _images!
.map((e) => e.toJson())
.where((element) => element.isNotEmpty)
.toList(growable: false)
.toList(growable: false),
};
}

Expand All @@ -51,5 +59,6 @@ class DebugMeta {
DebugMeta(
sdk: sdk ?? this.sdk,
images: images ?? _images,
unknown: unknown,
);
}
12 changes: 11 additions & 1 deletion dart/lib/src/protocol/mechanism.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:meta/meta.dart';

import 'access_aware_map.dart';

/// Sentry Exception Mechanism
/// The exception mechanism is an optional field residing
/// in the Exception Interface. It carries additional information about
Expand Down Expand Up @@ -76,6 +78,9 @@ class Mechanism {
/// (the last to be listed in the exception values).
final int? parentId;

@internal
final Map<String, dynamic>? unknown;

Mechanism({
required this.type,
this.description,
Expand All @@ -88,6 +93,7 @@ class Mechanism {
this.source,
this.exceptionId,
this.parentId,
this.unknown,
}) : _meta = meta != null ? Map.from(meta) : null,
_data = data != null ? Map.from(data) : null;

Expand Down Expand Up @@ -116,10 +122,12 @@ class Mechanism {
source: source ?? this.source,
exceptionId: exceptionId ?? this.exceptionId,
parentId: parentId ?? this.parentId,
unknown: unknown,
);

/// Deserializes a [Mechanism] from JSON [Map].
factory Mechanism.fromJson(Map<String, dynamic> json) {
factory Mechanism.fromJson(Map<String, dynamic> jsonData) {
final json = AccessAwareMap(jsonData);
var data = json['data'];
if (data != null) {
data = Map<String, dynamic>.from(data as Map);
Expand All @@ -142,12 +150,14 @@ class Mechanism {
source: json['source'],
exceptionId: json['exception_id'],
parentId: json['parent_id'],
unknown: json.notAccessed(),
);
}

/// Produces a [Map] that can be serialized to JSON.
Map<String, dynamic> toJson() {
return {
...?unknown,
'type': type,
if (description != null) 'description': description,
if (helpLink != null) 'help_link': helpLink,
Expand Down
32 changes: 22 additions & 10 deletions dart/lib/src/protocol/metric_summary.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import 'package:meta/meta.dart';

import '../metrics/metric.dart';
import 'access_aware_map.dart';

class MetricSummary {
final num min;
Expand All @@ -7,7 +10,10 @@ class MetricSummary {
final int count;
final Map<String, String>? tags;

MetricSummary.fromGauge(GaugeMetric gauge)
@internal
final Map<String, dynamic>? unknown;

MetricSummary.fromGauge(GaugeMetric gauge, {this.unknown})
: min = gauge.minimum,
max = gauge.maximum,
sum = gauge.sum,
Expand All @@ -19,20 +25,26 @@ class MetricSummary {
required this.max,
required this.sum,
required this.count,
required this.tags});
required this.tags,
this.unknown});

/// Deserializes a [MetricSummary] from JSON [Map].
factory MetricSummary.fromJson(Map<String, dynamic> data) => MetricSummary(
min: data['min'],
max: data['max'],
count: data['count'],
sum: data['sum'],
tags: data['tags']?.cast<String, String>(),
);
factory MetricSummary.fromJson(Map<String, dynamic> data) {
final json = AccessAwareMap(data);
return MetricSummary(
min: json['min'],
max: json['max'],
count: json['count'],
sum: json['sum'],
tags: json['tags']?.cast<String, String>(),
unknown: json.notAccessed(),
);
}

/// Produces a [Map] that can be serialized to JSON.
Map<String, dynamic> toJson() {
return <String, dynamic>{
return {
...?unknown,
'min': min,
'max': max,
'count': count,
Expand Down
12 changes: 11 additions & 1 deletion dart/lib/src/protocol/sdk_info.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:meta/meta.dart';

import 'access_aware_map.dart';

/// An object describing the system SDK.
@immutable
class SdkInfo {
Expand All @@ -8,26 +10,33 @@ class SdkInfo {
final int? versionMinor;
final int? versionPatchlevel;

@internal
final Map<String, dynamic>? unknown;

const SdkInfo({
this.sdkName,
this.versionMajor,
this.versionMinor,
this.versionPatchlevel,
this.unknown,
});

/// Deserializes a [SdkInfo] from JSON [Map].
factory SdkInfo.fromJson(Map<String, dynamic> json) {
factory SdkInfo.fromJson(Map<String, dynamic> data) {
final json = AccessAwareMap(data);
return SdkInfo(
sdkName: json['sdk_name'],
versionMajor: json['version_major'],
versionMinor: json['version_minor'],
versionPatchlevel: json['version_patchlevel'],
unknown: json.notAccessed(),
);
}

/// Produces a [Map] that can be serialized to JSON.
Map<String, dynamic> toJson() {
return {
...?unknown,
if (sdkName != null) 'sdk_name': sdkName,
if (versionMajor != null) 'version_major': versionMajor,
if (versionMinor != null) 'version_minor': versionMinor,
Expand All @@ -46,5 +55,6 @@ class SdkInfo {
versionMajor: versionMajor ?? this.versionMajor,
versionMinor: versionMinor ?? this.versionMinor,
versionPatchlevel: versionPatchlevel ?? this.versionPatchlevel,
unknown: unknown,
);
}
Loading