Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Deserializing Events #4724

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft

Conversation

philipphofmann
Copy link
Member

@philipphofmann philipphofmann commented Jan 16, 2025

📜 Description

Add Decodable implementations via Swift extensions to deserialize SentryEvents.

This is the feature branch PR for deserializing SentryEvents. We're going to open multiple PRs to this one, so we have smaller PRs for quicker reviews.

To minimize the scope the goal is not to use Encodable and keep the existing serialization logic.

Tasks

Preview Give feedback

💡 Motivation and Context

We need this for app hangs #4261.

💚 How did you test it?

📝 Checklist

You have to check all boxes before merging:

  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

Add Decodable implementations via Swift extensions to deserialize
SentryEvents.
Copy link

github-actions bot commented Jan 16, 2025

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 6e024ed

@philprime
Copy link
Contributor

In case you want to implement a custom encoder for converting to the dictionary, I did implement a custom encoder before in Postie, to parse custom property wrappers/annotations into a structure to send URL requests.

Even though that use case is quite more complicated than just encoding to a dictionary, it might be helpful for reference:

https://github.com/kula-app/Postie/blob/main/Sources/Postie/Encoder/RequestEncoder.swift

Copy link

github-actions bot commented Jan 16, 2025

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1217.31 ms 1247.08 ms 29.78 ms
Size 22.31 KiB 789.76 KiB 767.45 KiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
279841c 1237.29 ms 1254.12 ms 16.83 ms
e92acb3 1241.51 ms 1258.59 ms 17.08 ms
a176fc4 1226.24 ms 1247.50 ms 21.26 ms
e19cca3 1203.98 ms 1232.55 ms 28.57 ms
f801098 1225.41 ms 1237.45 ms 12.04 ms
32c4446 1225.00 ms 1231.29 ms 6.29 ms
c319795 1205.12 ms 1231.20 ms 26.08 ms
94d8eb3 1221.56 ms 1236.81 ms 15.26 ms
f2daa68 1238.40 ms 1256.43 ms 18.03 ms
024f3db 1228.08 ms 1246.55 ms 18.47 ms

App size

Revision Plain With Sentry Diff
279841c 22.84 KiB 403.19 KiB 380.34 KiB
e92acb3 21.90 KiB 724.68 KiB 702.78 KiB
a176fc4 22.84 KiB 403.24 KiB 380.39 KiB
e19cca3 21.58 KiB 669.74 KiB 648.16 KiB
f801098 21.58 KiB 614.71 KiB 593.13 KiB
32c4446 22.84 KiB 403.24 KiB 380.39 KiB
c319795 20.76 KiB 431.99 KiB 411.22 KiB
94d8eb3 21.58 KiB 417.86 KiB 396.28 KiB
f2daa68 21.58 KiB 418.40 KiB 396.82 KiB
024f3db 21.90 KiB 725.67 KiB 703.76 KiB

Previous results on branch: feat/deserializing-events

Startup times

Revision Plain With Sentry Diff
04e8394 1223.24 ms 1244.33 ms 21.08 ms
378d4bd 1216.53 ms 1241.19 ms 24.66 ms
8dae1f6 1212.60 ms 1226.52 ms 13.93 ms
8a562cc 1228.57 ms 1245.18 ms 16.60 ms

App size

Revision Plain With Sentry Diff
04e8394 22.31 KiB 771.93 KiB 749.62 KiB
378d4bd 22.31 KiB 784.05 KiB 761.73 KiB
8dae1f6 22.31 KiB 772.51 KiB 750.20 KiB
8a562cc 22.31 KiB 773.33 KiB 751.02 KiB

@philipphofmann
Copy link
Member Author

In case you want to implement a custom encoder for converting to the dictionary

Thanks for pointing that out. I would rather spend the time converting all the serialization to Decoable, because that's what we should do on the long run, IMO.

@philprime, does the overall approach look good to you?

@philprime
Copy link
Contributor

Looks good to me.

@philipphofmann
Copy link
Member Author

philipphofmann commented Jan 16, 2025

FYI, @philprime, I ditched the Encodable because we have some tests validating the data for envelopes that break when using Encodable. Switching the whole serialization to Encodable will make fixing the tests easier. I want to keep the scope small for now.

