From 4025afc4b543cb6289ce73be34b0091a54047683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sat, 1 Oct 2022 20:52:00 +0200 Subject: [PATCH 01/24] update protocol --- dart/example_web/web/event.dart | 2 +- dart/example_web/web/main.dart | 2 +- .../http_client/failed_request_client.dart | 1 + dart/lib/src/protocol.dart | 1 + dart/lib/src/protocol/breadcrumb.dart | 25 +--- dart/lib/src/protocol/debug_image.dart | 74 ++++------ dart/lib/src/protocol/sentry_app.dart | 49 +++---- dart/lib/src/protocol/sentry_geo.dart | 29 ++++ dart/lib/src/protocol/sentry_gpu.dart | 116 ++++++++++----- dart/lib/src/protocol/sentry_request.dart | 70 +++++---- dart/lib/src/protocol/sentry_runtime.dart | 23 ++- dart/lib/src/protocol/sentry_stack_frame.dart | 133 +++++++----------- dart/lib/src/protocol/sentry_stack_trace.dart | 41 ++++-- dart/lib/src/protocol/sentry_user.dart | 93 +++++++++--- dart/lib/src/scope.dart | 2 +- .../failed_request_client_test.dart | 4 + dart/test/mocks.dart | 2 +- dart/test/protocol/sentry_request_test.dart | 1 + dart/test/protocol/sentry_user_test.dart | 16 +-- dart/test/scope_test.dart | 2 +- dart/test/sentry_client_test.dart | 10 +- dart/test/sentry_event_test.dart | 13 +- dart/test/test_utils.dart | 2 +- .../test/load_contexts_integrations_test.dart | 4 +- 24 files changed, 393 insertions(+), 322 deletions(-) create mode 100644 dart/lib/src/protocol/sentry_geo.dart diff --git a/dart/example_web/web/event.dart b/dart/example_web/web/event.dart index 1ba3ea04fd..81550d9385 100644 --- a/dart/example_web/web/event.dart +++ b/dart/example_web/web/event.dart @@ -14,7 +14,7 @@ final event = SentryEvent( username: 'first-user', email: 'first@user.lan', // ipAddress: '127.0.0.1', - extras: {'first-sign-in': '2020-01-01'}, + data: {'first-sign-in': '2020-01-01'}, ), breadcrumbs: [ Breadcrumb( diff --git a/dart/example_web/web/main.dart b/dart/example_web/web/main.dart index f405fc5a66..6e7d9ccb7e 100644 --- a/dart/example_web/web/main.dart +++ b/dart/example_web/web/main.dart @@ -52,7 +52,7 @@ Future runApp() async { username: 'first-user', email: 'first@user.lan', // ipAddress: '127.0.0.1', - extras: {'first-sign-in': '2020-01-01'}, + data: {'first-sign-in': '2020-01-01'}, ), ); }); diff --git a/dart/lib/src/http_client/failed_request_client.dart b/dart/lib/src/http_client/failed_request_client.dart index bbffa27728..f3e8e4bc5a 100644 --- a/dart/lib/src/http_client/failed_request_client.dart +++ b/dart/lib/src/http_client/failed_request_client.dart @@ -166,6 +166,7 @@ class FailedRequestClient extends BaseClient { queryString: query, cookies: sendDefaultPii ? request.headers['Cookie'] : null, data: _getDataFromRequest(request), + // ignore: deprecated_member_use_from_same_package other: { 'content_length': request.contentLength.toString(), 'duration': requestDuration.toString(), diff --git a/dart/lib/src/protocol.dart b/dart/lib/src/protocol.dart index f193e1968f..26a4fc2118 100644 --- a/dart/lib/src/protocol.dart +++ b/dart/lib/src/protocol.dart @@ -23,6 +23,7 @@ export 'protocol/sentry_runtime.dart'; export 'protocol/sentry_stack_frame.dart'; export 'protocol/sentry_stack_trace.dart'; export 'protocol/sentry_user.dart'; +export 'protocol/sentry_geo.dart'; export 'protocol/max_body_size.dart'; export 'protocol/sentry_culture.dart'; export 'protocol/sentry_thread.dart'; diff --git a/dart/lib/src/protocol/breadcrumb.dart b/dart/lib/src/protocol/breadcrumb.dart index 1a72340696..500e04f2ac 100644 --- a/dart/lib/src/protocol/breadcrumb.dart +++ b/dart/lib/src/protocol/breadcrumb.dart @@ -148,27 +148,14 @@ class Breadcrumb { /// Converts this breadcrumb to a map that can be serialized to JSON according /// to the Sentry protocol. Map toJson() { - final json = { + return { 'timestamp': formatDateAsIso8601WithMillisPrecision(timestamp), + if (message != null) 'message': message, + if (category != null) 'category': category, + if (data?.isNotEmpty ?? false) 'data': data, + if (level != null) 'level': level!.name, + if (type != null) 'type': type, }; - - if (message != null) { - json['message'] = message; - } - if (category != null) { - json['category'] = category; - } - if (data?.isNotEmpty ?? false) { - json['data'] = data; - } - if (level != null) { - json['level'] = level!.name; - } - - if (type != null) { - json['type'] = type; - } - return json; } Breadcrumb copyWith({ diff --git a/dart/lib/src/protocol/debug_image.dart b/dart/lib/src/protocol/debug_image.dart index 9d5a0a441f..df45a12fed 100644 --- a/dart/lib/src/protocol/debug_image.dart +++ b/dart/lib/src/protocol/debug_image.dart @@ -45,6 +45,12 @@ class DebugImage { /// Optional. Identifier of the dynamic library or executable. It is the value of the LC_UUID load command in the Mach header, formatted as UUID. Can be empty for Mach images, as it is equivalent to the debug identifier. final String? codeId; + /// MachO CPU subtype identifier. + final int? cpuSubtype; + + /// MachO CPU type identifier. + final int? cpuType; + const DebugImage({ required this.type, this.name, @@ -57,6 +63,8 @@ class DebugImage { this.codeFile, this.arch, this.codeId, + this.cpuType, + this.cpuSubtype, }); /// Deserializes a [DebugImage] from JSON [Map]. @@ -73,56 +81,28 @@ class DebugImage { codeFile: json['code_file'], arch: json['arch'], codeId: json['code_id'], + cpuType: json['cpu_type'], + cpuSubtype: json['cpu_subtype'], ); } /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - - if (uuid != null) { - json['uuid'] = uuid; - } - - json['type'] = type; - - if (debugId != null) { - json['debug_id'] = debugId; - } - - if (name != null) { - json['name'] = name; - } - - if (debugFile != null) { - json['debug_file'] = debugFile; - } - - if (codeFile != null) { - json['code_file'] = codeFile; - } - - if (imageAddr != null) { - json['image_addr'] = imageAddr; - } - - if (imageVmAddr != null) { - json['image_vmaddr'] = imageVmAddr; - } - - if (imageSize != null) { - json['image_size'] = imageSize; - } - - if (arch != null) { - json['arch'] = arch; - } - - if (codeId != null) { - json['code_id'] = codeId; - } - - return json; + return { + 'type': type, + if (uuid != null) 'uuid': uuid, + if (debugId != null) 'debug_id': debugId, + if (name != null) 'name': name, + if (debugFile != null) 'debug_file': debugFile, + if (codeFile != null) 'code_file': codeFile, + if (imageAddr != null) 'image_addr': imageAddr, + if (imageVmAddr != null) 'image_vmaddr': imageVmAddr, + if (imageSize != null) 'image_size': imageSize, + if (arch != null) 'arch': arch, + if (codeId != null) 'code_id': codeId, + if (cpuType != null) 'cpu_type': cpuType, + if (cpuSubtype != null) 'cpu_subtype': cpuSubtype, + }; } DebugImage copyWith({ @@ -137,6 +117,8 @@ class DebugImage { int? imageSize, String? arch, String? codeId, + int? cpuType, + int? cpuSubtype, }) => DebugImage( uuid: uuid ?? this.uuid, @@ -150,5 +132,7 @@ class DebugImage { imageSize: imageSize ?? this.imageSize, arch: arch ?? this.arch, codeId: codeId ?? this.codeId, + cpuType: cpuType ?? this.cpuType, + cpuSubtype: cpuSubtype ?? this.cpuSubtype, ); } diff --git a/dart/lib/src/protocol/sentry_app.dart b/dart/lib/src/protocol/sentry_app.dart index 90581e1fb4..960b7d0cb4 100644 --- a/dart/lib/src/protocol/sentry_app.dart +++ b/dart/lib/src/protocol/sentry_app.dart @@ -16,6 +16,7 @@ class SentryApp { this.buildType, this.startTime, this.deviceAppHash, + this.appMemory, }); /// Human readable application name, as it appears on the platform. @@ -39,6 +40,9 @@ class SentryApp { /// Application specific device identifier. final String? deviceAppHash; + /// Amount of memory used by the application in bytes. + final int? appMemory; + /// Deserializes a [SentryApp] from JSON [Map]. factory SentryApp.fromJson(Map data) => SentryApp( name: data['app_name'], @@ -50,41 +54,21 @@ class SentryApp { ? DateTime.tryParse(data['app_start_time']) : null, deviceAppHash: data['device_app_hash'], + appMemory: data['app_memory'], ); /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - - if (name != null) { - json['app_name'] = name!; - } - - if (version != null) { - json['app_version'] = version!; - } - - if (identifier != null) { - json['app_identifier'] = identifier!; - } - - if (build != null) { - json['app_build'] = build!; - } - - if (buildType != null) { - json['build_type'] = buildType!; - } - - if (startTime != null) { - json['app_start_time'] = startTime!.toIso8601String(); - } - - if (deviceAppHash != null) { - json['device_app_hash'] = deviceAppHash!; - } - - return json; + return { + if (name != null) 'app_name': name!, + if (version != null) 'app_version': version!, + if (identifier != null) 'app_identifier': identifier!, + if (build != null) 'app_build': build!, + if (buildType != null) 'build_type': buildType!, + if (deviceAppHash != null) 'device_app_hash': deviceAppHash!, + if (appMemory != null) 'app_memory': appMemory!, + if (startTime != null) 'app_start_time': startTime!.toIso8601String(), + }; } SentryApp clone() => SentryApp( @@ -95,6 +79,7 @@ class SentryApp { buildType: buildType, startTime: startTime, deviceAppHash: deviceAppHash, + appMemory: appMemory, ); SentryApp copyWith({ @@ -105,6 +90,7 @@ class SentryApp { String? buildType, DateTime? startTime, String? deviceAppHash, + int? appMemory, }) => SentryApp( name: name ?? this.name, @@ -114,5 +100,6 @@ class SentryApp { buildType: buildType ?? this.buildType, startTime: startTime ?? this.startTime, deviceAppHash: deviceAppHash ?? this.deviceAppHash, + appMemory: appMemory ?? this.appMemory, ); } diff --git a/dart/lib/src/protocol/sentry_geo.dart b/dart/lib/src/protocol/sentry_geo.dart new file mode 100644 index 0000000000..e8221c1537 --- /dev/null +++ b/dart/lib/src/protocol/sentry_geo.dart @@ -0,0 +1,29 @@ +/// Geographical location of the end user or device. +class SentryGeo { + SentryGeo({this.city, this.countryCode, this.region}); + + factory SentryGeo.fromJson(Map json) { + return SentryGeo( + city: json['city'], + countryCode: json['country_code'], + region: json['region'], + ); + } + + /// Human readable city name. + final String? city; + + /// Two-letter country code (ISO 3166-1 alpha-2). + final String? countryCode; + + /// Human readable region name or code. + final String? region; + + Map toJson() { + return { + if (city != null) 'city': city, + if (countryCode != null) 'country_code': countryCode, + if (region != null) 'region': region, + }; + } +} diff --git a/dart/lib/src/protocol/sentry_gpu.dart b/dart/lib/src/protocol/sentry_gpu.dart index 6696f7b4f7..64747eb868 100644 --- a/dart/lib/src/protocol/sentry_gpu.dart +++ b/dart/lib/src/protocol/sentry_gpu.dart @@ -44,6 +44,27 @@ class SentryGpu { /// The Non-Power-Of-Two-Support support. final String? npotSupport; + /// Approximate "shader capability" level of the graphics device. + /// For Example: + /// Shader Model 2.0, OpenGL ES 3.0, Metal / OpenGL ES 3.1, 27 (unknown) + final String? graphicsShaderLevel; + + /// Largest size of a texture that is supported by the graphics hardware. + /// For Example: 16384 + final int? maxTextureSize; + + /// Whether compute shaders are available on the device. + final bool? supportsComputeShaders; + + /// Whether GPU draw call instancing is supported. + final bool? supportsDrawCallInstancing; + + /// Whether geometry shaders are available on the device. + final bool? supportsGeometryShaders; + + /// Whether ray tracing is available on the device. + final bool? supportsRayTracing; + const SentryGpu({ this.name, this.id, @@ -54,6 +75,12 @@ class SentryGpu { this.multiThreadedRendering, this.version, this.npotSupport, + this.graphicsShaderLevel, + this.maxTextureSize, + this.supportsComputeShaders, + this.supportsDrawCallInstancing, + this.supportsGeometryShaders, + this.supportsRayTracing, }); /// Deserializes a [SentryGpu] from JSON [Map]. @@ -67,6 +94,12 @@ class SentryGpu { multiThreadedRendering: data['multi_threaded_rendering'], version: data['version'], npotSupport: data['npot_support'], + graphicsShaderLevel: data['graphics_shader_level'], + maxTextureSize: data['max_texture_size'], + supportsComputeShaders: data['supports_compute_shaders'], + supportsDrawCallInstancing: data['supports_draw_call_instancing'], + supportsGeometryShaders: data['supports_geometry_shaders'], + supportsRayTracing: data['supports_ray_tracing'], ); SentryGpu clone() => SentryGpu( @@ -79,49 +112,39 @@ class SentryGpu { multiThreadedRendering: multiThreadedRendering, version: version, npotSupport: npotSupport, + graphicsShaderLevel: graphicsShaderLevel, + maxTextureSize: maxTextureSize, + supportsComputeShaders: supportsComputeShaders, + supportsDrawCallInstancing: supportsDrawCallInstancing, + supportsGeometryShaders: supportsGeometryShaders, + supportsRayTracing: supportsRayTracing, ); /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - - if (name != null) { - json['name'] = name; - } - - if (id != null) { - json['id'] = id; - } - - if (vendorId != null) { - json['vendor_id'] = vendorId; - } - - if (vendorName != null) { - json['vendor_name'] = vendorName; - } - - if (memorySize != null) { - json['memory_size'] = memorySize; - } - - if (apiType != null) { - json['api_type'] = apiType; - } - - if (multiThreadedRendering != null) { - json['multi_threaded_rendering'] = multiThreadedRendering; - } - - if (version != null) { - json['version'] = version; - } - - if (npotSupport != null) { - json['npot_support'] = npotSupport; - } - - return json; + return { + if (name != null) 'name': name, + if (id != null) 'id': id, + if (vendorId != null) 'vendor_id': vendorId, + if (vendorName != null) 'vendor_name': vendorName, + if (memorySize != null) 'memory_size': memorySize, + if (apiType != null) 'api_type': apiType, + if (multiThreadedRendering != null) + 'multi_threaded_rendering': multiThreadedRendering, + if (version != null) 'version': version, + if (npotSupport != null) 'npot_support': npotSupport, + if (graphicsShaderLevel != null) + 'graphics_shader_level': graphicsShaderLevel, + if (maxTextureSize != null) 'max_texture_size': maxTextureSize, + if (supportsComputeShaders != null) + 'supports_compute_shaders': supportsComputeShaders, + if (supportsDrawCallInstancing != null) + 'supports_draw_call_instancing': supportsDrawCallInstancing, + if (supportsGeometryShaders != null) + 'supports_geometry_shaders': supportsGeometryShaders, + if (supportsRayTracing != null) + 'supports_ray_tracing': supportsRayTracing, + }; } SentryGpu copyWith({ @@ -134,6 +157,12 @@ class SentryGpu { bool? multiThreadedRendering, String? version, String? npotSupport, + String? graphicsShaderLevel, + int? maxTextureSize, + bool? supportsComputeShaders, + bool? supportsDrawCallInstancing, + bool? supportsGeometryShaders, + bool? supportsRayTracing, }) => SentryGpu( name: name ?? this.name, @@ -146,5 +175,14 @@ class SentryGpu { multiThreadedRendering ?? this.multiThreadedRendering, version: version ?? this.version, npotSupport: npotSupport ?? this.npotSupport, + graphicsShaderLevel: graphicsShaderLevel ?? this.graphicsShaderLevel, + maxTextureSize: maxTextureSize ?? this.maxTextureSize, + supportsComputeShaders: + supportsComputeShaders ?? this.supportsComputeShaders, + supportsDrawCallInstancing: + supportsDrawCallInstancing ?? this.supportsDrawCallInstancing, + supportsGeometryShaders: + supportsGeometryShaders ?? this.supportsGeometryShaders, + supportsRayTracing: supportsRayTracing ?? this.supportsRayTracing, ); } diff --git a/dart/lib/src/protocol/sentry_request.dart b/dart/lib/src/protocol/sentry_request.dart index 7c326df727..369c8d29cb 100644 --- a/dart/lib/src/protocol/sentry_request.dart +++ b/dart/lib/src/protocol/sentry_request.dart @@ -53,17 +53,26 @@ class SentryRequest { final Map? _other; + @Deprecated('Will be removed in v7') Map get other => Map.unmodifiable(_other ?? const {}); + /// The fragment of the request URL. + final String? fragment; + + /// The inferred content type of the request payload. + final String? inferredContentType; + SentryRequest({ this.url, this.method, this.queryString, this.cookies, + this.fragment, + this.inferredContentType, dynamic data, Map? headers, Map? env, - Map? other, + @Deprecated('Will be removed in v7.') Map? other, }) : _data = data, _headers = headers != null ? Map.from(headers) : null, _env = env != null ? Map.from(env) : null, @@ -79,47 +88,29 @@ class SentryRequest { data: json['data'], headers: json['headers'], env: json['env'], + // ignore: deprecated_member_use_from_same_package other: json['other'], + fragment: json['fragment'], + inferredContentType: json['inferred_content_type'], ); } /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - - if (url != null) { - json['url'] = url; - } - - if (method != null) { - json['method'] = method; - } - - if (queryString != null) { - json['query_string'] = queryString; - } - - if (_data != null) { - json['data'] = _data; - } - - if (cookies != null) { - json['cookies'] = cookies; - } - - if (headers.isNotEmpty) { - json['headers'] = headers; - } - - if (env.isNotEmpty) { - json['env'] = env; - } - - if (other.isNotEmpty) { - json['other'] = other; - } - - return json; + return { + if (url != null) 'url': url, + if (method != null) 'method': method, + if (queryString != null) 'query_string': queryString, + if (_data != null) 'data': _data, + if (cookies != null) 'cookies': cookies, + if (headers.isNotEmpty) 'headers': headers, + if (env.isNotEmpty) 'env': env, + // ignore: deprecated_member_use_from_same_package + if (other.isNotEmpty) 'other': other, + if (fragment != null) 'fragment': fragment, + if (inferredContentType != null) + 'inferred_content_type': inferredContentType, + }; } SentryRequest copyWith({ @@ -127,10 +118,12 @@ class SentryRequest { String? method, String? queryString, String? cookies, + String? fragment, + String? inferredContentType, dynamic data, Map? headers, Map? env, - Map? other, + @Deprecated('Will be removed in v7.') Map? other, }) => SentryRequest( url: url ?? this.url, @@ -140,6 +133,9 @@ class SentryRequest { data: data ?? _data, headers: headers ?? _headers, env: env ?? _env, + // ignore: deprecated_member_use_from_same_package other: other ?? _other, + fragment: fragment, + inferredContentType: inferredContentType, ); } diff --git a/dart/lib/src/protocol/sentry_runtime.dart b/dart/lib/src/protocol/sentry_runtime.dart index 245845d078..4779d9b098 100644 --- a/dart/lib/src/protocol/sentry_runtime.dart +++ b/dart/lib/src/protocol/sentry_runtime.dart @@ -10,13 +10,14 @@ class SentryRuntime { static const listType = 'runtimes'; static const type = 'runtime'; - const SentryRuntime({ - this.key, - this.name, - this.version, - this.compiler, - this.rawDescription, - }) : assert(key == null || key.length >= 1); + const SentryRuntime( + {this.key, + this.name, + this.version, + this.compiler, + this.rawDescription, + this.build}) + : assert(key == null || key.length >= 1); /// Key used in the JSON and which will be displayed /// in the Sentry UI. Defaults to lower case version of [name]. @@ -40,12 +41,16 @@ class SentryRuntime { /// and version from this string, if they are not explicitly given. final String? rawDescription; + /// Application build string, if it is separate from the version. + final String? build; + /// Deserializes a [SentryRuntime] from JSON [Map]. factory SentryRuntime.fromJson(Map data) => SentryRuntime( name: data['name'], version: data['version'], compiler: data['compiler'], rawDescription: data['raw_description'], + build: data['build'], ); /// Produces a [Map] that can be serialized to JSON. @@ -55,6 +60,7 @@ class SentryRuntime { if (compiler != null) 'compiler': compiler, if (version != null) 'version': version, if (rawDescription != null) 'raw_description': rawDescription, + if (build != null) 'build': build, }; } @@ -64,6 +70,7 @@ class SentryRuntime { version: version, compiler: compiler, rawDescription: rawDescription, + build: build, ); SentryRuntime copyWith({ @@ -72,6 +79,7 @@ class SentryRuntime { String? version, String? compiler, String? rawDescription, + String? build, }) => SentryRuntime( key: key ?? this.key, @@ -79,5 +87,6 @@ class SentryRuntime { version: version ?? this.version, compiler: compiler ?? this.compiler, rawDescription: rawDescription ?? this.rawDescription, + build: build ?? this.build, ); } diff --git a/dart/lib/src/protocol/sentry_stack_frame.dart b/dart/lib/src/protocol/sentry_stack_frame.dart index 27085f8522..a2bfb47c45 100644 --- a/dart/lib/src/protocol/sentry_stack_frame.dart +++ b/dart/lib/src/protocol/sentry_stack_frame.dart @@ -23,10 +23,12 @@ class SentryStackFrame { this.symbolAddr, this.instructionAddr, this.rawFunction, + this.stackStart, + this.symbol, List? framesOmitted, List? preContext, List? postContext, - Map? vars, + Map? vars, }) : _framesOmitted = framesOmitted != null ? List.from(framesOmitted) : null, _preContext = preContext != null ? List.from(preContext) : null, @@ -46,10 +48,10 @@ class SentryStackFrame { /// An immutable list of source code lines after context_line (in order) – usually [lineno + 1:lineno + 5]. List get postContext => List.unmodifiable(_postContext ?? const []); - final Map? _vars; + final Map? _vars; /// An immutable mapping of variables which were available within this frame (usually context-locals). - Map get vars => Map.unmodifiable(_vars ?? const {}); + Map get vars => Map.unmodifiable(_vars ?? const {}); final List? _framesOmitted; @@ -108,6 +110,23 @@ class SentryStackFrame { /// The original function name, if the function name is shortened or demangled. Sentry shows the raw function when clicking on the shortened one in the UI. final String? rawFunction; + /// Marks this frame as the bottom of a chained stack trace. + /// + /// Stack traces from asynchronous code consist of several sub traces that + /// are chained together into one large list. This flag indicates the root + /// function of a chained stack trace. Depending on the runtime and thread, + /// this is either the main function or a thread base stub. + /// + /// This field should only be specified when true. + final bool? stackStart; + + /// Potentially mangled name of the symbol as it appears in an executable. + /// + /// This is different from a function name by generally being the mangled name + /// that appears natively in the binary. + /// This is relevant for languages like Swift, C++ or Rust. + final String? symbol; + /// Deserializes a [SentryStackFrame] from JSON [Map]. factory SentryStackFrame.fromJson(Map json) { return SentryStackFrame( @@ -130,90 +149,36 @@ class SentryStackFrame { preContext: json['pre_context'], postContext: json['post_context'], vars: json['vars'], + symbol: json['symbol'], + stackStart: json['stack_start'], ); } /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - - if (_preContext?.isNotEmpty ?? false) { - json['pre_context'] = _preContext; - } - - if (_postContext?.isNotEmpty ?? false) { - json['post_context'] = _postContext; - } - - if (_vars?.isNotEmpty ?? false) { - json['vars'] = _vars; - } - - if (_framesOmitted?.isNotEmpty ?? false) { - json['frames_omitted'] = _framesOmitted; - } - - if (fileName != null) { - json['filename'] = fileName; - } - - if (package != null) { - json['package'] = package; - } - - if (function != null) { - json['function'] = function; - } - - if (module != null) { - json['module'] = module; - } - - if (lineNo != null) { - json['lineno'] = lineNo; - } - - if (colNo != null) { - json['colno'] = colNo; - } - - if (absPath != null) { - json['abs_path'] = absPath; - } - - if (contextLine != null) { - json['context_line'] = contextLine; - } - - if (inApp != null) { - json['in_app'] = inApp; - } - - if (native != null) { - json['native'] = native; - } - - if (platform != null) { - json['platform'] = platform; - } - - if (imageAddr != null) { - json['image_addr'] = imageAddr; - } - - if (symbolAddr != null) { - json['symbol_addr'] = symbolAddr; - } - - if (instructionAddr != null) { - json['instruction_addr'] = instructionAddr; - } - - if (rawFunction != null) { - json['raw_function'] = rawFunction; - } - - return json; + return { + if (_preContext?.isNotEmpty ?? false) 'pre_context': _preContext, + if (_postContext?.isNotEmpty ?? false) 'post_context': _postContext, + if (_vars?.isNotEmpty ?? false) 'vars': _vars, + if (_framesOmitted?.isNotEmpty ?? false) 'frames_omitted': _framesOmitted, + if (fileName != null) 'filename': fileName, + if (package != null) 'package': package, + if (function != null) 'function': function, + if (module != null) 'module': module, + if (lineNo != null) 'lineno': lineNo, + if (colNo != null) 'colno': colNo, + if (absPath != null) 'abs_path': absPath, + if (contextLine != null) 'context_line': contextLine, + if (inApp != null) 'in_app': inApp, + if (native != null) 'native': native, + if (platform != null) 'platform': platform, + if (imageAddr != null) 'image_addr': imageAddr, + if (symbolAddr != null) 'symbol_addr': symbolAddr, + if (instructionAddr != null) 'instruction_addr': instructionAddr, + if (rawFunction != null) 'raw_function': rawFunction, + if (symbol != null) 'symbol': symbol, + if (stackStart != null) 'stack_start': stackStart, + }; } SentryStackFrame copyWith({ @@ -236,6 +201,8 @@ class SentryStackFrame { List? preContext, List? postContext, Map? vars, + bool? stackStart, + String? symbol, }) => SentryStackFrame( absPath: absPath ?? this.absPath, @@ -257,5 +224,7 @@ class SentryStackFrame { preContext: preContext ?? _preContext, postContext: postContext ?? _postContext, vars: vars ?? _vars, + symbol: symbol ?? symbol, + stackStart: stackStart ?? stackStart, ); } diff --git a/dart/lib/src/protocol/sentry_stack_trace.dart b/dart/lib/src/protocol/sentry_stack_trace.dart index abb74fdcca..c8a6076726 100644 --- a/dart/lib/src/protocol/sentry_stack_trace.dart +++ b/dart/lib/src/protocol/sentry_stack_trace.dart @@ -8,6 +8,8 @@ class SentryStackTrace { SentryStackTrace({ required List frames, Map? registers, + this.lang, + this.snapshot, }) : _frames = frames, _registers = Map.from(registers ?? {}); @@ -25,6 +27,23 @@ class SentryStackTrace { /// thus mapping to the last frame in the list. Map get registers => Map.unmodifiable(_registers ?? const {}); + /// The language of the stacktrace + final String? lang; + + /// Indicates that this stack trace is a snapshot triggered + /// by an external signal. + /// + /// If this field is false, then the stack trace points to the code that + /// caused this stack trace to be created. + /// This can be the location of a raised exception, as well as an exception or + /// signal handler. + /// + /// If this field is true, then the stack trace was captured as part + /// of creating an unrelated event. For example, a thread other than the + /// crashing thread, or a stack trace computed as a result of an external kill + /// signal. + final bool? snapshot; + /// Deserializes a [SentryStackTrace] from JSON [Map]. factory SentryStackTrace.fromJson(Map json) { final framesJson = json['frames'] as List?; @@ -35,23 +54,21 @@ class SentryStackTrace { .toList() : [], registers: json['registers'], + lang: json['lang'], + snapshot: json['snapshot'], ); } /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - - if (_frames?.isNotEmpty ?? false) { - json['frames'] = - _frames?.map((frame) => frame.toJson()).toList(growable: false); - } - - if (_registers?.isNotEmpty ?? false) { - json['registers'] = _registers; - } - - return json; + return { + if (_frames?.isNotEmpty ?? false) + 'frames': + _frames?.map((frame) => frame.toJson()).toList(growable: false), + if (_registers?.isNotEmpty ?? false) 'registers': _registers, + if (lang != null) 'lang': lang, + if (snapshot != null) 'snapshot': snapshot, + }; } SentryStackTrace copyWith({ diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index 960ed8733c..43c17bdc7d 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -1,5 +1,7 @@ import 'package:meta/meta.dart'; +import '../../sentry.dart'; + /// Describes the current user associated with the application, such as the /// currently signed in user. /// @@ -37,13 +39,21 @@ class SentryUser { this.email, this.ipAddress, this.segment, - Map? extras, - }) : assert(id != null || - username != null || - email != null || - ipAddress != null || - segment != null), - extras = extras == null ? null : Map.from(extras); + this.subscription, + this.geo, + this.name, + Map? data, + @Deprecated('Will be removed in v7. Use data instead') + Map? extras, + }) : assert( + id != null || + username != null || + email != null || + ipAddress != null || + segment != null, + ), + assert(data == null || extras == null, 'Only use one of data/extra'), + data = (data ?? extras) == null ? null : Map.from(data ?? extras ?? {}); /// A unique identifier of the user. final String? id; @@ -64,13 +74,35 @@ class SentryUser { /// /// These keys are stored as extra information but not specifically processed /// by Sentry. - final Map? extras; + final Map? data; + + @Deprecated('Will be removed in v7. Use [data] instead') + Map? get extras => data; + + final String? subscription; + + /// Approximate geographical location of the end user or device. + final SentryGeo? geo; + + /// Human readable name of the user. + final String? name; /// Deserializes a [SentryUser] from JSON [Map]. factory SentryUser.fromJson(Map json) { - var extras = json['extras']; + var extras = json['extras'] as Map?; if (extras != null) { - extras = Map.from(extras as Map); + extras = Map.from(extras); + } + + var data = json['data'] as Map?; + if (data != null) { + data = Map.from(data); + } + + SentryGeo? geo; + final geoJson = json['geo'] as Map?; + if (geoJson != null) { + geo = SentryGeo.fromJson(geoJson); } return SentryUser( id: json['id'], @@ -78,19 +110,28 @@ class SentryUser { email: json['email'], ipAddress: json['ip_address'], segment: json['segment'], + data: data, + geo: geo, + name: json['name'], + subscription: json['subscription'], + // ignore: deprecated_member_use_from_same_package extras: extras, ); } /// Produces a [Map] that can be serialized to JSON. Map toJson() { + final geoJson = geo?.toJson(); return { if (id != null) 'id': id, if (username != null) 'username': username, if (email != null) 'email': email, if (ipAddress != null) 'ip_address': ipAddress, if (segment != null) 'segment': segment, - if (extras?.isNotEmpty ?? false) 'extras': extras, + if (data?.isNotEmpty ?? false) 'data': data, + if (subscription != null) 'subscription': subscription, + if (name != null) 'name': name, + if (geoJson != null && geoJson.isNotEmpty) 'geo': geoJson, }; } @@ -100,14 +141,24 @@ class SentryUser { String? email, String? ipAddress, String? segment, - Map? extras, - }) => - SentryUser( - id: id ?? this.id, - username: username ?? this.username, - email: email ?? this.email, - ipAddress: ipAddress ?? this.ipAddress, - segment: segment ?? this.segment, - extras: extras ?? this.extras, - ); + @Deprecated('Will be removed in v7. Use [data] instead') + Map? extras, + String? name, + String? subscription, + SentryGeo? geo, + Map? data, + }) { + assert(data == null || extras == null, 'Only use one of data/extra'); + return SentryUser( + id: id ?? this.id, + username: username ?? this.username, + email: email ?? this.email, + ipAddress: ipAddress ?? this.ipAddress, + segment: segment ?? this.segment, + // ignore: deprecated_member_use_from_same_package + data: (data ?? extras) ?? (this.data ?? this.extras), + geo: geo ?? this.geo, + name: name ?? this.name, + ); + } } diff --git a/dart/lib/src/scope.dart b/dart/lib/src/scope.dart index 5e63a0a8ec..5e25493e87 100644 --- a/dart/lib/src/scope.dart +++ b/dart/lib/src/scope.dart @@ -389,7 +389,7 @@ class Scope { email: eventUser?.email, ipAddress: eventUser?.ipAddress, username: eventUser?.username, - extras: _mergeUserExtra(eventUser?.extras, scopeUser.extras), + data: _mergeUserExtra(eventUser?.data, scopeUser.data), ); } diff --git a/dart/test/http_client/failed_request_client_test.dart b/dart/test/http_client/failed_request_client_test.dart index 342a7f00f1..715ffc12d7 100644 --- a/dart/test/http_client/failed_request_client_test.dart +++ b/dart/test/http_client/failed_request_client_test.dart @@ -57,7 +57,9 @@ void main() { expect(request?.queryString, 'foo=bar'); expect(request?.cookies, 'foo=bar'); expect(request?.headers, {'Cookie': 'foo=bar'}); + // ignore: deprecated_member_use_from_same_package expect(request?.other.keys.contains('duration'), true); + // ignore: deprecated_member_use_from_same_package expect(request?.other.keys.contains('content_length'), true); }); @@ -108,7 +110,9 @@ void main() { expect(request?.queryString, 'foo=bar'); expect(request?.cookies, 'foo=bar'); expect(request?.headers, {'Cookie': 'foo=bar'}); + // ignore: deprecated_member_use_from_same_package expect(request?.other.keys.contains('duration'), true); + // ignore: deprecated_member_use_from_same_package expect(request?.other.keys.contains('content_length'), true); }); diff --git a/dart/test/mocks.dart b/dart/test/mocks.dart index cb36172d06..d046f001a6 100644 --- a/dart/test/mocks.dart +++ b/dart/test/mocks.dart @@ -33,7 +33,7 @@ final fakeEvent = SentryEvent( username: 'first-user', email: 'first@user.lan', ipAddress: '127.0.0.1', - extras: {'first-sign-in': '2020-01-01'}, + data: {'first-sign-in': '2020-01-01'}, ), breadcrumbs: [ Breadcrumb( diff --git a/dart/test/protocol/sentry_request_test.dart b/dart/test/protocol/sentry_request_test.dart index ae78f75fdb..394da9119d 100644 --- a/dart/test/protocol/sentry_request_test.dart +++ b/dart/test/protocol/sentry_request_test.dart @@ -11,6 +11,7 @@ void main() { data: {'key': 'value'}, headers: {'header_key': 'header_value'}, env: {'env_key': 'env_value'}, + // ignore: deprecated_member_use_from_same_package other: {'other_key': 'other_value'}, ); diff --git a/dart/test/protocol/sentry_user_test.dart b/dart/test/protocol/sentry_user_test.dart index 82a22ec7a0..2a958624e2 100644 --- a/dart/test/protocol/sentry_user_test.dart +++ b/dart/test/protocol/sentry_user_test.dart @@ -8,7 +8,7 @@ void main() { username: 'username', email: 'email', ipAddress: 'ipAddress', - extras: {'key': 'value'}, + data: {'key': 'value'}, segment: 'seg', ); @@ -17,7 +17,7 @@ void main() { 'username': 'username', 'email': 'email', 'ip_address': 'ipAddress', - 'extras': {'key': 'value'}, + 'data': {'key': 'value'}, 'segment': 'seg', }; @@ -41,9 +41,7 @@ void main() { }); test('toJson only serialises non-null values', () { - var data = SentryUser( - id: 'id', - ); + var data = SentryUser(id: 'id'); var json = data.toJson(); @@ -54,9 +52,7 @@ void main() { expect(json.containsKey('extras'), false); expect(json.containsKey('segment'), false); - data = SentryUser( - ipAddress: 'ip', - ); + data = SentryUser(ipAddress: 'ip'); json = data.toJson(); @@ -86,7 +82,7 @@ void main() { username: 'username1', email: 'email1', ipAddress: 'ipAddress1', - extras: {'key1': 'value1'}, + data: {'key1': 'value1'}, segment: 'seg1', ); @@ -94,7 +90,7 @@ void main() { expect('username1', copy.username); expect('email1', copy.email); expect('ipAddress1', copy.ipAddress); - expect({'key1': 'value1'}, copy.extras); + expect({'key1': 'value1'}, copy.data); expect('seg1', copy.segment); }); }); diff --git a/dart/test/scope_test.dart b/dart/test/scope_test.dart index de3d2f7d55..12f8b6a04c 100644 --- a/dart/test/scope_test.dart +++ b/dart/test/scope_test.dart @@ -366,7 +366,7 @@ void main() { username: 'first-user', email: 'first@user.lan', ipAddress: '127.0.0.1', - extras: const {'first-sign-in': '2020-01-01'}, + data: const {'first-sign-in': '2020-01-01'}, ); final breadcrumb = Breadcrumb(message: 'Authenticated'); diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 5161fcb53b..b2ce44b493 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -613,7 +613,7 @@ void main() { await scope.setUser( SentryUser( id: 'id', - extras: { + data: { 'foo': 'bar', 'bar': 'foo', }, @@ -623,7 +623,7 @@ void main() { var eventWithUser = event.copyWith( user: SentryUser( id: 'id', - extras: { + data: { 'foo': 'this bar is more important', 'event': 'Really important event' }, @@ -634,9 +634,9 @@ void main() { final capturedEnvelope = fixture.transport.envelopes.first; final capturedEvent = await eventFromEnvelope(capturedEnvelope); - expect(capturedEvent.user?.extras?['foo'], 'this bar is more important'); - expect(capturedEvent.user?.extras?['bar'], 'foo'); - expect(capturedEvent.user?.extras?['event'], 'Really important event'); + expect(capturedEvent.user?.data?['foo'], 'this bar is more important'); + expect(capturedEvent.user?.data?['bar'], 'foo'); + expect(capturedEvent.user?.data?['event'], 'Really important event'); }); }); diff --git a/dart/test/sentry_event_test.dart b/dart/test/sentry_event_test.dart index 104f68b547..2fb1a7d451 100644 --- a/dart/test/sentry_event_test.dart +++ b/dart/test/sentry_event_test.dart @@ -160,11 +160,12 @@ void main() { final timestamp = DateTime.utc(2019); final user = SentryUser( - id: 'user_id', - username: 'username', - email: 'email@email.com', - ipAddress: '127.0.0.1', - extras: const {'foo': 'bar'}); + id: 'user_id', + username: 'username', + email: 'email@email.com', + ipAddress: '127.0.0.1', + data: const {'foo': 'bar'}, + ); final breadcrumbs = [ Breadcrumb( @@ -248,7 +249,7 @@ void main() { 'username': 'username', 'email': 'email@email.com', 'ip_address': '127.0.0.1', - 'extras': {'foo': 'bar'} + 'data': {'foo': 'bar'} }, 'breadcrumbs': { { diff --git a/dart/test/test_utils.dart b/dart/test/test_utils.dart index c364e323d8..f9c8d354d6 100644 --- a/dart/test/test_utils.dart +++ b/dart/test/test_utils.dart @@ -379,7 +379,7 @@ void runTest({Codec, List?>? gzip, bool isWeb = false}) { username: 'username', email: 'email@email.com', ipAddress: '127.0.0.1', - extras: {'foo': 'bar'}, + data: {'foo': 'bar'}, ); final options = SentryOptions( diff --git a/flutter/test/load_contexts_integrations_test.dart b/flutter/test/load_contexts_integrations_test.dart index 2c6b9fd008..d27c222cb8 100644 --- a/flutter/test/load_contexts_integrations_test.dart +++ b/flutter/test/load_contexts_integrations_test.dart @@ -321,7 +321,7 @@ void main() { expect(event?.user?.username, 'fixture-username'); expect(event?.user?.email, 'fixture-email'); expect(event?.user?.ipAddress, 'fixture-ip_address'); - expect(event?.user?.extras?['key'], 'value'); + expect(event?.user?.data?['key'], 'value'); }); test('should not override user with native', () async { @@ -448,7 +448,7 @@ class Fixture { 'username': 'fixture-username', 'email': 'fixture-email', 'ip_address': 'fixture-ip_address', - 'extras': {'key': 'value'}, + 'data': {'key': 'value'}, }, 'tags': {'key-a': 'native', 'key-b': 'native'}, 'extra': {'key-a': 'native', 'key-b': 'native'}, From 1cd84a85c2e5b93b58b2e2078a1227fda1e4a5c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sun, 2 Oct 2022 11:37:38 +0200 Subject: [PATCH 02/24] formatting --- dart/lib/src/protocol/sentry_runtime.dart | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dart/lib/src/protocol/sentry_runtime.dart b/dart/lib/src/protocol/sentry_runtime.dart index 4779d9b098..960f48c170 100644 --- a/dart/lib/src/protocol/sentry_runtime.dart +++ b/dart/lib/src/protocol/sentry_runtime.dart @@ -10,14 +10,14 @@ class SentryRuntime { static const listType = 'runtimes'; static const type = 'runtime'; - const SentryRuntime( - {this.key, - this.name, - this.version, - this.compiler, - this.rawDescription, - this.build}) - : assert(key == null || key.length >= 1); + const SentryRuntime({ + this.key, + this.name, + this.version, + this.compiler, + this.rawDescription, + this.build, + }) : assert(key == null || key.length >= 1); /// Key used in the JSON and which will be displayed /// in the Sentry UI. Defaults to lower case version of [name]. From c4a77e521c0c2c41ff0be4efac2db1eaf387520b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sun, 2 Oct 2022 11:39:41 +0200 Subject: [PATCH 03/24] add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62b0a89dba..0fd636a41e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixes - Tracer does not allow setting measurement if finished ([#1026](https://github.com/getsentry/sentry-dart/pull/1026)) +- Bring protocol up to date with latest Sentry protocol ([#1038](https://github.com/getsentry/sentry-dart/pull/1038)) ### Features From 5354e1367e814a41118785c1eb36a666aa190a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sun, 2 Oct 2022 12:50:45 +0200 Subject: [PATCH 04/24] fix tests --- dart/lib/src/protocol/sentry_user.dart | 8 ++++---- dio/test/mocks.dart | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index 43c17bdc7d..747b0f46af 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -89,20 +89,20 @@ class SentryUser { /// Deserializes a [SentryUser] from JSON [Map]. factory SentryUser.fromJson(Map json) { - var extras = json['extras'] as Map?; + var extras = json['extras']; if (extras != null) { extras = Map.from(extras); } - var data = json['data'] as Map?; + var data = json['data']; if (data != null) { data = Map.from(data); } SentryGeo? geo; - final geoJson = json['geo'] as Map?; + final geoJson = json['geo']; if (geoJson != null) { - geo = SentryGeo.fromJson(geoJson); + geo = SentryGeo.fromJson(Map.from(geoJson)); } return SentryUser( id: json['id'], diff --git a/dio/test/mocks.dart b/dio/test/mocks.dart index b17a27e8b6..c1fec9182b 100644 --- a/dio/test/mocks.dart +++ b/dio/test/mocks.dart @@ -33,7 +33,7 @@ final fakeEvent = SentryEvent( username: 'first-user', email: 'first@user.lan', ipAddress: '127.0.0.1', - extras: {'first-sign-in': '2020-01-01'}, + data: {'first-sign-in': '2020-01-01'}, ), breadcrumbs: [ Breadcrumb( From 05280c191b331afbfe561c03088f05add711c341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sun, 2 Oct 2022 13:06:15 +0200 Subject: [PATCH 05/24] clean up toJson methods --- dart/lib/src/protocol/debug_meta.dart | 22 +++++-------- dart/lib/src/protocol/mechanism.dart | 36 ++++++--------------- dart/lib/src/protocol/sdk_info.dart | 24 ++++---------- dart/lib/src/protocol/sdk_version.dart | 22 ++++--------- dart/lib/src/protocol/sentry_browser.dart | 15 +++------ dart/lib/src/protocol/sentry_exception.dart | 35 +++++--------------- dart/lib/src/protocol/sentry_message.dart | 18 +++-------- 7 files changed, 47 insertions(+), 125 deletions(-) diff --git a/dart/lib/src/protocol/debug_meta.dart b/dart/lib/src/protocol/debug_meta.dart index 24d8183d54..205b2cc13e 100644 --- a/dart/lib/src/protocol/debug_meta.dart +++ b/dart/lib/src/protocol/debug_meta.dart @@ -33,21 +33,15 @@ class DebugMeta { /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - final sdkInfo = sdk?.toJson(); - if (sdkInfo?.isNotEmpty ?? false) { - json['sdk_info'] = sdkInfo; - } - - if (_images?.isNotEmpty ?? false) { - json['images'] = _images! - .map((e) => e.toJson()) - .where((element) => element.isNotEmpty) - .toList(growable: false); - } - - return json; + return { + if (sdkInfo?.isNotEmpty ?? false) 'sdk_info': sdkInfo, + if (_images?.isNotEmpty ?? false) + 'images': _images! + .map((e) => e.toJson()) + .where((element) => element.isNotEmpty) + .toList(growable: false) + }; } DebugMeta copyWith({ diff --git a/dart/lib/src/protocol/mechanism.dart b/dart/lib/src/protocol/mechanism.dart index 2e5d08e1ad..5a8be56de1 100644 --- a/dart/lib/src/protocol/mechanism.dart +++ b/dart/lib/src/protocol/mechanism.dart @@ -99,33 +99,15 @@ class Mechanism { /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - - json['type'] = type; - - if (description != null) { - json['description'] = description; - } - - if (helpLink != null) { - json['help_link'] = helpLink; - } - - if (handled != null) { - json['handled'] = handled; - } - - if (_meta?.isNotEmpty ?? false) { - json['meta'] = _meta; - } - - if (_data?.isNotEmpty ?? false) { - json['data'] = _data; - } - - if (synthetic != null) { - json['synthetic'] = synthetic; - } + return { + 'type': type, + if (description != null) 'description': description, + if (helpLink != null) 'help_link': helpLink, + if (handled != null) 'handled': handled, + if (_meta?.isNotEmpty ?? false) 'meta': _meta, + if (_data?.isNotEmpty ?? false) 'data': _data, + if (synthetic != null) 'synthetic': synthetic, + }; return json; } diff --git a/dart/lib/src/protocol/sdk_info.dart b/dart/lib/src/protocol/sdk_info.dart index a3434afd83..cf0b7d0f41 100644 --- a/dart/lib/src/protocol/sdk_info.dart +++ b/dart/lib/src/protocol/sdk_info.dart @@ -27,24 +27,12 @@ class SdkInfo { /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - if (sdkName != null) { - json['sdk_name'] = sdkName; - } - - if (versionMajor != null) { - json['version_major'] = versionMajor; - } - - if (versionMinor != null) { - json['version_minor'] = versionMinor; - } - - if (versionPatchlevel != null) { - json['version_patchlevel'] = versionPatchlevel; - } - - return json; + return { + if (sdkName != null) 'sdk_name': sdkName, + if (versionMajor != null) 'version_major': versionMajor, + if (versionMinor != null) 'version_minor': versionMinor, + if (versionPatchlevel != null) 'version_patchlevel': versionPatchlevel, + }; } SdkInfo copyWith({ diff --git a/dart/lib/src/protocol/sdk_version.dart b/dart/lib/src/protocol/sdk_version.dart index b69ca3c130..37c68fe700 100644 --- a/dart/lib/src/protocol/sdk_version.dart +++ b/dart/lib/src/protocol/sdk_version.dart @@ -79,21 +79,13 @@ class SdkVersion { /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - - json['name'] = name; - - json['version'] = version; - - if (packages.isNotEmpty) { - json['packages'] = - packages.map((p) => p.toJson()).toList(growable: false); - } - - if (integrations.isNotEmpty) { - json['integrations'] = integrations; - } - return json; + return { + 'name': name, + 'version': version, + if (packages.isNotEmpty) + 'packages': packages.map((p) => p.toJson()).toList(growable: false), + if (integrations.isNotEmpty) 'integrations': integrations, + }; } /// Adds a package diff --git a/dart/lib/src/protocol/sentry_browser.dart b/dart/lib/src/protocol/sentry_browser.dart index 5c536d5819..f2807e1092 100644 --- a/dart/lib/src/protocol/sentry_browser.dart +++ b/dart/lib/src/protocol/sentry_browser.dart @@ -25,17 +25,10 @@ class SentryBrowser { /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - - if (name != null) { - json['name'] = name; - } - - if (version != null) { - json['version'] = version; - } - - return json; + return { + if (name != null) 'name': name, + if (version != null) 'version': version, + }; } SentryBrowser clone() => SentryBrowser(name: name, version: version); diff --git a/dart/lib/src/protocol/sentry_exception.dart b/dart/lib/src/protocol/sentry_exception.dart index 767c38198d..3b3bab7924 100644 --- a/dart/lib/src/protocol/sentry_exception.dart +++ b/dart/lib/src/protocol/sentry_exception.dart @@ -51,33 +51,14 @@ class SentryException { /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - - if (type != null) { - json['type'] = type; - } - - if (value != null) { - json['value'] = value; - } - - if (module != null) { - json['module'] = module; - } - - if (stackTrace != null) { - json['stacktrace'] = stackTrace!.toJson(); - } - - if (mechanism != null) { - json['mechanism'] = mechanism!.toJson(); - } - - if (threadId != null) { - json['thread_id'] = threadId; - } - - return json; + return { + if (type != null) 'type': type, + if (value != null) 'value': value, + if (module != null) 'module': module, + if (stackTrace != null) 'stacktrace': stackTrace!.toJson(), + if (mechanism != null) 'mechanism': mechanism!.toJson(), + if (threadId != null) 'thread_id': threadId, + }; } SentryException copyWith({ diff --git a/dart/lib/src/protocol/sentry_message.dart b/dart/lib/src/protocol/sentry_message.dart index e234de5584..9d86c279cc 100644 --- a/dart/lib/src/protocol/sentry_message.dart +++ b/dart/lib/src/protocol/sentry_message.dart @@ -33,19 +33,11 @@ class SentryMessage { /// Produces a [Map] that can be serialized to JSON. Map toJson() { - final json = {}; - - json['formatted'] = formatted; - - if (template != null) { - json['message'] = template; - } - - if (params?.isNotEmpty ?? false) { - json['params'] = params; - } - - return json; + return { + 'formatted': formatted, + if (template != null) 'message': template, + if (params?.isNotEmpty ?? false) 'params': params, + }; } SentryMessage copyWith({ From cd2119bcba6e2e1c7b532dc2fbccfec2b9159c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sun, 2 Oct 2022 13:27:02 +0200 Subject: [PATCH 06/24] fix mistake --- dart/lib/src/protocol/mechanism.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/dart/lib/src/protocol/mechanism.dart b/dart/lib/src/protocol/mechanism.dart index 5a8be56de1..2c06c954f6 100644 --- a/dart/lib/src/protocol/mechanism.dart +++ b/dart/lib/src/protocol/mechanism.dart @@ -108,7 +108,5 @@ class Mechanism { if (_data?.isNotEmpty ?? false) 'data': _data, if (synthetic != null) 'synthetic': synthetic, }; - - return json; } } From 79fd9be45d7f40c6bd96c36e976fa6715a51fbce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Mon, 3 Oct 2022 14:47:22 +0200 Subject: [PATCH 07/24] Update dart/lib/src/protocol/sentry_user.dart Co-authored-by: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com> --- dart/lib/src/protocol/sentry_user.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index 747b0f46af..ff8c977208 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -43,7 +43,7 @@ class SentryUser { this.geo, this.name, Map? data, - @Deprecated('Will be removed in v7. Use data instead') + @Deprecated('Will be removed in v7. Use [data] instead') Map? extras, }) : assert( id != null || From 2039ade5cd352e8db8a82d06d7536ad2fbd7f2a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 3 Oct 2022 15:45:38 +0200 Subject: [PATCH 08/24] rename methods --- dart/lib/src/scope.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dart/lib/src/scope.dart b/dart/lib/src/scope.dart index 5e25493e87..035b5552cb 100644 --- a/dart/lib/src/scope.dart +++ b/dart/lib/src/scope.dart @@ -389,13 +389,13 @@ class Scope { email: eventUser?.email, ipAddress: eventUser?.ipAddress, username: eventUser?.username, - data: _mergeUserExtra(eventUser?.data, scopeUser.data), + data: _mergeUserData(eventUser?.data, scopeUser.data), ); } /// If the User on the scope and the user of an event have extra entries with /// the same key, the event user extra will be kept. - Map _mergeUserExtra( + Map _mergeUserData( Map? eventExtra, Map? scopeExtra, ) { From e27167124d033b96614c5a500167b2044cf7241f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 3 Oct 2022 16:03:00 +0200 Subject: [PATCH 09/24] don't remove extras --- dart/lib/src/protocol/sentry_user.dart | 13 ++++++++----- dart/lib/src/scope.dart | 2 ++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index ff8c977208..13999b25d0 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -52,8 +52,9 @@ class SentryUser { ipAddress != null || segment != null, ), - assert(data == null || extras == null, 'Only use one of data/extra'), - data = (data ?? extras) == null ? null : Map.from(data ?? extras ?? {}); + data = data == null ? null : Map.from(data), + // ignore: deprecated_member_use_from_same_package + extras = extras == null ? null : Map.from(extras); /// A unique identifier of the user. final String? id; @@ -77,7 +78,7 @@ class SentryUser { final Map? data; @Deprecated('Will be removed in v7. Use [data] instead') - Map? get extras => data; + final Map? extras; final String? subscription; @@ -129,6 +130,8 @@ class SentryUser { if (ipAddress != null) 'ip_address': ipAddress, if (segment != null) 'segment': segment, if (data?.isNotEmpty ?? false) 'data': data, + // ignore: deprecated_member_use_from_same_package + if (extras?.isNotEmpty ?? false) 'extras': extras, if (subscription != null) 'subscription': subscription, if (name != null) 'name': name, if (geoJson != null && geoJson.isNotEmpty) 'geo': geoJson, @@ -148,15 +151,15 @@ class SentryUser { SentryGeo? geo, Map? data, }) { - assert(data == null || extras == null, 'Only use one of data/extra'); return SentryUser( id: id ?? this.id, username: username ?? this.username, email: email ?? this.email, ipAddress: ipAddress ?? this.ipAddress, segment: segment ?? this.segment, + data: data ?? this.data, // ignore: deprecated_member_use_from_same_package - data: (data ?? extras) ?? (this.data ?? this.extras), + extras: extras ?? this.extras, geo: geo ?? this.geo, name: name ?? this.name, ); diff --git a/dart/lib/src/scope.dart b/dart/lib/src/scope.dart index 035b5552cb..5cacd27a43 100644 --- a/dart/lib/src/scope.dart +++ b/dart/lib/src/scope.dart @@ -390,6 +390,8 @@ class Scope { ipAddress: eventUser?.ipAddress, username: eventUser?.username, data: _mergeUserData(eventUser?.data, scopeUser.data), + // ignore: deprecated_member_use_from_same_package + extras: _mergeUserData(eventUser?.extras, scopeUser.extras), ); } From b01c5f8881287d00e2a257676fe79eaa490d0c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 3 Oct 2022 16:12:09 +0200 Subject: [PATCH 10/24] rename variables --- dart/lib/src/scope.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dart/lib/src/scope.dart b/dart/lib/src/scope.dart index 5cacd27a43..e5c9a36ed9 100644 --- a/dart/lib/src/scope.dart +++ b/dart/lib/src/scope.dart @@ -398,17 +398,17 @@ class Scope { /// If the User on the scope and the user of an event have extra entries with /// the same key, the event user extra will be kept. Map _mergeUserData( - Map? eventExtra, - Map? scopeExtra, + Map? eventData, + Map? scopeData, ) { final map = {}; - if (eventExtra != null) { - map.addAll(eventExtra); + if (eventData != null) { + map.addAll(eventData); } - if (scopeExtra == null) { + if (scopeData == null) { return map; } - for (var value in scopeExtra.entries) { + for (var value in scopeData.entries) { map.putIfAbsent(value.key, () => value.value); } return map; From 1268efffa7773e37aabcfcec5e62575f2a325179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 3 Oct 2022 16:28:03 +0200 Subject: [PATCH 11/24] remove subscription --- dart/lib/src/protocol/sentry_user.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index 13999b25d0..1381544ba8 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -39,7 +39,6 @@ class SentryUser { this.email, this.ipAddress, this.segment, - this.subscription, this.geo, this.name, Map? data, @@ -80,8 +79,6 @@ class SentryUser { @Deprecated('Will be removed in v7. Use [data] instead') final Map? extras; - final String? subscription; - /// Approximate geographical location of the end user or device. final SentryGeo? geo; @@ -114,7 +111,6 @@ class SentryUser { data: data, geo: geo, name: json['name'], - subscription: json['subscription'], // ignore: deprecated_member_use_from_same_package extras: extras, ); @@ -132,7 +128,6 @@ class SentryUser { if (data?.isNotEmpty ?? false) 'data': data, // ignore: deprecated_member_use_from_same_package if (extras?.isNotEmpty ?? false) 'extras': extras, - if (subscription != null) 'subscription': subscription, if (name != null) 'name': name, if (geoJson != null && geoJson.isNotEmpty) 'geo': geoJson, }; @@ -147,7 +142,6 @@ class SentryUser { @Deprecated('Will be removed in v7. Use [data] instead') Map? extras, String? name, - String? subscription, SentryGeo? geo, Map? data, }) { From 3afd2c569777935658e795d683eb1962914f5220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Fri, 7 Oct 2022 14:28:50 +0200 Subject: [PATCH 12/24] add geo docs --- dart/lib/src/protocol/sentry_user.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index 1381544ba8..dd16140197 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -80,6 +80,9 @@ class SentryUser { final Map? extras; /// Approximate geographical location of the end user or device. + /// + /// The geolocation is automatically inferred by Sentry.io if the [ipAddress] is set. + /// Sentry however doesn't collect the [ipAddress] automatically because it is PII. final SentryGeo? geo; /// Human readable name of the user. From adb4a773cb5200bfd604d2c32f6c3397982ca555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sat, 8 Oct 2022 14:18:04 +0200 Subject: [PATCH 13/24] remove inferred content type --- dart/lib/src/protocol/sentry_request.dart | 9 --------- 1 file changed, 9 deletions(-) diff --git a/dart/lib/src/protocol/sentry_request.dart b/dart/lib/src/protocol/sentry_request.dart index 369c8d29cb..c657b03269 100644 --- a/dart/lib/src/protocol/sentry_request.dart +++ b/dart/lib/src/protocol/sentry_request.dart @@ -59,16 +59,12 @@ class SentryRequest { /// The fragment of the request URL. final String? fragment; - /// The inferred content type of the request payload. - final String? inferredContentType; - SentryRequest({ this.url, this.method, this.queryString, this.cookies, this.fragment, - this.inferredContentType, dynamic data, Map? headers, Map? env, @@ -91,7 +87,6 @@ class SentryRequest { // ignore: deprecated_member_use_from_same_package other: json['other'], fragment: json['fragment'], - inferredContentType: json['inferred_content_type'], ); } @@ -108,8 +103,6 @@ class SentryRequest { // ignore: deprecated_member_use_from_same_package if (other.isNotEmpty) 'other': other, if (fragment != null) 'fragment': fragment, - if (inferredContentType != null) - 'inferred_content_type': inferredContentType, }; } @@ -119,7 +112,6 @@ class SentryRequest { String? queryString, String? cookies, String? fragment, - String? inferredContentType, dynamic data, Map? headers, Map? env, @@ -136,6 +128,5 @@ class SentryRequest { // ignore: deprecated_member_use_from_same_package other: other ?? _other, fragment: fragment, - inferredContentType: inferredContentType, ); } From e82eeb3acae3d0dc21de678bf53c40972d5f480c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sat, 8 Oct 2022 14:29:41 +0200 Subject: [PATCH 14/24] add data to native layer --- .../main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt | 9 +++++++++ flutter/ios/Classes/SentryFlutterPluginApple.swift | 3 +++ 2 files changed, 12 insertions(+) diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt index 047285a059..f03699f3a0 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -284,6 +284,15 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { } userInstance.others = others } + (user["data"] as? Map)?.let { data -> + val others = mutableMapOf() + for ((key, value) in data.entries) { + if (value != null) { + others[key] = value.toString() + } + } + userInstance.data = others + } Sentry.setUser(userInstance) diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index 8b8f31523f..d36e980494 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -519,6 +519,9 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { if let extras = user["extras"] as? [String: Any] { userInstance.data = extras } + if let data = user["data"] as? [String: Any] { + userInstance.data = data + } SentrySDK.setUser(userInstance) } else { From 7774ab37dc4a8a7c7c915e8b79ad4d371d0e615b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sat, 8 Oct 2022 14:59:51 +0200 Subject: [PATCH 15/24] fix formatting --- dart/lib/src/protocol/sentry_user.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index dd16140197..d3892d64cb 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -80,7 +80,7 @@ class SentryUser { final Map? extras; /// Approximate geographical location of the end user or device. - /// + /// /// The geolocation is automatically inferred by Sentry.io if the [ipAddress] is set. /// Sentry however doesn't collect the [ipAddress] automatically because it is PII. final SentryGeo? geo; From fabed948f7cf0bae7de186b3c8031dc09d97d2bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 10 Oct 2022 18:44:03 +0200 Subject: [PATCH 16/24] add segment --- flutter/android/build.gradle | 2 +- .../src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt | 2 +- flutter/ios/Classes/SentryFlutterPluginApple.swift | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 1fe237e25b..4e8e6b4247 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -54,6 +54,6 @@ android { } dependencies { - api 'io.sentry:sentry-android:6.4.3' + api 'io.sentry:sentry-android:6.5.0-beta.3' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" } diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt index f03699f3a0..63fa9702e6 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -275,6 +275,7 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { (user["id"] as? String)?.let { userInstance.id = it } (user["username"] as? String)?.let { userInstance.username = it } (user["ip_address"] as? String)?.let { userInstance.ipAddress = it } + (user["segment"] as? String)?.let { userInstance.segment = it } (user["extras"] as? Map)?.let { extras -> val others = mutableMapOf() for ((key, value) in extras.entries) { @@ -291,7 +292,6 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { others[key] = value.toString() } } - userInstance.data = others } Sentry.setUser(userInstance) diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index d36e980494..645821e348 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -516,6 +516,9 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { if let ipAddress = user["ip_address"] as? String { userInstance.ipAddress = ipAddress } + if let segment = user["segment"] as? String { + userInstance.segment = segment + } if let extras = user["extras"] as? [String: Any] { userInstance.data = extras } From 79ea6b2f3b9cb4d9ccc2002101fe3c92fa94ea4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 10 Oct 2022 19:06:29 +0200 Subject: [PATCH 17/24] merge data --- flutter/ios/Classes/SentryFlutterPluginApple.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index 645821e348..9bed49c328 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -523,7 +523,13 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { userInstance.data = extras } if let data = user["data"] as? [String: Any] { - userInstance.data = data + if(userInstance.data == nil) { + userInstance.data = data + } else { + userInstance.data = userInstance.data!.reduce(into: data) { + (r, e) in r[e.0] = e.1 + } + } } SentrySDK.setUser(userInstance) From 5beb837288df7f9aa560ee82a30fee9ee46a8d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 10 Oct 2022 19:21:44 +0200 Subject: [PATCH 18/24] fix changelog --- CHANGELOG.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04bbf80234..6ecd393c00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,19 @@ # Changelog -## 6.12.0 +## Unreleased ### Fixes - Bring protocol up to date with latest Sentry protocol ([#1038](https://github.com/getsentry/sentry-dart/pull/1038)) + +### Dependencies + +- Bump Android SDK from v6.4.3 to v6.5.0-beta3 ([#1038](https://github.com/getsentry/sentry-dart/pull/1038)) + +## 6.12.0 + +### Fixes + - Handle traces sampler exception ([#1040](https://github.com/getsentry/sentry-dart/pull/1040)) - tracePropagationTargets ignores invalid Regex ([#1043](https://github.com/getsentry/sentry-dart/pull/1043)) - SentryDevice cast error ([#1059](https://github.com/getsentry/sentry-dart/pull/1059)) From cfa7f3bafd658e8c0e521709fe0ebae206a3516e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 10 Oct 2022 19:28:01 +0200 Subject: [PATCH 19/24] fix swift lint --- flutter/ios/Classes/SentryFlutterPluginApple.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index 05d2b484ce..c7cd17bc0c 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -526,9 +526,7 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { if(userInstance.data == nil) { userInstance.data = data } else { - userInstance.data = userInstance.data!.reduce(into: data) { - (r, e) in r[e.0] = e.1 - } + userInstance.data = userInstance.data!.reduce(into: data) { (first, second) in first[second.0] = second.1 } } } From 3d0896c71df42662d41912b0c36dcf5c1cb1037a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Tue, 11 Oct 2022 09:15:46 +0200 Subject: [PATCH 20/24] Update dart/lib/src/protocol/sentry_user.dart --- dart/lib/src/protocol/sentry_user.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index d3892d64cb..f0e4cb5e86 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -83,6 +83,8 @@ class SentryUser { /// /// The geolocation is automatically inferred by Sentry.io if the [ipAddress] is set. /// Sentry however doesn't collect the [ipAddress] automatically because it is PII. + /// The geo location will currently not be synced to the native layer, if available. + // See https://github.com/getsentry/sentry-dart/issues/1065 final SentryGeo? geo; /// Human readable name of the user. From 279ada4e4b8f5948444f67942491370d1b47884b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Tue, 11 Oct 2022 09:20:23 +0200 Subject: [PATCH 21/24] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb01bf57d3..1c59fb817a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,13 @@ # Changelog -## 6.12.1 +## Unreleased ### Fixes - Bring protocol up to date with latest Sentry protocol ([#1038](https://github.com/getsentry/sentry-dart/pull/1038)) +## 6.12.1 + ### Dependencies - Bump Android SDK from v6.4.3 to v6.5.0 ([#1062](https://github.com/getsentry/sentry-dart/pull/1062), [#1064](https://github.com/getsentry/sentry-dart/pull/1064)) From 60b99db1f32351bdf9a69530e2b456b3c6d14167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Tue, 11 Oct 2022 17:59:00 +0200 Subject: [PATCH 22/24] fix swift lint --- flutter/ios/Classes/SentryFlutterPluginApple.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index e129e1c967..c2208941f6 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -523,10 +523,10 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { userInstance.data = extras } if let data = user["data"] as? [String: Any] { - if(userInstance.data == nil) { - userInstance.data = data + if let oldData = userInstance.data { + userInstance.data = oldData.reduce(into: data) { (first, second) in first[second.0] = second.1 } } else { - userInstance.data = userInstance.data!.reduce(into: data) { (first, second) in first[second.0] = second.1 } + userInstance.data = data } } From 49eb8224ca70616a2b9bf6ef1c4b303e9b9126bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Wed, 12 Oct 2022 10:21:03 +0200 Subject: [PATCH 23/24] Update build.gradle --- flutter/example/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/example/android/app/build.gradle b/flutter/example/android/app/build.gradle index 9c708c5c3e..f3cf4a9d90 100644 --- a/flutter/example/android/app/build.gradle +++ b/flutter/example/android/app/build.gradle @@ -66,7 +66,7 @@ android { // TODO: we need to fix CI as the version 21.1 (default) is not installed by default on // GH Actions. - ndkVersion "21.4.7075529" // windows requires 21.4.7075529 + ndkVersion "25.1.8937393" externalNativeBuild { cmake { From 37dbdeb2ed37276a7ad49f98d39ec890ea7f7b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Wed, 12 Oct 2022 13:24:43 +0200 Subject: [PATCH 24/24] Update CHANGELOG.md --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e90c5464f..3634834d03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,15 @@ # Changelog -## 6.12.2 +## Unreleased ### Fixes - Bring protocol up to date with latest Sentry protocol ([#1038](https://github.com/getsentry/sentry-dart/pull/1038)) + +## 6.12.2 + +### Fixes + - Avoid dependency conflict with package_info_plus v2 ([#1068](https://github.com/getsentry/sentry-dart/pull/1068)) ## 6.12.1