-
-
Notifications
You must be signed in to change notification settings - Fork 277
Feat : add a Hub class #113
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
Merged
Merged
Changes from 20 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
6a5d2c3
hub interface & instanciation
rxlabz 4f01775
- hub capture event
rxlabz ea5c55f
- hub capture exception
rxlabz bd09da0
hub captureMessage
rxlabz c5317a4
fix some tests
rxlabz 6a8910e
fix more tests
rxlabz f5d3dd0
changelog
rxlabz f102ac3
fix all tests
rxlabz 055b9b0
feedbacks
rxlabz 370d2d5
fix test : revert to ArgumentError.notNull('options')
rxlabz 974d1f6
remove required hub methods
rxlabz c8c1df0
implement `Hub.close()`
rxlabz 6c6c649
feedbacks : remove the IHub interface + minors
rxlabz a924040
Hub.configureScope
rxlabz 823c91c
Hub.clone and Scope.clone
rxlabz b04d67c
remove the non required scope methods
rxlabz 37cf83c
replace the ListQueue _stack by a DoubleLinkedQueue
rxlabz b9f9f9e
rename `response` to `sentryId`
rxlabz 5067a36
serialize the potential error stackTrace
rxlabz 54729ba
Revert the DoubleLinkedQueue to a resourceless ListQueue
rxlabz 729d6bc
fix a json serialization test
rxlabz 4ea1537
add a const SentryId.emptyId
rxlabz 5932534
don't assign a new lastEventId if the client capture method is not ca…
rxlabz 97f6c53
feedbacks:
rxlabz e89c488
feedbacks:
rxlabz 647f1b0
simplify the captureMessage API
rxlabz 91f709a
capture message
rxlabz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,280 @@ | ||
| import 'dart:async'; | ||
| import 'dart:collection'; | ||
|
|
||
| import 'client.dart'; | ||
| import 'noop_client.dart'; | ||
| import 'protocol.dart'; | ||
| import 'scope.dart'; | ||
| import 'sentry_options.dart'; | ||
|
|
||
| typedef ScopeCallback = void Function(Scope); | ||
|
|
||
| /// SDK API contract which combines a client and scope management | ||
| class Hub { | ||
| static SentryClient _getClient({SentryOptions fromOptions}) { | ||
| return SentryClient( | ||
| dsn: fromOptions.dsn, | ||
| environmentAttributes: fromOptions.environmentAttributes, | ||
| compressPayload: fromOptions.compressPayload, | ||
| httpClient: fromOptions.httpClient, | ||
| clock: fromOptions.clock, | ||
| uuidGenerator: fromOptions.uuidGenerator, | ||
| ); | ||
| } | ||
|
|
||
| final ListQueue<_StackItem> _stack; | ||
marandaneto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| final SentryOptions _options; | ||
|
|
||
| factory Hub(SentryOptions options) { | ||
| _validateOptions(options); | ||
|
|
||
| return Hub._(options); | ||
| } | ||
|
|
||
| Hub._(SentryOptions options) | ||
| : _options = options, | ||
| _stack = ListQueue() { | ||
| _stack.add(_StackItem(_getClient(fromOptions: options), Scope(_options))); | ||
| _isEnabled = true; | ||
| } | ||
|
|
||
| static void _validateOptions(SentryOptions options) { | ||
| if (options == null) { | ||
| throw ArgumentError.notNull('options'); | ||
rxlabz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| if (options.dsn == null) { | ||
| throw ArgumentError.notNull('options.dsn'); | ||
| } | ||
| } | ||
|
|
||
| bool _isEnabled = false; | ||
|
|
||
| /// Check if the Hub is enabled/active. | ||
| bool get isEnabled => _isEnabled; | ||
|
|
||
| SentryId _lastEventId; | ||
|
|
||
| /// Last event id recorded in the current scope | ||
| SentryId get lastEventId => _lastEventId; | ||
|
|
||
| /// Captures the event. | ||
| Future<SentryId> captureEvent(Event event) async { | ||
| var sentryId = SentryId.empty(); | ||
|
|
||
| if (!_isEnabled) { | ||
| _options.logger( | ||
| SeverityLevel.warning, | ||
| "Instance is disabled and this 'captureEvent' call is a no-op.", | ||
| ); | ||
| } else if (event == null) { | ||
| _options.logger( | ||
| SeverityLevel.warning, | ||
| 'captureEvent called with null parameter.', | ||
| ); | ||
| } else { | ||
| final item = _stack.first; | ||
| if (item != null) { | ||
| try { | ||
| sentryId = await item.client.captureEvent(event, scope: item.scope); | ||
| } catch (err) { | ||
| /* TODO add Event.id */ | ||
| _options.logger( | ||
| SeverityLevel.error, | ||
| 'Error while capturing event with id: ${event}', | ||
| ); | ||
| } | ||
| } else { | ||
| _options.logger( | ||
| SeverityLevel.fatal, | ||
| 'Stack peek was null when captureEvent', | ||
| ); | ||
| } | ||
| } | ||
| _lastEventId = sentryId; | ||
| return sentryId; | ||
| } | ||
|
|
||
| /// Captures the exception | ||
| Future<SentryId> captureException( | ||
| dynamic throwable, { | ||
| dynamic stackTrace, | ||
| }) async { | ||
| var sentryId = SentryId.empty(); | ||
|
|
||
| if (!_isEnabled) { | ||
| _options.logger( | ||
| SeverityLevel.warning, | ||
| "Instance is disabled and this 'captureException' call is a no-op.", | ||
| ); | ||
| } else if (throwable == null) { | ||
| _options.logger( | ||
| SeverityLevel.warning, | ||
| 'captureException called with null parameter.', | ||
| ); | ||
| } else { | ||
| final item = _stack.first; | ||
marandaneto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (item != null) { | ||
| try { | ||
| // TODO pass the scope | ||
| sentryId = await item.client.captureException( | ||
| throwable, | ||
| stackTrace: stackTrace, | ||
| ); | ||
| } catch (err) { | ||
| _options.logger( | ||
| SeverityLevel.error, | ||
| 'Error while capturing exception : ${throwable}', | ||
| ); | ||
| } | ||
| } else { | ||
| _options.logger( | ||
| SeverityLevel.fatal, | ||
| 'Stack peek was null when captureException', | ||
| ); | ||
| } | ||
| } | ||
| _lastEventId = sentryId; | ||
| return sentryId; | ||
| } | ||
|
|
||
| /// Captures the message. | ||
| Future<SentryId> captureMessage( | ||
| Message message, { | ||
| SeverityLevel level = SeverityLevel.info, | ||
| }) async { | ||
| var sentryId = SentryId.empty(); | ||
|
|
||
| if (!_isEnabled) { | ||
| _options.logger( | ||
marandaneto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| SeverityLevel.warning, | ||
| "Instance is disabled and this 'captureMessage' call is a no-op.", | ||
| ); | ||
| } else if (message == null) { | ||
| _options.logger( | ||
| SeverityLevel.warning, | ||
| 'captureMessage called with null parameter.', | ||
| ); | ||
| } else { | ||
| final item = _stack.first; | ||
| if (item != null) { | ||
| try { | ||
| // TODO pass the scope | ||
| sentryId = await item.client.captureMessage(message, level: level); | ||
| } catch (err) { | ||
| _options.logger( | ||
marandaneto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| SeverityLevel.error, | ||
| 'Error while capturing message with id: ${message}', | ||
| ); | ||
| } | ||
| } else { | ||
| _options.logger( | ||
| SeverityLevel.fatal, | ||
| 'Stack peek was null when captureMessage', | ||
| ); | ||
| } | ||
| } | ||
| _lastEventId = sentryId; | ||
| return sentryId; | ||
| } | ||
|
|
||
| /// Binds a different client to the hub | ||
| void bindClient(SentryClient client) { | ||
| if (!_isEnabled) { | ||
| _options.logger(SeverityLevel.warning, | ||
| "Instance is disabled and this 'bindClient' call is a no-op."); | ||
| } else { | ||
| final item = _stack.first; | ||
| if (item != null) { | ||
| if (client != null) { | ||
| _options.logger(SeverityLevel.debug, 'New client bound to scope.'); | ||
| item.client = client; | ||
| } else { | ||
| _options.logger(SeverityLevel.debug, 'NoOp client bound to scope.'); | ||
| item.client = NoOpSentryClient(); | ||
| } | ||
| } else { | ||
| _options.logger( | ||
| SeverityLevel.fatal, | ||
| 'Stack peek was null when bindClient', | ||
| ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Clones the Hub | ||
| Hub clone() { | ||
| if (!_isEnabled) { | ||
| _options..logger(SeverityLevel.warning, 'Disabled Hub cloned.'); | ||
| } | ||
| final clone = Hub(_options); | ||
| for (final item in _stack) { | ||
| clone._stack.add(_StackItem(item.client, item.scope.clone())); | ||
| } | ||
| return clone; | ||
| } | ||
|
|
||
| /// Flushes out the queue for up to timeout seconds and disable the Hub. | ||
| void close() { | ||
| if (!_isEnabled) { | ||
| _options.logger( | ||
| SeverityLevel.warning, | ||
| "Instance is disabled and this 'close' call is a no-op.", | ||
| ); | ||
| } else { | ||
| final item = _stack.first; | ||
| if (item != null) { | ||
| try { | ||
| item.client.close(); | ||
| } catch (err) { | ||
| _options.logger( | ||
| SeverityLevel.error, | ||
| 'Error while closing the Hub.', | ||
| ); | ||
| } | ||
| } else { | ||
| _options.logger( | ||
| SeverityLevel.fatal, | ||
| 'Stack peek was NULL when closing Hub', | ||
| ); | ||
| } | ||
| _isEnabled = false; | ||
| } | ||
| } | ||
|
|
||
| /// Configures the scope through the callback. | ||
| void configureScope(ScopeCallback callback) { | ||
| if (!_isEnabled) { | ||
| _options.logger( | ||
| SeverityLevel.warning, | ||
| "Instance is disabled and this 'configureScope' call is a no-op.", | ||
| ); | ||
| } else { | ||
| final item = _stack.first; | ||
| if (item != null) { | ||
| try { | ||
| callback(item.scope); | ||
| } catch (err) { | ||
| _options.logger( | ||
| SeverityLevel.error, | ||
| "Error in the 'configureScope' callback.", | ||
| ); | ||
| } | ||
| } else { | ||
| _options.logger( | ||
| SeverityLevel.fatal, | ||
| 'Stack peek was NULL when configureScope', | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| class _StackItem { | ||
| SentryClient client; | ||
|
|
||
| final Scope scope; | ||
|
|
||
| _StackItem(this.client, this.scope); | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.