From e35f77f1f4c8e4b2c48556650a6c3c5cad260fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 8 Nov 2021 18:58:02 +0100 Subject: [PATCH 01/19] Logging Integration --- sentry_logging/.gitignore | 10 ++ sentry_logging/CHANGELOG.md | 3 + sentry_logging/README.md | 1 + sentry_logging/analysis_options.yaml | 32 +++++ .../example/sentry_logging_example.dart | 34 +++++ sentry_logging/lib/sentry_logging.dart | 3 + sentry_logging/lib/src/extension.dart | 54 ++++++++ .../lib/src/logging_integration.dart | 58 ++++++++ sentry_logging/pubspec.yaml | 16 +++ sentry_logging/test/extension_test.dart | 0 .../test/logging_integration_test.dart | 97 +++++++++++++ sentry_logging/test/mock_hub.dart | 130 ++++++++++++++++++ 12 files changed, 438 insertions(+) create mode 100644 sentry_logging/.gitignore create mode 100644 sentry_logging/CHANGELOG.md create mode 100644 sentry_logging/README.md create mode 100644 sentry_logging/analysis_options.yaml create mode 100644 sentry_logging/example/sentry_logging_example.dart create mode 100644 sentry_logging/lib/sentry_logging.dart create mode 100644 sentry_logging/lib/src/extension.dart create mode 100644 sentry_logging/lib/src/logging_integration.dart create mode 100644 sentry_logging/pubspec.yaml create mode 100644 sentry_logging/test/extension_test.dart create mode 100644 sentry_logging/test/logging_integration_test.dart create mode 100644 sentry_logging/test/mock_hub.dart diff --git a/sentry_logging/.gitignore b/sentry_logging/.gitignore new file mode 100644 index 0000000000..65c34dc86e --- /dev/null +++ b/sentry_logging/.gitignore @@ -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 diff --git a/sentry_logging/CHANGELOG.md b/sentry_logging/CHANGELOG.md new file mode 100644 index 0000000000..effe43c82c --- /dev/null +++ b/sentry_logging/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version. diff --git a/sentry_logging/README.md b/sentry_logging/README.md new file mode 100644 index 0000000000..1a1aebed6a --- /dev/null +++ b/sentry_logging/README.md @@ -0,0 +1 @@ +# WIP \ No newline at end of file diff --git a/sentry_logging/analysis_options.yaml b/sentry_logging/analysis_options.yaml new file mode 100644 index 0000000000..b49dc0f505 --- /dev/null +++ b/sentry_logging/analysis_options.yaml @@ -0,0 +1,32 @@ +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 \ No newline at end of file diff --git a/sentry_logging/example/sentry_logging_example.dart b/sentry_logging/example/sentry_logging_example.dart new file mode 100644 index 0000000000..abfb09d89b --- /dev/null +++ b/sentry_logging/example/sentry_logging_example.dart @@ -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 main() async { + // ATTENTION: Change the DSN below with your own to see the events in Sentry. Get one at sentry.io + const dsn = + 'https://9934c532bf8446ef961450973c898537@o447951.ingest.sentry.io/5428562'; + + await Sentry.init( + (options) { + options.dsn = dsn; + options.addIntegration(LoggingIntegration()); + }, + appRunner: runApp, + ); +} + +Future 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, + ); + } +} diff --git a/sentry_logging/lib/sentry_logging.dart b/sentry_logging/lib/sentry_logging.dart new file mode 100644 index 0000000000..9b56c3f433 --- /dev/null +++ b/sentry_logging/lib/sentry_logging.dart @@ -0,0 +1,3 @@ +library sentry_logging; + +export 'src/logging_integration.dart'; diff --git a/sentry_logging/lib/src/extension.dart b/sentry_logging/lib/src/extension.dart new file mode 100644 index 0000000000..3bfebc4bc9 --- /dev/null +++ b/sentry_logging/lib/src/extension.dart @@ -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: { + if (object != null) 'LogRecord.object': object!.toString(), + if (error != null) 'LogRecord.error': error!.toString(), + if (stackTrace != null) 'LogRecord.stackTrace': stackTrace!.toString(), + 'LogRecord.loggerName': loggerName, + 'LogRecord.sequenceNumber': sequenceNumber, + }, + ); + } + + SentryEvent toEvent() { + return SentryEvent( + logger: loggerName, + level: level.toSentryLevel(), + message: SentryMessage(message), + throwable: error, + extra: { + if (object != null) 'LogRecord.object': object!, + 'LogRecord.sequenceNumber': sequenceNumber, + }, + ); + } +} + +extension LogLevelX on Level { + SentryLevel? toSentryLevel() { + return { + 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]; + } +} diff --git a/sentry_logging/lib/src/logging_integration.dart b/sentry_logging/lib/src/logging_integration.dart new file mode 100644 index 0000000000..924166b089 --- /dev/null +++ b/sentry_logging/lib/src/logging_integration.dart @@ -0,0 +1,58 @@ +import 'dart:async'; + +import 'package:logging/logging.dart'; +import 'package:sentry/sentry.dart'; +import 'extension.dart'; + +/// An [Integration] which listens to all messages of the +/// [logging](https://pub.dev/packages/logging) package. +class LoggingIntegration extends Integration { + /// Creates the [LoggingIntegration]. + /// + /// Setting [logExceptionAsEvent] to true (default) captures all + /// messages with errors as an [SentryEvent] instead of an [Breadcrumb]. + /// Setting [logExceptionAsEvent] to false captures everything as + /// [Breadcrumb]s. + LoggingIntegration({bool logExceptionAsEvent = true}) + : _logExceptionsAsEvents = logExceptionAsEvent; + + final bool _logExceptionsAsEvents; + late StreamSubscription _subscription; + late Hub _hub; + + @override + FutureOr call(Hub hub, SentryOptions options) { + _hub = hub; + _subscription = Logger.root.onRecord.listen( + _onLog, + onError: (Object error, StackTrace stackTrace) { + _hub.captureException(error, stackTrace: stackTrace); + }, + ); + options.sdk.addIntegration('LoggingIntegration'); + } + + @override + Future close() async { + await super.close(); + await _subscription.cancel(); + } + + void _onLog(LogRecord record) { + // Everything is just logged as a breadcrumb + if (!_logExceptionsAsEvents) { + _hub.addBreadcrumb(record.toBreadcrumb()); + return; + } + + // If a LogRecord contains an exception, it gets reported as an SentryEvent + if (record.error == null) { + _hub.addBreadcrumb(record.toBreadcrumb()); + } else { + _hub.captureEvent( + record.toEvent(), + stackTrace: record.stackTrace, + ); + } + } +} diff --git a/sentry_logging/pubspec.yaml b/sentry_logging/pubspec.yaml new file mode 100644 index 0000000000..627c1eb8cb --- /dev/null +++ b/sentry_logging/pubspec.yaml @@ -0,0 +1,16 @@ +name: sentry_logging +description: An integration which adds support for recording log from the logging package. +version: 1.0.0 +homepage: https://docs.sentry.io/platforms/flutter/ +repository: https://github.com/getsentry/sentry-dart + +environment: + sdk: '>=2.14.4 <3.0.0' + +dependencies: + logging: ^1.0.0 + sentry: ^6.1.0 + +dev_dependencies: + lints: ^1.0.0 + test: ^1.16.0 diff --git a/sentry_logging/test/extension_test.dart b/sentry_logging/test/extension_test.dart new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sentry_logging/test/logging_integration_test.dart b/sentry_logging/test/logging_integration_test.dart new file mode 100644 index 0000000000..2f0183ac08 --- /dev/null +++ b/sentry_logging/test/logging_integration_test.dart @@ -0,0 +1,97 @@ +import 'package:logging/logging.dart'; +import 'package:sentry/sentry.dart'; +import 'package:sentry_logging/sentry_logging.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; + +import 'mock_hub.dart'; + +void main() { + late Fixture fixture; + setUp(() { + fixture = Fixture(); + }); + + test('options.sdk.integrations contains $LoggingIntegration', () async { + final sut = fixture.createSut(); + await sut.call(fixture.hub, fixture.options); + await sut.close(); + expect( + fixture.options.sdk.integrations.contains('LoggingIntegration'), + true, + ); + }); + + test('logger gets recorded', () async { + final sut = fixture.createSut(); + await sut.call(fixture.hub, fixture.options); + + final log = Logger('FooBarLogger'); + log.warning( + 'A log message', + ); + + expect(fixture.hub.events.length, 0); + expect(fixture.hub.breadcrumbs.length, 1); + final crumb = fixture.hub.breadcrumbs.first; + expect(crumb.level, SentryLevel.warning); + expect(crumb.message, 'A log message'); + expect(crumb.data, { + 'LogRecord.loggerName': 'FooBarLogger', + 'LogRecord.sequenceNumber': 0, + }); + expect(crumb.timestamp, isNotNull); + expect(crumb.category, 'log'); + expect(crumb.type, 'debug'); + }); + + test('exceptions is recorded as breadcrumb if logExceptionsAsEvents = false', + () async { + final sut = fixture.createSut(logExceptionsAsEvents: false); + await sut.call(fixture.hub, fixture.options); + + final log = Logger('FooBarLogger'); + log.warning( + 'A log message', + Exception('foo bar'), + StackTrace.current, + ); + expect(fixture.hub.events.length, 0); + expect(fixture.hub.breadcrumbs.length, 1); + final crumb = fixture.hub.breadcrumbs.first; + expect(crumb.data?.length, 4); + }); + + test('exceptions is recorded as event if logExceptionsAsEvents = true', + () async { + final sut = fixture.createSut(logExceptionsAsEvents: true); + await sut.call(fixture.hub, fixture.options); + + final exception = Exception('foo bar'); + final stackTrace = StackTrace.current; + + final log = Logger('FooBarLogger'); + log.warning( + 'A log message', + exception, + stackTrace, + ); + expect(fixture.hub.breadcrumbs.length, 0); + expect(fixture.hub.events.length, 1); + final event = fixture.hub.events.first.event; + expect(event.level, SentryLevel.warning); + expect(event.logger, 'FooBarLogger'); + expect(event.throwable, exception); + expect(event.extra?['LogRecord.sequenceNumber'], isNotNull); + expect(fixture.hub.events.first.stackTrace, stackTrace); + }); +} + +class Fixture { + SentryOptions options = SentryOptions(dsn: fakeDsn); + MockHub hub = MockHub(); + + LoggingIntegration createSut({bool logExceptionsAsEvents = true}) { + return LoggingIntegration(logExceptionAsEvent: logExceptionsAsEvents); + } +} diff --git a/sentry_logging/test/mock_hub.dart b/sentry_logging/test/mock_hub.dart new file mode 100644 index 0000000000..0368eda24e --- /dev/null +++ b/sentry_logging/test/mock_hub.dart @@ -0,0 +1,130 @@ +import 'package:sentry/sentry.dart'; + +final fakeDsn = 'https://abc@def.ingest.sentry.io/1234567'; + +class MockHub implements Hub { + final List breadcrumbs = []; + final List events = []; + + @override + void addBreadcrumb(Breadcrumb crumb, {dynamic hint}) { + breadcrumbs.add(crumb); + } + + @override + Future captureEvent( + SentryEvent event, { + dynamic stackTrace, + dynamic hint, + ScopeCallback? withScope, + }) async { + events.add(CapturedEvents(event, stackTrace)); + return SentryId.newId(); + } + + // everything below is not needed + + @override + void bindClient(SentryClient client) {} + + @override + Future captureException( + dynamic throwable, { + dynamic stackTrace, + dynamic hint, + ScopeCallback? withScope, + }) { + // TODO: implement captureException + throw UnimplementedError(); + } + + @override + Future captureMessage( + String? message, { + SentryLevel? level, + String? template, + List? params, + dynamic hint, + ScopeCallback? withScope, + }) { + // TODO: implement captureMessage + throw UnimplementedError(); + } + + @override + Future captureTransaction(SentryTransaction transaction) { + // TODO: implement captureTransaction + throw UnimplementedError(); + } + + @override + Future captureUserFeedback(SentryUserFeedback userFeedback) { + // TODO: implement captureUserFeedback + throw UnimplementedError(); + } + + @override + Hub clone() { + // TODO: implement clone + throw UnimplementedError(); + } + + @override + Future close() { + // TODO: implement close + throw UnimplementedError(); + } + + @override + void configureScope(ScopeCallback callback) { + // TODO: implement configureScope + } + + @override + ISentrySpan? getSpan() { + // TODO: implement getSpan + throw UnimplementedError(); + } + + @override + // TODO: implement isEnabled + bool get isEnabled => throw UnimplementedError(); + + @override + // TODO: implement lastEventId + SentryId get lastEventId => throw UnimplementedError(); + + @override + void setSpanContext( + dynamic throwable, + ISentrySpan span, + String transaction, + ) {} + + @override + ISentrySpan startTransaction( + String name, + String operation, { + String? description, + bool? bindToScope, + Map? customSamplingContext, + }) { + throw UnimplementedError(); + } + + @override + ISentrySpan startTransactionWithContext( + SentryTransactionContext transactionContext, { + Map? customSamplingContext, + bool? bindToScope, + }) { + throw UnimplementedError(); + } +} + +class CapturedEvents { + CapturedEvents(this.event, this.stackTrace); + + final SentryEvent event; + final dynamic stackTrace; +} From a3852fb1376e3d5f2efa0f5b6cb44df8a97af9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 8 Nov 2021 19:06:11 +0100 Subject: [PATCH 02/19] CI --- .github/workflows/logging.yml | 97 +++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 .github/workflows/logging.yml diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml new file mode 100644 index 0000000000..16e112039e --- /dev/null +++ b/.github/workflows/logging.yml @@ -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: ./sentry-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: ./sentry_logging/coverage/lcov.info + + - uses: VeryGoodOpenSource/very_good_coverage@v1.1.1 + if: runner.os == 'Linux' + with: + path: "./sentry_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 From 5e6f17a47753bafb013a04d37cadc887da8350d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Tue, 9 Nov 2021 20:24:06 +0100 Subject: [PATCH 03/19] Readme --- sentry_logging/README.md | 50 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/sentry_logging/README.md b/sentry_logging/README.md index 1a1aebed6a..9a497a8184 100644 --- a/sentry_logging/README.md +++ b/sentry_logging/README.md @@ -1 +1,49 @@ -# WIP \ No newline at end of file +# Sentry integration for `logging` package +=========== + +