Copy link

codecov bot commented Jan 16, 2025

Codecov Report

Attention: Patch coverage is 99.68187% with 3 lines in your changes missing coverage. Please review.

Project coverage is 91.321%. Comparing base (f5a9f3f) to head (6e024ed).

Files with missing lines Patch % Lines
...s/Swift/Protocol/Codable/DecodeArbitraryData.swift 95.774% 3 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##              main     #4724       +/-   ##
=============================================
+ Coverage   91.112%   91.321%   +0.209%     
=============================================
  Files          623       636       +13     
  Lines        72495     73415      +920     
  Branches     25785     26785     +1000     
=============================================
+ Hits         66052     67044      +992     
+ Misses        6351      6272       -79     
- Partials        92        99        +7     
Files with missing lines Coverage Δ
Sources/Sentry/SentryGeo.m 95.000% <100.000%> (+1.000%) ⬆️
...ft/Protocol/Codable/NSNumberDecodableWrapper.swift 100.000% <100.000%> (ø)
Sources/Swift/Protocol/Codable/SentryCodable.swift 100.000% <100.000%> (ø)
...es/Swift/Protocol/Codable/SentryFrameCodable.swift 100.000% <100.000%> (ø)
...rces/Swift/Protocol/Codable/SentryGeoCodable.swift 100.000% <100.000%> (ø)
...wift/Protocol/Codable/SentryMechanismCodable.swift 100.000% <100.000%> (ø)
.../Protocol/Codable/SentryMechanismMetaCodable.swift 100.000% <100.000%> (ø)
.../Swift/Protocol/Codable/SentryNSErrorCodable.swift 100.000% <100.000%> (ø)
...ift/Protocol/Codable/SentryStacktraceCodable.swift 100.000% <100.000%> (ø)
...ces/Swift/Protocol/Codable/SentryUserCodable.swift 100.000% <100.000%> (ø)
... and 11 more

... and 24 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f5a9f3f...6e024ed. Read the comment docs.

Comment on lines 3 to 15
func decodeFromJSONData<T: Decodable>(jsonData: Data) -> T? {
if jsonData.isEmpty {
return nil
}

do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: jsonData)
} catch {
SentryLog.error("Could not decode object of type \(T.self) from JSON data due to error: \(error)")
return nil
}
}
Copy link
Contributor

@brustolin brustolin Jan 20, 2025

Choose a reason for hiding this comment

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

l:

Suggested change
func decodeFromJSONData<T: Decodable>(jsonData: Data) -> T? {
if jsonData.isEmpty {
return nil
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: jsonData)
} catch {
SentryLog.error("Could not decode object of type \(T.self) from JSON data due to error: \(error)")
return nil
}
}
extension Decodable {
init?(jsonData: Data) {
guard !jsonData.isEmpty else {
return nil
}
do {
let decoder = JSONDecoder()
self = try decoder.decode(Self.self, from: jsonData)
} catch {
print("Could not decode object of type \(Self.self) from JSON data due to error: \(error)")
return nil
}
}
}

Then, instead of

let decoded = decodeFromJSONData(jsonData: data) as Geo?

We have

let decoded = Geo(jsonData: data)

Copy link
Contributor

Choose a reason for hiding this comment

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

Just want to point out that Decodable is considered to be decoder-agnostic, so adding a convenience method to the type would not be agnostic anymore. It also takes away the option to configure JSONDecoder in unit tests etc.

Copy link
Contributor

Choose a reason for hiding this comment

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

It is just a convenience initializer, just like the decodeFromJSONData that it would replace, that also does not give the option to configure JSONDecoder

Add Decodable/Deserializing of SentryFrame, including logic for decoding NSNumbers.
### Internal

- Change macros TEST and TESTCI to SENTRY_TEST and SENTRY_TEST_CI (#4712)
- Deserializing SentryEvents with Decodable (#4724)

Choose a reason for hiding this comment

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

  • 🚫 The changelog entry seems to be part of an already released section ## 8.44.0.
    Consider moving the entry to the ## Unreleased section, please.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants