-
-
Notifications
You must be signed in to change notification settings - Fork 276
Add integration for logging package #631
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
Changes from all commits
e35f77f
a3852fb
5e6f17a
4e8e47c
dc02e35
5ddae9d
74b7cce
020462a
326fe43
4ebcde8
96894a7
820ec00
8d83f84
66c974a
a229695
72b5d2c
dd2f5fa
c905ab2
04c4fcc
0d4805b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,8 @@ on: | |
| branches: | ||
| - main | ||
| pull_request: | ||
| paths-ignore: | ||
| - 'logging/**' | ||
| defaults: | ||
| run: | ||
| shell: bash | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,8 @@ on: | |
| branches: | ||
| - main | ||
| pull_request: | ||
| paths-ignore: | ||
| - 'logging/**' | ||
| defaults: | ||
| run: | ||
| shell: bash | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| name: logging | ||
| on: | ||
| push: | ||
| branches: | ||
| - main | ||
| pull_request: | ||
| defaults: | ||
| run: | ||
| shell: bash | ||
| jobs: | ||
| build: | ||
| name: Build ${{matrix.sdk}} on ${{matrix.os}} | ||
| runs-on: ${{ matrix.os }} | ||
| timeout-minutes: 20 | ||
| defaults: | ||
| run: | ||
| working-directory: ./logging | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| os: [ubuntu-latest, windows-latest, macos-latest] | ||
| sdk: [stable, beta, dev] | ||
| exclude: | ||
| # Bad state: Could not run tests with Observatory enabled. Try setting a different port with --port option. | ||
| - os: ubuntu-latest | ||
| sdk: beta | ||
| # hanging often | ||
| - os: ubuntu-latest | ||
| sdk: dev | ||
| - os: macos-latest | ||
| sdk: beta | ||
| # macos-latest is taking hours due to limited resources | ||
| - os: macos-latest | ||
| sdk: dev | ||
|
|
||
| steps: | ||
| - uses: dart-lang/setup-dart@v1 | ||
| with: | ||
| sdk: ${{ matrix.sdk }} | ||
| - uses: actions/checkout@v2 | ||
| # coverage with 'chrome' platform hangs the build | ||
| - name: Test (VM and browser) | ||
| run: | | ||
| dart pub get | ||
| dart test -p chrome | ||
| dart test -p vm --coverage=coverage | ||
| dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.packages --report-on=lib | ||
|
|
||
| - uses: codecov/codecov-action@v1 | ||
| if: runner.os == 'Linux' | ||
| with: | ||
| name: sentry | ||
| file: ./logging/coverage/lcov.info | ||
|
|
||
| - uses: VeryGoodOpenSource/[email protected] | ||
| if: runner.os == 'Linux' | ||
| with: | ||
| path: "./logging/coverage/lcov.info" | ||
| min_coverage: 90 | ||
|
|
||
| analyze: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
| defaults: | ||
| run: | ||
| working-directory: ./dart | ||
| steps: | ||
| - uses: dart-lang/setup-dart@v1 | ||
| with: | ||
| sdk: stable | ||
| - uses: actions/checkout@v2 | ||
| - run: | | ||
| dart pub get | ||
| dart analyze --fatal-infos | ||
| dart format --set-exit-if-changed ./ | ||
|
|
||
| package-analysis: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
| steps: | ||
| - uses: actions/checkout@v2 | ||
| - uses: axel-op/dart-package-analyzer@v3 | ||
| id: analysis | ||
| with: | ||
| githubToken: ${{ secrets.GITHUB_TOKEN }} | ||
| relativePath: dart/ | ||
| - name: Check scores | ||
| env: | ||
| TOTAL: ${{ steps.analysis.outputs.total }} | ||
| TOTAL_MAX: ${{ steps.analysis.outputs.total_max }} | ||
| run: | | ||
| PERCENTAGE=$(( $TOTAL * 100 / $TOTAL_MAX )) | ||
| if (( $PERCENTAGE < 100 )) | ||
| then | ||
| echo Score too low! | ||
| exit 1 | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # Files and directories created by pub. | ||
| .dart_tool/ | ||
| .packages | ||
|
|
||
| # Conventional directory for build outputs. | ||
| build/ | ||
|
|
||
| # Omit committing pubspec.lock for library packages; see | ||
| # https://dart.dev/guides/libraries/private-files#pubspeclock. | ||
| pubspec.lock |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../CHANGELOG.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| # Sentry integration for `logging` package | ||
| =========== | ||
|
|
||
| <p align="center"> | ||
| <a href="https://sentry.io" target="_blank" align="center"> | ||
| <img src="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" width="280"> | ||
| </a> | ||
| <br /> | ||
| </p> | ||
|
|
||
| | package | build | pub | likes | popularity | pub points | | ||
| | ------- | ------- | ------- | ------- | ------- | ------- | | ||
| | sentry | [](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Alogging) | [](https://pub.dev/packages/sentry_logging) | [](https://pub.dev/packages/sentry_logging/score) | [](https://pub.dev/packages/sentry_logging/score) | [](https://pub.dev/packages/sentry_logging/score) | ||
|
|
||
| Integration for the [`logging`](https://pub.dev/packages/logging) package. | ||
|
|
||
| #### Usage | ||
|
|
||
| - Sign up for a Sentry.io account and get a DSN at http://sentry.io. | ||
|
|
||
| - Follow the installing instructions on [pub.dev](https://pub.dev/packages/sentry/install). | ||
|
|
||
| - Initialize the Sentry SDK using the DSN issued by Sentry.io and add the `LoggingIntegration` | ||
|
|
||
| ```dart | ||
| import 'package:sentry/sentry.dart'; | ||
|
|
||
| Future<void> main() async { | ||
| await Sentry.init( | ||
| (options) { | ||
| options.dsn = 'https://[email protected]/example'; | ||
| options.addIntegration(LoggingIntegration()); | ||
| }, | ||
| appRunner: initApp, // Init your App. | ||
| ); | ||
| } | ||
|
|
||
| void initApp() { | ||
| // your app code | ||
| } | ||
| ``` | ||
|
|
||
| #### Resources | ||
|
|
||
| * [](https://docs.sentry.io/platforms/dart/) | ||
| * [](https://forum.sentry.io/c/sdks) | ||
| * [](https://discord.gg/Ww9hbqr) | ||
| * [](https://stackoverflow.com/questions/tagged/sentry) | ||
| * [](https://twitter.com/intent/follow?screen_name=getsentry) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| include: package:lints/recommended.yaml | ||
|
|
||
| analyzer: | ||
| strong-mode: | ||
| implicit-casts: false | ||
| implicit-dynamic: false | ||
| language: | ||
| strict-raw-types: true | ||
| errors: | ||
| # treat missing required parameters as a warning (not a hint) | ||
| missing_required_param: error | ||
| # treat missing returns as a warning (not a hint) | ||
| missing_return: error | ||
| # allow having TODOs in the code | ||
| todo: ignore | ||
| # allow self-reference to deprecated members (we do this because otherwise we have | ||
| # to annotate every member in every test, assert, etc, when we deprecate something) | ||
| deprecated_member_use_from_same_package: warning | ||
| # ignore sentry/path on pubspec as we change it on deployment | ||
| invalid_dependency: ignore | ||
| exclude: | ||
| - example/** | ||
|
|
||
| linter: | ||
| rules: | ||
| - prefer_final_locals | ||
| - public_member_api_docs | ||
| - prefer_single_quotes | ||
| - prefer_relative_imports | ||
| - unnecessary_brace_in_string_interps | ||
| - implementation_imports | ||
| - require_trailing_commas | ||
| - unawaited_futures |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import 'package:sentry_logging/sentry_logging.dart'; | ||
| import 'dart:async'; | ||
| import 'package:sentry/sentry.dart'; | ||
| import 'package:logging/logging.dart'; | ||
|
|
||
| Future<void> main() async { | ||
| // ATTENTION: Change the DSN below with your own to see the events in Sentry. Get one at sentry.io | ||
| const dsn = | ||
| 'https://[email protected]/5428562'; | ||
|
|
||
| await Sentry.init( | ||
| (options) { | ||
| options.dsn = dsn; | ||
| options.addIntegration(LoggingIntegration()); | ||
| }, | ||
| appRunner: runApp, | ||
| ); | ||
| } | ||
|
|
||
| Future<void> runApp() async { | ||
| final log = Logger('MyAwesomeLogger'); | ||
|
|
||
| log.warning('a warning!'); | ||
|
|
||
| try { | ||
| throw Exception(); | ||
| } catch (error, stackTrace) { | ||
| // The log from above will be contained in this crash report. | ||
| await Sentry.captureException( | ||
| error, | ||
| stackTrace: stackTrace, | ||
| ); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| library sentry_logging; | ||
|
|
||
| export 'src/logging_integration.dart'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| // ignore_for_file: public_member_api_docs | ||
|
|
||
| import 'package:logging/logging.dart'; | ||
| import 'package:sentry/sentry.dart'; | ||
| import 'package:sentry/sentry_io.dart'; | ||
|
|
||
| extension LogRecordX on LogRecord { | ||
| Breadcrumb toBreadcrumb() { | ||
| return Breadcrumb( | ||
| category: 'log', | ||
| type: 'debug', | ||
| timestamp: time, | ||
| level: level.toSentryLevel(), | ||
| message: message, | ||
| data: <String, Object>{ | ||
| if (object != null) 'LogRecord.object': object!, | ||
| if (error != null) 'LogRecord.error': error!, | ||
| if (stackTrace != null) 'LogRecord.stackTrace': stackTrace!, | ||
| 'LogRecord.loggerName': loggerName, | ||
| 'LogRecord.sequenceNumber': sequenceNumber, | ||
| }, | ||
| ); | ||
| } | ||
|
|
||
| SentryEvent toEvent() { | ||
| return SentryEvent( | ||
| logger: loggerName, | ||
| level: level.toSentryLevel(), | ||
| message: SentryMessage(message), | ||
marandaneto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| throwable: error, | ||
| extra: <String, Object>{ | ||
| if (object != null) 'LogRecord.object': object!, | ||
| 'LogRecord.sequenceNumber': sequenceNumber, | ||
| }, | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| extension LogLevelX on Level { | ||
| SentryLevel? toSentryLevel() { | ||
| return <Level, SentryLevel?>{ | ||
| Level.ALL: SentryLevel.debug, | ||
| Level.FINEST: SentryLevel.debug, | ||
| Level.FINER: SentryLevel.debug, | ||
| Level.FINE: SentryLevel.debug, | ||
| Level.CONFIG: SentryLevel.debug, | ||
| Level.INFO: SentryLevel.info, | ||
| Level.WARNING: SentryLevel.warning, | ||
| Level.SEVERE: SentryLevel.error, | ||
| Level.SHOUT: SentryLevel.fatal, | ||
| Level.OFF: null, | ||
| }[this]; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| import 'dart:async'; | ||
|
|
||
| import 'package:logging/logging.dart'; | ||
| import 'package:sentry/sentry.dart'; | ||
| import 'version.dart'; | ||
| import 'extension.dart'; | ||
|
|
||
| /// An [Integration] which listens to all messages of the | ||
| /// [logging](https://pub.dev/packages/logging) package. | ||
| class LoggingIntegration extends Integration<SentryOptions> { | ||
| /// Creates the [LoggingIntegration]. | ||
| /// | ||
| /// All log events equal or higher than [minBreadcrumbLevel] are recorded as a | ||
| /// [Breadcrumb]. | ||
| /// All log events equal or higher than [minEventLevel] are recorded as a | ||
| /// [SentryEvent]. | ||
| LoggingIntegration({ | ||
| Level minBreadcrumbLevel = Level.INFO, | ||
| Level minEventLevel = Level.SEVERE, | ||
| }) : _minBreadcrumbLevel = minBreadcrumbLevel, | ||
| _minEventLevel = minEventLevel; | ||
|
|
||
| final Level _minBreadcrumbLevel; | ||
| final Level _minEventLevel; | ||
| late StreamSubscription<LogRecord> _subscription; | ||
| late Hub _hub; | ||
|
|
||
| @override | ||
| FutureOr<void> call(Hub hub, SentryOptions options) { | ||
| _hub = hub; | ||
| _setSdkVersion(options); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ueman @marandaneto Should the SDK version be set here? This reports
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it also report
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From what I understand, this is called only once when the integration is registered and overrides the original SDK.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this should not be set https://github.com/getsentry/sentry-dart/blob/main/logging/lib/src/logging_integration.dart#L49-L50 |
||
| _subscription = Logger.root.onRecord.listen( | ||
| _onLog, | ||
| onError: (Object error, StackTrace stackTrace) async { | ||
| await _hub.captureException(error, stackTrace: stackTrace); | ||
| }, | ||
| ); | ||
| options.sdk.addIntegration('LoggingIntegration'); | ||
| } | ||
|
|
||
| @override | ||
| Future<void> close() async { | ||
| await super.close(); | ||
| await _subscription.cancel(); | ||
| } | ||
|
|
||
| void _setSdkVersion(SentryOptions options) { | ||
| final sdk = SdkVersion( | ||
| name: sdkName, | ||
| version: sdkVersion, | ||
| integrations: options.sdk.integrations, | ||
| packages: options.sdk.packages, | ||
| ); | ||
| sdk.addPackage('pub:sentry_logging', sdkVersion); | ||
| options.sdk = sdk; | ||
| } | ||
|
|
||
| bool _isLoggable(Level logLevel, Level minLevel) { | ||
| return logLevel >= minLevel; | ||
| } | ||
|
|
||
| void _onLog(LogRecord record) async { | ||
| // The event must be logged first, otherwise the log would also be added | ||
| // to the breadcrumbs for itself. | ||
| if (_isLoggable(record.level, _minEventLevel)) { | ||
| await _hub.captureEvent( | ||
| record.toEvent(), | ||
| stackTrace: record.stackTrace, | ||
| ); | ||
| } | ||
|
|
||
| if (_isLoggable(record.level, _minBreadcrumbLevel)) { | ||
| _hub.addBreadcrumb(record.toBreadcrumb()); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| /// The SDK version reported to Sentry.io in the submitted events. | ||
| const String sdkVersion = '6.2.0'; | ||
|
|
||
| /// The default SDK name reported to Sentry.io in the submitted events. | ||
| const String sdkName = 'sentry.dart.logging'; |
Uh oh!
There was an error while loading. Please reload this page.