+ + + +
+

+ +| package | build | pub | likes | popularity | pub points | +| ------- | ------- | ------- | ------- | ------- | ------- | +| sentry | [![build](https://github.com/getsentry/sentry-dart/workflows/logging/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Alogging) | [![pub package](https://img.shields.io/pub/v/sentry_logging.svg)](https://pub.dev/packages/sentry_logging) | [![likes](https://badges.bar/sentry_logging/likes)](https://pub.dev/packages/sentry_logging/score) | [![popularity](https://badges.bar/sentry_logging/popularity)](https://pub.dev/packages/sentry_logging/score) | [![pub points](https://badges.bar/sentry_logging/pub%20points)](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 main() async { + await Sentry.init( + (options) { + options.dsn = 'https://example@sentry.io/example'; + options.addIntegration(LoggingIntegration()); + }, + appRunner: initApp, // Init your App. + ); +} + +void initApp() { + // your app code +} +``` + +#### Resources + +* [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/dart/) +* [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks) +* [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +* [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) +* [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) \ No newline at end of file From 4e8e47cce2462a60ce048f4afcacaecf8a599164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Tue, 9 Nov 2021 20:29:26 +0100 Subject: [PATCH 04/19] fix path --- .github/workflows/logging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 16e112039e..e1dacd23aa 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -14,7 +14,7 @@ jobs: timeout-minutes: 20 defaults: run: - working-directory: ./sentry-logging + working-directory: ./sentry_logging strategy: fail-fast: false matrix: From dc02e35213917a77a8840b4b139d4a6e1d5ff9ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Tue, 9 Nov 2021 20:31:25 +0100 Subject: [PATCH 05/19] only build logging when necessary --- .github/workflows/logging.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index e1dacd23aa..03fe966f46 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -4,6 +4,17 @@ on: branches: - main pull_request: +on: + push: + branches: + - main + paths: + - "sentry_logging/**" + - ".github/workflows/logging.yml" + pull_request: + paths: + - "sentry_logging/**" + - ".github/workflows/logging.yml" defaults: run: shell: bash From 5ddae9d83c706c7c54925c637c1453811fae9986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Fri, 19 Nov 2021 15:05:26 +0100 Subject: [PATCH 06/19] Update sentry_logging/pubspec.yaml Co-authored-by: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com> --- sentry_logging/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_logging/pubspec.yaml b/sentry_logging/pubspec.yaml index 627c1eb8cb..e2883b613e 100644 --- a/sentry_logging/pubspec.yaml +++ b/sentry_logging/pubspec.yaml @@ -5,7 +5,7 @@ homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart environment: - sdk: '>=2.14.4 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: logging: ^1.0.0 From 74b7cce56849b2db960f2ff003a09275e46565af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Fri, 19 Nov 2021 15:13:10 +0100 Subject: [PATCH 07/19] Update sentry_logging/pubspec.yaml Co-authored-by: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com> --- sentry_logging/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_logging/pubspec.yaml b/sentry_logging/pubspec.yaml index e2883b613e..585f6a2078 100644 --- a/sentry_logging/pubspec.yaml +++ b/sentry_logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 1.0.0 +version: 6.2.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart From 020462acd4e309c9dc1250f78d6571d272ef2e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 22 Nov 2021 20:54:32 +0100 Subject: [PATCH 08/19] always build --- .github/workflows/logging.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 03fe966f46..903860996c 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -8,13 +8,6 @@ on: push: branches: - main - paths: - - "sentry_logging/**" - - ".github/workflows/logging.yml" - pull_request: - paths: - - "sentry_logging/**" - - ".github/workflows/logging.yml" defaults: run: shell: bash From 326fe43953fc7ee20a6c613110ff554c8bce1018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 22 Nov 2021 20:54:52 +0100 Subject: [PATCH 09/19] pr feedback --- .../lib/src/logging_integration.dart | 44 ++++++++++---- sentry_logging/lib/src/version.dart | 5 ++ sentry_logging/pubspec.yaml | 1 + sentry_logging/test/extension_test.dart | 0 .../test/logging_integration_test.dart | 60 ++++++++++++++----- sentry_logging/test/version_test.dart | 19 ++++++ 6 files changed, 102 insertions(+), 27 deletions(-) create mode 100644 sentry_logging/lib/src/version.dart delete mode 100644 sentry_logging/test/extension_test.dart create mode 100644 sentry_logging/test/version_test.dart diff --git a/sentry_logging/lib/src/logging_integration.dart b/sentry_logging/lib/src/logging_integration.dart index 924166b089..42287328b7 100644 --- a/sentry_logging/lib/src/logging_integration.dart +++ b/sentry_logging/lib/src/logging_integration.dart @@ -2,6 +2,7 @@ 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 @@ -13,16 +14,21 @@ class LoggingIntegration extends Integration { /// messages with errors as an [SentryEvent] instead of an [Breadcrumb]. /// Setting [logExceptionAsEvent] to false captures everything as /// [Breadcrumb]s. - LoggingIntegration({bool logExceptionAsEvent = true}) - : _logExceptionsAsEvents = logExceptionAsEvent; + LoggingIntegration({ + Level minBreadcrumbLevel = Level.INFO, + Level minEventLevel = Level.SEVERE, + }) : _minBreadcrumbLevel = minBreadcrumbLevel, + _minEventLevel = minEventLevel; - final bool _logExceptionsAsEvents; + final Level _minBreadcrumbLevel; + final Level _minEventLevel; late StreamSubscription _subscription; late Hub _hub; @override FutureOr call(Hub hub, SentryOptions options) { _hub = hub; + _setSdkVersion(options); _subscription = Logger.root.onRecord.listen( _onLog, onError: (Object error, StackTrace stackTrace) { @@ -38,21 +44,33 @@ class LoggingIntegration extends Integration { await _subscription.cancel(); } - void _onLog(LogRecord record) { - // Everything is just logged as a breadcrumb - if (!_logExceptionsAsEvents) { - _hub.addBreadcrumb(record.toBreadcrumb()); - return; - } + 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; + } - // If a LogRecord contains an exception, it gets reported as an SentryEvent - if (record.error == null) { - _hub.addBreadcrumb(record.toBreadcrumb()); - } else { + bool _isLoggable(Level logLevel, Level minLevel) { + return logLevel > minLevel; + } + + void _onLog(LogRecord record) { + // The event must be logged first, otherwise the log would also be added + // to the breadcrumbs for itself. + if (_isLoggable(record.level, _minEventLevel)) { _hub.captureEvent( record.toEvent(), stackTrace: record.stackTrace, ); } + + if (_isLoggable(record.level, _minBreadcrumbLevel)) { + _hub.addBreadcrumb(record.toBreadcrumb()); + } } } diff --git a/sentry_logging/lib/src/version.dart b/sentry_logging/lib/src/version.dart new file mode 100644 index 0000000000..59c029d25d --- /dev/null +++ b/sentry_logging/lib/src/version.dart @@ -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.sentry_logging'; diff --git a/sentry_logging/pubspec.yaml b/sentry_logging/pubspec.yaml index 585f6a2078..6a5685656c 100644 --- a/sentry_logging/pubspec.yaml +++ b/sentry_logging/pubspec.yaml @@ -14,3 +14,4 @@ dependencies: dev_dependencies: lints: ^1.0.0 test: ^1.16.0 + yaml: ^3.1.0 # needed for version match (code and pubspec) diff --git a/sentry_logging/test/extension_test.dart b/sentry_logging/test/extension_test.dart deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/sentry_logging/test/logging_integration_test.dart b/sentry_logging/test/logging_integration_test.dart index 2f0183ac08..797825d69f 100644 --- a/sentry_logging/test/logging_integration_test.dart +++ b/sentry_logging/test/logging_integration_test.dart @@ -1,6 +1,7 @@ import 'package:logging/logging.dart'; import 'package:sentry/sentry.dart'; import 'package:sentry_logging/sentry_logging.dart'; +import 'package:sentry_logging/src/version.dart'; import 'package:test/expect.dart'; import 'package:test/scaffolding.dart'; @@ -22,9 +23,21 @@ void main() { ); }); - test('logger gets recorded', () async { + test('options.sdk.integrations contains version', () async { final sut = fixture.createSut(); await sut.call(fixture.hub, fixture.options); + await sut.close(); + + expect(fixture.options.sdk.name, sdkName); + final package = fixture.options.sdk.packages + .firstWhere((it) => it.name == 'pub:sentry_logging'); + expect(package.name, 'pub:sentry_logging'); + expect(package.version, sdkVersion); + }); + + test('logger gets recorded if level over minlevel', () async { + final sut = fixture.createSut(minBreadcrumbLevel: Level.CONFIG); + await sut.call(fixture.hub, fixture.options); final log = Logger('FooBarLogger'); log.warning( @@ -45,26 +58,22 @@ void main() { expect(crumb.type, 'debug'); }); - test('exceptions is recorded as breadcrumb if logExceptionsAsEvents = false', - () async { - final sut = fixture.createSut(logExceptionsAsEvents: false); + test('logger gets not recorded if level under minlevel', () async { + final sut = fixture.createSut(minBreadcrumbLevel: Level.SEVERE); await sut.call(fixture.hub, fixture.options); final log = Logger('FooBarLogger'); log.warning( 'A log message', - Exception('foo bar'), - StackTrace.current, ); + expect(fixture.hub.events.length, 0); - expect(fixture.hub.breadcrumbs.length, 1); - final crumb = fixture.hub.breadcrumbs.first; - expect(crumb.data?.length, 4); + expect(fixture.hub.breadcrumbs.length, 0); }); - test('exceptions is recorded as event if logExceptionsAsEvents = true', + test('exception is recorded as event if minEventLevel over minlevel', () async { - final sut = fixture.createSut(logExceptionsAsEvents: true); + final sut = fixture.createSut(minEventLevel: Level.INFO); await sut.call(fixture.hub, fixture.options); final exception = Exception('foo bar'); @@ -76,8 +85,8 @@ void main() { exception, stackTrace, ); - expect(fixture.hub.breadcrumbs.length, 0); expect(fixture.hub.events.length, 1); + expect(fixture.hub.events.first.event.breadcrumbs, null); final event = fixture.hub.events.first.event; expect(event.level, SentryLevel.warning); expect(event.logger, 'FooBarLogger'); @@ -85,13 +94,36 @@ void main() { expect(event.extra?['LogRecord.sequenceNumber'], isNotNull); expect(fixture.hub.events.first.stackTrace, stackTrace); }); + + test('exception is not recorded as event if minEventLevel under minlevel', + () async { + final sut = fixture.createSut(minEventLevel: Level.SEVERE); + await sut.call(fixture.hub, fixture.options); + + final exception = Exception('foo bar'); + final stackTrace = StackTrace.current; + + final log = Logger('FooBarLogger'); + log.warning( + 'A log message', + exception, + stackTrace, + ); + expect(fixture.hub.events.length, 0); + }); } class Fixture { SentryOptions options = SentryOptions(dsn: fakeDsn); MockHub hub = MockHub(); - LoggingIntegration createSut({bool logExceptionsAsEvents = true}) { - return LoggingIntegration(logExceptionAsEvent: logExceptionsAsEvents); + LoggingIntegration createSut({ + Level minBreadcrumbLevel = Level.INFO, + Level minEventLevel = Level.SEVERE, + }) { + return LoggingIntegration( + minBreadcrumbLevel: minBreadcrumbLevel, + minEventLevel: minEventLevel, + ); } } diff --git a/sentry_logging/test/version_test.dart b/sentry_logging/test/version_test.dart new file mode 100644 index 0000000000..509e313c23 --- /dev/null +++ b/sentry_logging/test/version_test.dart @@ -0,0 +1,19 @@ +@TestOn('vm') + +import 'dart:io'; + +import 'package:sentry_logging/src/version.dart'; +import 'package:test/test.dart'; +import 'package:yaml/yaml.dart' as yaml; + +void main() { + test( + 'sdkVersion matches that of pubspec.yaml', + () { + final dynamic pubspec = + yaml.loadYaml(File('pubspec.yaml').readAsStringSync()); + expect(sdkVersion, pubspec['version']); + }, + skip: 'works locally but not on CI', + ); +} From 4ebcde8e9390dc530c0543de38f75187ac83dab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 22 Nov 2021 21:01:23 +0100 Subject: [PATCH 10/19] don't build dart/flutter if just logging is changed --- .github/workflows/dart.yml | 2 ++ .github/workflows/flutter.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index be334bad54..30aaae3b84 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -4,6 +4,8 @@ on: branches: - main pull_request: + paths-ignore: + - 'sentry_logging/**' defaults: run: shell: bash diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index dbabca418b..116486e7c7 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -4,6 +4,8 @@ on: branches: - main pull_request: + paths-ignore: + - 'sentry_logging/**' defaults: run: shell: bash From 96894a7ad385582943612bfa552f47d4ebe7e83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 22 Nov 2021 21:28:22 +0100 Subject: [PATCH 11/19] fix ci --- .github/workflows/logging.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 903860996c..e1dacd23aa 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -4,10 +4,6 @@ on: branches: - main pull_request: -on: - push: - branches: - - main defaults: run: shell: bash From 820ec00aa1eb43a4c8864ab9f460eee008cdf263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Mon, 22 Nov 2021 21:32:53 +0100 Subject: [PATCH 12/19] fix coverage --- sentry_logging/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/sentry_logging/pubspec.yaml b/sentry_logging/pubspec.yaml index 6a5685656c..a65d2e9889 100644 --- a/sentry_logging/pubspec.yaml +++ b/sentry_logging/pubspec.yaml @@ -15,3 +15,4 @@ dev_dependencies: lints: ^1.0.0 test: ^1.16.0 yaml: ^3.1.0 # needed for version match (code and pubspec) + coverage: ^1.0.3 From 8d83f844f9ada95ce1003a74e2379f02c614661d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Tue, 23 Nov 2021 08:02:24 +0100 Subject: [PATCH 13/19] Update sentry_logging/CHANGELOG.md --- sentry_logging/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_logging/CHANGELOG.md b/sentry_logging/CHANGELOG.md index effe43c82c..65aa1d5afa 100644 --- a/sentry_logging/CHANGELOG.md +++ b/sentry_logging/CHANGELOG.md @@ -1,3 +1,3 @@ -## 1.0.0 +## 6.2.0 - Initial version. From 66c974ae905de4b7fe4530f3ad41d7840a141a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Tue, 23 Nov 2021 10:35:26 +0100 Subject: [PATCH 14/19] Update sentry_logging/lib/src/version.dart Co-authored-by: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com> --- sentry_logging/lib/src/version.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_logging/lib/src/version.dart b/sentry_logging/lib/src/version.dart index 59c029d25d..c3e59be25c 100644 --- a/sentry_logging/lib/src/version.dart +++ b/sentry_logging/lib/src/version.dart @@ -2,4 +2,4 @@ const String sdkVersion = '6.2.0'; /// The default SDK name reported to Sentry.io in the submitted events. -const String sdkName = 'sentry.dart.sentry_logging'; +const String sdkName = 'sentry.dart.logging'; From a229695f3dba2032ee092f0b45fae31fe7ed2ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Tue, 23 Nov 2021 20:10:04 +0100 Subject: [PATCH 15/19] use async await --- sentry_logging/analysis_options.yaml | 3 ++- sentry_logging/lib/src/logging_integration.dart | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sentry_logging/analysis_options.yaml b/sentry_logging/analysis_options.yaml index b49dc0f505..f80d2938b0 100644 --- a/sentry_logging/analysis_options.yaml +++ b/sentry_logging/analysis_options.yaml @@ -29,4 +29,5 @@ linter: - prefer_relative_imports - unnecessary_brace_in_string_interps - implementation_imports - - require_trailing_commas \ No newline at end of file + - require_trailing_commas + - unawaited_futures \ No newline at end of file diff --git a/sentry_logging/lib/src/logging_integration.dart b/sentry_logging/lib/src/logging_integration.dart index 42287328b7..29d82985d2 100644 --- a/sentry_logging/lib/src/logging_integration.dart +++ b/sentry_logging/lib/src/logging_integration.dart @@ -31,8 +31,8 @@ class LoggingIntegration extends Integration { _setSdkVersion(options); _subscription = Logger.root.onRecord.listen( _onLog, - onError: (Object error, StackTrace stackTrace) { - _hub.captureException(error, stackTrace: stackTrace); + onError: (Object error, StackTrace stackTrace) async { + await _hub.captureException(error, stackTrace: stackTrace); }, ); options.sdk.addIntegration('LoggingIntegration'); @@ -59,11 +59,11 @@ class LoggingIntegration extends Integration { return logLevel > minLevel; } - void _onLog(LogRecord record) { + 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)) { - _hub.captureEvent( + await _hub.captureEvent( record.toEvent(), stackTrace: record.stackTrace, ); From 72b5d2c6768141ed82263a70b10470f12968400d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Tue, 23 Nov 2021 20:18:37 +0100 Subject: [PATCH 16/19] remove to string --- sentry_logging/lib/src/extension.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sentry_logging/lib/src/extension.dart b/sentry_logging/lib/src/extension.dart index 3bfebc4bc9..af98344f4a 100644 --- a/sentry_logging/lib/src/extension.dart +++ b/sentry_logging/lib/src/extension.dart @@ -13,9 +13,9 @@ extension LogRecordX on LogRecord { level: level.toSentryLevel(), message: message, data: { - if (object != null) 'LogRecord.object': object!.toString(), - if (error != null) 'LogRecord.error': error!.toString(), - if (stackTrace != null) 'LogRecord.stackTrace': stackTrace!.toString(), + if (object != null) 'LogRecord.object': object!, + if (error != null) 'LogRecord.error': error!, + if (stackTrace != null) 'LogRecord.stackTrace': stackTrace!, 'LogRecord.loggerName': loggerName, 'LogRecord.sequenceNumber': sequenceNumber, }, From dd2f5fa951be1d1a33202abfc678d73f098081a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sat, 27 Nov 2021 13:56:39 +0100 Subject: [PATCH 17/19] Rename folder to logging + symlink changelog --- .github/workflows/dart.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/logging.yml | 6 +++--- CHANGELOG.md | 2 ++ {sentry_logging => logging}/.gitignore | 0 logging/CHANGELOG.md | 1 + {sentry_logging => logging}/README.md | 0 {sentry_logging => logging}/analysis_options.yaml | 0 .../example/sentry_logging_example.dart | 0 {sentry_logging => logging}/lib/sentry_logging.dart | 0 {sentry_logging => logging}/lib/src/extension.dart | 0 .../lib/src/logging_integration.dart | 0 {sentry_logging => logging}/lib/src/version.dart | 0 {sentry_logging => logging}/pubspec.yaml | 0 .../test/logging_integration_test.dart | 0 {sentry_logging => logging}/test/mock_hub.dart | 0 {sentry_logging => logging}/test/version_test.dart | 0 sentry_logging/CHANGELOG.md | 3 --- 18 files changed, 8 insertions(+), 8 deletions(-) rename {sentry_logging => logging}/.gitignore (100%) create mode 120000 logging/CHANGELOG.md rename {sentry_logging => logging}/README.md (100%) rename {sentry_logging => logging}/analysis_options.yaml (100%) rename {sentry_logging => logging}/example/sentry_logging_example.dart (100%) rename {sentry_logging => logging}/lib/sentry_logging.dart (100%) rename {sentry_logging => logging}/lib/src/extension.dart (100%) rename {sentry_logging => logging}/lib/src/logging_integration.dart (100%) rename {sentry_logging => logging}/lib/src/version.dart (100%) rename {sentry_logging => logging}/pubspec.yaml (100%) rename {sentry_logging => logging}/test/logging_integration_test.dart (100%) rename {sentry_logging => logging}/test/mock_hub.dart (100%) rename {sentry_logging => logging}/test/version_test.dart (100%) delete mode 100644 sentry_logging/CHANGELOG.md diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 30aaae3b84..5af8c077ca 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -5,7 +5,7 @@ on: - main pull_request: paths-ignore: - - 'sentry_logging/**' + - 'logging/**' defaults: run: shell: bash diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 116486e7c7..beacbab857 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -5,7 +5,7 @@ on: - main pull_request: paths-ignore: - - 'sentry_logging/**' + - 'logging/**' defaults: run: shell: bash diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index e1dacd23aa..e749cb2ac3 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -14,7 +14,7 @@ jobs: timeout-minutes: 20 defaults: run: - working-directory: ./sentry_logging + working-directory: ./logging strategy: fail-fast: false matrix: @@ -50,12 +50,12 @@ jobs: if: runner.os == 'Linux' with: name: sentry - file: ./sentry_logging/coverage/lcov.info + file: ./logging/coverage/lcov.info - uses: VeryGoodOpenSource/very_good_coverage@v1.1.1 if: runner.os == 'Linux' with: - path: "./sentry_logging/coverage/lcov.info" + path: "./logging/coverage/lcov.info" min_coverage: 90 analyze: diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a96201fc9..fa3e65feae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Unreleased +* Feat: Integration for `logging` (#631) + # 6.1.0 * Bump: Sentry-Android to 5.3.0 and Sentry-Cocoa to 7.5.1 (#629) diff --git a/sentry_logging/.gitignore b/logging/.gitignore similarity index 100% rename from sentry_logging/.gitignore rename to logging/.gitignore diff --git a/logging/CHANGELOG.md b/logging/CHANGELOG.md new file mode 120000 index 0000000000..04c99a55ca --- /dev/null +++ b/logging/CHANGELOG.md @@ -0,0 +1 @@ +../CHANGELOG.md \ No newline at end of file diff --git a/sentry_logging/README.md b/logging/README.md similarity index 100% rename from sentry_logging/README.md rename to logging/README.md diff --git a/sentry_logging/analysis_options.yaml b/logging/analysis_options.yaml similarity index 100% rename from sentry_logging/analysis_options.yaml rename to logging/analysis_options.yaml diff --git a/sentry_logging/example/sentry_logging_example.dart b/logging/example/sentry_logging_example.dart similarity index 100% rename from sentry_logging/example/sentry_logging_example.dart rename to logging/example/sentry_logging_example.dart diff --git a/sentry_logging/lib/sentry_logging.dart b/logging/lib/sentry_logging.dart similarity index 100% rename from sentry_logging/lib/sentry_logging.dart rename to logging/lib/sentry_logging.dart diff --git a/sentry_logging/lib/src/extension.dart b/logging/lib/src/extension.dart similarity index 100% rename from sentry_logging/lib/src/extension.dart rename to logging/lib/src/extension.dart diff --git a/sentry_logging/lib/src/logging_integration.dart b/logging/lib/src/logging_integration.dart similarity index 100% rename from sentry_logging/lib/src/logging_integration.dart rename to logging/lib/src/logging_integration.dart diff --git a/sentry_logging/lib/src/version.dart b/logging/lib/src/version.dart similarity index 100% rename from sentry_logging/lib/src/version.dart rename to logging/lib/src/version.dart diff --git a/sentry_logging/pubspec.yaml b/logging/pubspec.yaml similarity index 100% rename from sentry_logging/pubspec.yaml rename to logging/pubspec.yaml diff --git a/sentry_logging/test/logging_integration_test.dart b/logging/test/logging_integration_test.dart similarity index 100% rename from sentry_logging/test/logging_integration_test.dart rename to logging/test/logging_integration_test.dart diff --git a/sentry_logging/test/mock_hub.dart b/logging/test/mock_hub.dart similarity index 100% rename from sentry_logging/test/mock_hub.dart rename to logging/test/mock_hub.dart diff --git a/sentry_logging/test/version_test.dart b/logging/test/version_test.dart similarity index 100% rename from sentry_logging/test/version_test.dart rename to logging/test/version_test.dart diff --git a/sentry_logging/CHANGELOG.md b/sentry_logging/CHANGELOG.md deleted file mode 100644 index 65aa1d5afa..0000000000 --- a/sentry_logging/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -## 6.2.0 - -- Initial version. From 04c4fcc0fb6b75290e5ee132d42209ee86f7c40c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Wed, 1 Dec 2021 18:01:51 +0100 Subject: [PATCH 18/19] PR Feedback --- logging/lib/src/logging_integration.dart | 10 +++--- logging/test/logging_integration_test.dart | 37 ++++++++++++++++++---- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/logging/lib/src/logging_integration.dart b/logging/lib/src/logging_integration.dart index 29d82985d2..ac9d5d3548 100644 --- a/logging/lib/src/logging_integration.dart +++ b/logging/lib/src/logging_integration.dart @@ -10,10 +10,10 @@ import 'extension.dart'; class LoggingIntegration extends Integration { /// Creates the [LoggingIntegration]. /// - /// Setting [logExceptionAsEvent] to true (default) captures all - /// messages with errors as an [SentryEvent] instead of an [Breadcrumb]. - /// Setting [logExceptionAsEvent] to false captures everything as - /// [Breadcrumb]s. + /// 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, @@ -56,7 +56,7 @@ class LoggingIntegration extends Integration { } bool _isLoggable(Level logLevel, Level minLevel) { - return logLevel > minLevel; + return logLevel >= minLevel; } void _onLog(LogRecord record) async { diff --git a/logging/test/logging_integration_test.dart b/logging/test/logging_integration_test.dart index 797825d69f..cb30840b58 100644 --- a/logging/test/logging_integration_test.dart +++ b/logging/test/logging_integration_test.dart @@ -40,9 +40,7 @@ void main() { await sut.call(fixture.hub, fixture.options); final log = Logger('FooBarLogger'); - log.warning( - 'A log message', - ); + log.warning('A log message'); expect(fixture.hub.events.length, 0); expect(fixture.hub.breadcrumbs.length, 1); @@ -58,14 +56,23 @@ void main() { expect(crumb.type, 'debug'); }); + test('logger gets recorded if level equal minlevel', () async { + final sut = fixture.createSut(minBreadcrumbLevel: Level.INFO); + await sut.call(fixture.hub, fixture.options); + + final log = Logger('FooBarLogger'); + log.info('A log message'); + + expect(fixture.hub.events.length, 0); + expect(fixture.hub.breadcrumbs.length, 1); + }); + test('logger gets not recorded if level under minlevel', () async { final sut = fixture.createSut(minBreadcrumbLevel: Level.SEVERE); await sut.call(fixture.hub, fixture.options); final log = Logger('FooBarLogger'); - log.warning( - 'A log message', - ); + log.warning('A log message'); expect(fixture.hub.events.length, 0); expect(fixture.hub.breadcrumbs.length, 0); @@ -95,6 +102,24 @@ void main() { expect(fixture.hub.events.first.stackTrace, stackTrace); }); + test('exception is recorded as event if minEventLevel equal minlevel', + () async { + final sut = fixture.createSut(minEventLevel: Level.INFO); + await sut.call(fixture.hub, fixture.options); + + final exception = Exception('foo bar'); + final stackTrace = StackTrace.current; + + final log = Logger('FooBarLogger'); + log.info( + 'A log message', + exception, + stackTrace, + ); + expect(fixture.hub.events.length, 1); + expect(fixture.hub.events.first.event.breadcrumbs, null); + }); + test('exception is not recorded as event if minEventLevel under minlevel', () async { final sut = fixture.createSut(minEventLevel: Level.SEVERE); From 0d4805b3c95bf73a50b7542cd215b2335cc9662d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Wed, 1 Dec 2021 18:04:30 +0100 Subject: [PATCH 19/19] return some value --- logging/test/mock_hub.dart | 58 +++++++++++--------------------------- 1 file changed, 17 insertions(+), 41 deletions(-) diff --git a/logging/test/mock_hub.dart b/logging/test/mock_hub.dart index 0368eda24e..88cc465012 100644 --- a/logging/test/mock_hub.dart +++ b/logging/test/mock_hub.dart @@ -33,10 +33,8 @@ class MockHub implements Hub { dynamic stackTrace, dynamic hint, ScopeCallback? withScope, - }) { - // TODO: implement captureException - throw UnimplementedError(); - } + }) async => + SentryId.empty(); @override Future captureMessage( @@ -46,53 +44,33 @@ class MockHub implements Hub { List? params, dynamic hint, ScopeCallback? withScope, - }) { - // TODO: implement captureMessage - throw UnimplementedError(); - } + }) async => + SentryId.empty(); @override - Future captureTransaction(SentryTransaction transaction) { - // TODO: implement captureTransaction - throw UnimplementedError(); - } + Future captureTransaction(SentryTransaction transaction) async => + SentryId.empty(); @override - Future captureUserFeedback(SentryUserFeedback userFeedback) { - // TODO: implement captureUserFeedback - throw UnimplementedError(); - } + Future captureUserFeedback(SentryUserFeedback userFeedback) async {} @override - Hub clone() { - // TODO: implement clone - throw UnimplementedError(); - } + Hub clone() => throw UnimplementedError(); @override - Future close() { - // TODO: implement close - throw UnimplementedError(); - } + Future close() async {} @override - void configureScope(ScopeCallback callback) { - // TODO: implement configureScope - } + void configureScope(ScopeCallback callback) {} @override - ISentrySpan? getSpan() { - // TODO: implement getSpan - throw UnimplementedError(); - } + ISentrySpan? getSpan() => throw UnimplementedError(); @override - // TODO: implement isEnabled - bool get isEnabled => throw UnimplementedError(); + bool get isEnabled => true; @override - // TODO: implement lastEventId - SentryId get lastEventId => throw UnimplementedError(); + SentryId get lastEventId => SentryId.empty(); @override void setSpanContext( @@ -108,18 +86,16 @@ class MockHub implements Hub { String? description, bool? bindToScope, Map? customSamplingContext, - }) { - throw UnimplementedError(); - } + }) => + throw UnimplementedError(); @override ISentrySpan startTransactionWithContext( SentryTransactionContext transactionContext, { Map? customSamplingContext, bool? bindToScope, - }) { - throw UnimplementedError(); - } + }) => + throw UnimplementedError(); } class CapturedEvents {