-
Notifications
You must be signed in to change notification settings - Fork 21
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
Can't interpret line numbers with sourcemap. #1
Comments
I haven't actually deployed and been using this yet myself. But as a wild guess, is it possible these numbers represent character offsets, not line offsets? |
Thanks for the suggestion. No, trying with line 0 and column 9477 gives nothing, line 1 and column 9477 gives an output in polyfills, not in my code. If they were character offsets from the beginning of the file they'd have to be much bigger. They may be column numbers, and the line number is just missing. |
Ah interesting idea. Maybe my patch to react-native-fabric is buggy and missing column numbers? What platform are you testing with? This is the code that converts JS exceptions to objects Crashlytics will understand: |
I'm on iOS. Probably something's going wrong with the translation from the JS stackframe to CLSStackFrame but I don't know enough Objective C to be able to see what's wrong. |
As I tested many cases, the
The log will be:
|
Hey guys, I've been working on this problem, and after pulling most of my hair out, finally have a solution. The fix is a combination of pulling sourcemaps, tweaking this library and the native crashlytics reporting as well. I need some time to pick up the pieces and make an elegant patch and for now, stay tuned :). |
@mikelambert I'm trying to evaluate what's needed to be changed, and it looks like one PR for So the very least we'll have 2 PRs that depend upon each other which is a bummer (since we can't guarantee the upstream PR will happen on time). Any idea what to do here? perhaps fork Further, we need a new API like this:
Where the exising And also, we need a modified build step, or at least a README instruction that exports sourcemap as part of the regular RN build (I hacked it out manually in packager but I hope it comes built-in and does proper sourcemaps). |
Would it make sense to integrate this library (with your changes) into On Sun, Jul 10, 2016 at 5:12 AM Dotan J. Nahum [email protected]
|
I would be fine integrating this functionality entirely into react-native-fabric. I was unsure on which direction to go when building it originally. And I'm fine with a RN-fabric fork that we depend on until things are all upstreamed. I would prefer an init() and initWithSourceMap(). Sometimes the exceptions are visible/useful to users without line numbers, and probably faster to load and have smaller filesizes, so I'm okay with offering that backup support. Yeah, ideally we'd find a way to build sourcemaps as part of the building flow. But that might require manual changes to the ios/android build scripts, or changes to RN itself. I'm not as clear what was required here for your packager changes...but perhaps they could be enabled by a flag, and upstreamed to the RN codebase? |
So I'm now after a full project setup with how I think this can work, and it works great. Building the sourcemap is done in a similar way to a bundle, so I guess this is a command a user would need to run (I hacked the default react-native runner - but I think we can drive the fact that the build will always generate source maps to the core react native repo with a PR, aside from little more CPU i don't see why not) So here's how you engage with the new API: function crashload(){
const path = `${RNFS.MainBundlePath}/sourcemap.js`
RNFS.readFile(path, 'utf8').then((contents)=>{
crashlytics.init(JSON.parse(contents))
})
}
crashload() Unfortunately, anyone wanting to read a bundled source map has only one way to do that - with RNFS. Previous React Native releases had already read sourcemaps and had sourcemap exposed as a magic global variable but right now a React Native process comes up blank. It was made so in order to save memory - so we might need to warn users that using sourcemaps isn't for free. Back to the code sample, here,
And to sum it up, this uses the patch to this library and the Next up I'm going to submit a PR tomorrow (since I need to use this time right now for something else), and that will include the |
I've submitted the PR. To not hold this PR longer, I synthesized something that would make sense instead of a function name: file + line + col which you can take and go back to your source tree and find exactly what was the bit that was causing trouble. There's quite a bit of prepwork to do to set up sourcemaps and I've tried lining it out on the README, but I'll be here to help anyone wanting to set it up. The second issue with resolving proper line numbers was a bug in |
So what this does is do the sourcemap conversion on the device before uploading the stack trace to crashlytics? Very cool! However, I don't think I'd want to use it that way, first, because of the size issue in including the sourcemap in the app bundle, and second, I use code-push, and the sourcemap in the bundle is likely going to be out of date. So I'd want to use this to upload a correct trace of the minified bundle, then download it and translate manually. Can it be used like that? |
Yes, that's why the library gets a materialized source map already. Reading the source map is separated from using it, and in the given and suggested example it is packed with the app and read from the app bundle. It could by all means be fetched from network. I have to say, that a real solution for this problem must be that crashlytics or any server side component should do the mapping and translation based on a copy of the source maps that is sent to them. That's how it should work, because really, the client doing this - that's wasting precious memory for little value. In conclusion as long as Crashlytics don't provide this, we have to make up for it. Another 2 ways I thought about and dismissed early on is to make a service that integrates with crashlytics and provides an alternative view that they don't provide, and to make a transparent crashlytics-like service that accepts an event, demangles it and forwards it to the real crashlytics on the fly, and as far as the client cares it talks to the real crashlytics. Hope that makes sense. But really I'd hope crashlytics comes up with this feature soon, otherwise use this solution or move to more JavaScript friendly logging service early on. |
OK I'm trying this out using the fabric and crashlytics repos from github:jondot. When I initialize with the sourcemap, it does work great--- the crashlytics dashboard shows the exact function, file, line number and column of the error. But when launching again after the crash, the app is unresponsive for several seconds while it processes the 1.7MB sourcemap. I don't want to use it this way, since I'm sure that my need to examine crashlogs will be very infrequent ;-) So when I call crashlytics.init() with no arguments (I assume that's the way to use it if I want to do sourcemap translation later), the crashlog in my crashlytics dashboard looks like this:
Finally, if I use your fix to react-native-fabric and the old version of react-native-fabric-crashlytics, I get this:
Which does make some sense. When looking that up in the sourcemap, I get:
It's finding the right file, anyway. The error is actually on line 291. So we need column information in the bundle. |
Thanks @chetstone ! yes, I think I didn't give some love to the old path with init without sourcemap as much as needed. This should be it jondot@b5ad744#diff-168726dbe96b3ce427e7fedce31bb0bcR38 Regarding loading of sourcemap - that's true, completely the tradeoff of doing the mapping this way. My only suggestion would be to load that in background and init only when ready, or wait to see if there are better ideas. |
@chetstone fix is in, details here |
Thanks @jondot but sorry to say that doesn't really help much. It now shows the function name but I've got dozens of functions called onPress in my code. What I really need is the line number and column number in the bundle. Here's what I get now.
I guess 602 and 582 are line numbers but they shouldn't say foobar:602, the should be labeled with line: And column is still missing. It seems like if these are available when translating to a sourcemap they should be viewable here. |
I took a look... I can't figure out why the column number doesn't come through but if you use
That produces a report like this on the fabric dashboard:
Not perfect but good enough. |
Thanks guys for all the investigation, I'm impressed how far you've taken this (yay open source!) Some thoughts:
|
Perhaps it also takes a long time on the first load and I didn't notice. I won't have time to investigate further for a couple of days.
|
@mikelambert , probably you should also take a look at this issue too. Not sure if it only affects Android (it happened to me on Android). |
Thanks for the tip @jbrodriguez, I've just pushed 0.1.4 with an {offline: true} fix. (Note, jbrodriguez's issue is independent of the sourcemap issue...) |
@mikelambert, looks like you're missing a closing brace in your fix. On Sun, Jul 17, 2016 at 7:47 PM Mike Lambert [email protected]
|
Yup, sorry about that. :/ I noticed and immediately pushed a 0.1.5 (before your message) to NPM. Looks like I forgot to push the github repo before heading out, though...I've pushed that now. |
Thanks for the great work guys. I'm trying to understand how to use this correctly and all the option and pros and cons to the options (aka slower load times). @jondot can you explain the pros and cons to not passing a sourcemap to init? Should use your fork or this fork? What I'm hoping to do is use this to get some basic information about where the crash is occurring but not at the cost of slowing down the app very much. Sounds like I can call init without the source map and get what I'm looking for, right? |
@wootwoot1234 sorry for the late response. If you do use this, it means on every crash that's sent out, the actual device will do the symbolication of the stack trace, which means a bit of CPU work for the device. The idea is that in normal life a backend does this (that's how it happens on native, and why you send out your symbols to apple). |
Reviewed By: bestander Differential Revision: D3863894 fbshipit-source-id: a282758e022d403743841bc59277196e6741ed18
Hey Jon, I just remember I never actually merged your change in. I know you said we shouldn't rush, but I think we "didn't rush" for too long. :) It looks fully backwards compatible, so I'm fine to merge it in. But the "use sourcemap" case SourceMapConsumer does a lot of work at startup (json parsing, extracting all the metadata, etc). Ideally I'd like to make that lazily-done at exception time, as much as possible. Are you interested in making that change, or should I merge this in as-is, and consider my own attempt at improving the load times myself? |
Hey Mike, |
@mikelambert I think it would be beneficial to merge the code as is, I agree with @jondot 's last comment about "sourcemaps being inaccurate even after this patch" but anything would be better than what's currently available. Once it's merged it will easier to add a lazy function to do the JSON parsing and such at exception time. Additionally all of this is opt-in behaviour, so it's unlikely to affect existing users, and people who do decide to opt-in will be aware of the caveats. |
Any updates on this? I would love to have correct function names and line numbers in my reports.. |
Since I needed this, I made a pull request that enables line numbers on iOS and also on Android but, the Android ones are not correct due to facebook/react-native#6946. |
@mikelambert When would merge the pr? |
When I use this component, I get a log file in Crashlytics that looks something like this:
When I use sourcemap using the script given here, and using line number 9477 and column 1, I get this output:
There are only 608 lines in my main.jsbundle. How to interpret the output I'm seeing on crashlytics?
Thanks
The text was updated successfully, but these errors were encountered: