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
Support multi client storage #290
Conversation
ensures that error/session files in the old location are found
The filestore now uses a different directory for each different client api key/endpoint configuration. This supports the case where an application is configured with multiple clients. Old error reports stored on the device should be delivered in the same way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave this a once-over. On the surface of it, it looks good to me, though I didn't run it, nor understand it all.
I have a couple of questions at a high-level:
If the app crashes, then is updated with a new version of Bugsnag, is the "old" state of the filesystem compatible with this new logic?
Specifically, will the app succesfully send the crashes to Bugsnag? Could the state of the filesystem cause Bugsnag to crash?
Yes.
I'm not aware of anything within these changes that would cause an unhandled crash within the notifier, although the risky areas would be around:
|
final String storeDirectory; | ||
final String oldDirectory; | ||
|
||
File storageDir; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should this property be renamed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted it to be clear that there is a difference between the old directory we previously used, and the client-specific directory that we will use in future. Maybe the nomenclature is a bit off here?
|
||
// support multiple clients in the same app by using a unique directory path | ||
|
||
private File getStorageDir(String path, @NonNull Configuration config) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a project rotates API keys or the on-premise endpoint changes, will stored files ever be sent (or cleared)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not currently. Is this something we need to address?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah - in the worst case, files shouldn't be left on disk indefinitely. In the best case, everything is delivered according to the configuration at the time the report was captured. Splitting directories by endpoint and key works until either component needs to change. A better approach would be to write the entire request to disk including the endpoint and the headers. For example, a (nearly) raw HTTP request (format amended to encode protocol and port):
POST https://notify.bugsnag.com
Bugsnag-Api-Key: aaaabaaaabaaaabaaaa
Content-Type: application/json
{"events": [{"severity": "warning", "exceptions":[]}]
on premise example for contrast:
POST https://bugsnag.example.internal:79002
Bugsnag-Api-Key: aaaabaaaabaaaabaaaa
Content-Type: application/json
{"events": [{"severity": "warning", "exceptions":[]}]
Which could then be parsed until encountering the double newline for the endpoint and headers, then stream the rest as the body directly.
This should:
- Avoid cycling directories, ensuring everything is delivered and cleared from disk
- Tie API key to a request even if cached on disk
- Not affect reports not cached to disk
- Have the same integration tests
- Have the same/similar logic for handling reports in the old location
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this approach makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's also worth mentioning that we use the cache directory when storing files on Android, so Files may be deleted if they are left forever and the system is low on disk space.
Reading through the docs it looks like we may want to perform a check on our quota when writing files - I'll create a separate ticket for that.
I think it still makes sense to have a limit of around 128 reports/sessions on disk at any time.
for (File file : files) { | ||
assertTrue(file.getAbsolutePath().endsWith("foo.json")); | ||
} | ||
assertEquals(2, files.size()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there are multiple clients, will all attempt to find and send files from the "old" directory?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I've added a mazerunner scenario which covers this.
adds a scenario to verify that errors stored in the old directory are reported by multiple clients
if (exceptionDir.isDirectory()) { | ||
File[] files = exceptionDir.listFiles(); | ||
if (storageDir.isDirectory()) { | ||
File[] files = storageDir.listFiles(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs fixing as it doesn't take the previous directory into account.
alters the filestore so that it obtains all files (including from the legacy directory) when the max number of files is reached, and the oldest file needs to be deleted
@kattrali I wanted to check whether the remaining inline comments require any actions, namely:
|
Seems fine, perhaps should be annotated for removal in the next major
Ah, added detail inline for this. |
Closing this PR off as the intended approach has changed somewhat. |
Silence iOS test fixtures build warnings
Adds support for storage of files on a per-client basis, by using a different directory for each client based on a hash of their configured API key and endpoint.
This PR alters the
FileStore
class and its descendants so that new errors/sessions are stored in the appropriate location. Previously cached errors/sessions will still be flushed from disk from the old location - JUnit test coverage is added for this.Also see #286 and #285