Closed okalentiev closed 3 years ago
@okalentiev , are you adding any custom data to the payloads when reporting to Rollbar? Could it be you have circular references in the custom data? In general, we do make recursive calls when serializing the payloads to JSON. So, it is not unusual to see repetitive calls in the serialization stack. And we definitely not watching for circular data references within the serializable objects at the moment. The explicitly defined payload objects do not have any such references but any attached custom data potentially can have it and it would definitely resolve in an infinite loop during the serialization. Please, make sure not to add complex objects as custom data to the payloads.
Yes @akornich, judging from our previous crash investigations this is most definitely the case 🙂
We are already doing extensive filtering for the custom objects, but it might be that there are circular references. Though I would expect that we catch them before sending them to Rollbar 🤔
extension Dictionary where Key == AnyHashable, Value == Any {
// - Turn URLs to strings for rollbar tracking and return if new data is valid json
// - Map nil to NSNull() for JSONSerialization
var rollbarFiltered: [AnyHashable: Any]? {
var cleanData = [AnyHashable: Any]()
for (key, value) in self {
switch value {
case is URL:
cleanData[key] = (value as! URL).absoluteString
case Optional<Any>.none:
cleanData[key] = NSNull()
case is [AnyHashable: Any]:
cleanData[key] = (value as? [AnyHashable: Any])?.rollbarFiltered ?? NSNull()
default:
cleanData[key] = value
}
}
if JSONSerialization.isValidContent(cleanData) {
return cleanData
}
assertionFailure("Tried to send invalid json to rollbar: \(cleanData)")
return nil
}
}
extension JSONSerialization {
static func isValidContent(_ content: Any) -> Bool {
if content is NSString || content is NSNumber {
return true
} else if content is NSArray || content is NSDictionary {
return JSONSerialization.isValidJSONObject(content)
} else {
return false
}
}
}
I'm trying to think of a fast solution for now before we review our logging properly. We can do an extra step to map out the dictionary to string, then we might be able to avoid circular references. What do you think?
@okalentiev, I see what you mean. On a few occasions when I was implementing very complex application-specific models that were expected to support very detailed logging/tracing capability, I went with the concept of Traceable interface defining mainly one method TraceAsString that would produce a well-formatted string (multi-line string, in general) representation of the object claiming to implement Traceable interface. I had a basic reusable implementation of the method based on type-reflection of only properties of primitive types as well as Traceable ones (and collections of those). That gave me a great starting point with only a hand full of instances when I had to override it with a custom more elaborate implementation. Then my logging infrastructure would first try to resolve any incoming object to include into a log as Traceable and call TraceAsString on it in order to inject the object trace into a log record. You can go with a similar approach when turning your objects of interest into the Rollbar custom data values.
BTW, regarding your snippet, we have a somewhat similar solution implemented here.
Thanks for the suggestions! I think we are far from that at this point, but it's definitely something we should consider. I believe it might be even more straightforward to utilize Swift's CustomDebugStringConvertible
protocol. Our issue is probably coming from some JSON responses that we are logging for debugging purposes and since we pass them as dictionaries it causes issues. I will flatten them to strings so as not to confuse mapping logic.
I actually didn't realize that Rollbar sunset's this version. I will make sure we switch to the Rollbar-Apple asap.
@okalentiev , you are welcome! yes, we are moving from Rollbar-iOS to Rollbar-Apple. Rollbar-Apple is lightweight compare to Rollbar-iOS. It is modular. Crash reporting is optional and we are planning to support a few crash reporting alternatives. KSCrash and PLCrashReporter are already supported. Rollbar-Apple SDK is natively built on top of SwiftPM and provides a cleaner API and more Swift friendlier. @okalentiev , can we close this issue or you'll need further support on this?
Sure, thanks for the follow-up.
Looking for assistance figuring out how to fix this crash. It happens on production so there are no exact steps on how to reproduce it, unfortunately.
Rollbar iOS Version: 1.12.14 iOS: 13.6.1 (17G80) Device: iPhone 8 Plus