Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- new Dart code file structure #96
- Base the sdk name on the platform (`sentry.dart` for io & flutter, `sentry.dart.browser` in a browser context) #103
- Single changelog and readme for both packages #105
- new static API : Sentry.init(), Sentry.captureEvent() #108

# `package:sentry` changelog

Expand Down
73 changes: 73 additions & 0 deletions dart/example/event_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import 'package:sentry/src/protocol.dart';

final event = Event(
loggerName: 'main',
serverName: 'server.dart',
release: '1.4.0-preview.1',
environment: 'Test',
message: Message(formatted: 'This is an example Dart event.'),
transaction: '/example/app',
level: SeverityLevel.warning,
tags: const <String, String>{'project-id': '7371'},
extra: const <String, String>{'company-name': 'Dart Inc'},
fingerprint: const <String>['example-dart'],
userContext: const User(
id: '800',
username: 'first-user',
email: '[email protected]',
ipAddress: '127.0.0.1',
extras: <String, String>{'first-sign-in': '2020-01-01'}),
breadcrumbs: [
Breadcrumb('UI Lifecycle', DateTime.now().toUtc(),
category: 'ui.lifecycle',
type: 'navigation',
data: {'screen': 'MainActivity', 'state': 'created'},
level: SeverityLevel.info)
],
contexts: Contexts(
operatingSystem: const OperatingSystem(
name: 'Android',
version: '5.0.2',
build: 'LRX22G.P900XXS0BPL2',
kernelVersion:
'Linux version 3.4.39-5726670 (dpi@SWHC3807) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Dec 1 19:42:39 KST 2016',
rooted: false),
runtimes: [const Runtime(name: 'ART', version: '5')],
app: App(
name: 'Example Dart App',
version: '1.42.0',
identifier: 'HGT-App-13',
build: '93785',
buildType: 'release',
deviceAppHash: '5afd3a6',
startTime: DateTime.now().toUtc()),
browser: const Browser(name: 'Firefox', version: '42.0.1'),
device: Device(
name: 'SM-P900',
family: 'SM-P900',
model: 'SM-P900 (LRX22G)',
modelId: 'LRX22G',
arch: 'armeabi-v7a',
batteryLevel: 99,
orientation: Orientation.landscape,
manufacturer: 'samsung',
brand: 'samsung',
screenResolution: '2560x1600',
screenDensity: 2.1,
screenDpi: 320,
online: true,
charging: true,
lowMemory: true,
simulator: false,
memorySize: 1500,
freeMemory: 200,
usableMemory: 4294967296,
storageSize: 4294967296,
freeStorage: 2147483648,
externalStorageSize: 8589934592,
externalFreeStorage: 2863311530,
bootTime: DateTime.now().toUtc(),
timezone: 'America/Toronto',
),
),
);
112 changes: 27 additions & 85 deletions dart/example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import 'dart:io';

import 'package:sentry/sentry.dart';

import 'event_example.dart';

/// Sends a test exception report to Sentry.io using this Dart client.
Future<void> main(List<String> rawArgs) async {
if (rawArgs.length != 1) {
Expand All @@ -16,18 +18,26 @@ Future<void> main(List<String> rawArgs) async {
}

final dsn = rawArgs.single;
final client = SentryClient(dsn: dsn);
Sentry.init(Options(dsn: dsn));

print('\nReporting a complete event example: ');

// Sends a full Sentry event payload to show the different parts of the UI.
await captureCompleteExampleEvent(client);
final response = await Sentry.captureEvent(event);

if (response.isSuccessful) {
print('SUCCESS\nid: ${response.eventId}');
} else {
print('FAILURE: ${response.error}');
}

try {
await foo();
} catch (error, stackTrace) {
print('\nReporting the following stack trace: ');
print(stackTrace);
final response = await client.captureException(
exception: error,
final response = await Sentry.captureException(
error,
stackTrace: stackTrace,
);

Expand All @@ -37,89 +47,10 @@ Future<void> main(List<String> rawArgs) async {
print('FAILURE: ${response.error}');
}
} finally {
await client.close();
await Sentry.close();
}
}

Future<void> captureCompleteExampleEvent(SentryClient client) async {
final event = Event(
loggerName: 'main',
serverName: 'server.dart',
release: '1.4.0-preview.1',
environment: 'Test',
message: Message(formatted: 'This is an example Dart event.'),
transaction: '/example/app',
level: SeverityLevel.warning,
tags: const <String, String>{'project-id': '7371'},
extra: const <String, String>{'company-name': 'Dart Inc'},
fingerprint: const <String>['example-dart'],
userContext: const User(
id: '800',
username: 'first-user',
email: '[email protected]',
ipAddress: '127.0.0.1',
extras: <String, String>{'first-sign-in': '2020-01-01'}),
breadcrumbs: [
Breadcrumb('UI Lifecycle', DateTime.now().toUtc(),
category: 'ui.lifecycle',
type: 'navigation',
data: {'screen': 'MainActivity', 'state': 'created'},
level: SeverityLevel.info)
],
contexts: Contexts(
operatingSystem: const OperatingSystem(
name: 'Android',
version: '5.0.2',
build: 'LRX22G.P900XXS0BPL2',
kernelVersion:
'Linux version 3.4.39-5726670 (dpi@SWHC3807) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Dec 1 19:42:39 KST 2016',
rooted: false),
runtimes: [const Runtime(name: 'ART', version: '5')],
app: App(
name: 'Example Dart App',
version: '1.42.0',
identifier: 'HGT-App-13',
build: '93785',
buildType: 'release',
deviceAppHash: '5afd3a6',
startTime: DateTime.now().toUtc()),
browser: const Browser(name: 'Firefox', version: '42.0.1'),
device: Device(
name: 'SM-P900',
family: 'SM-P900',
model: 'SM-P900 (LRX22G)',
modelId: 'LRX22G',
arch: 'armeabi-v7a',
batteryLevel: 99,
orientation: Orientation.landscape,
manufacturer: 'samsung',
brand: 'samsung',
screenResolution: '2560x1600',
screenDensity: 2.1,
screenDpi: 320,
online: true,
charging: true,
lowMemory: true,
simulator: false,
memorySize: 1500,
freeMemory: 200,
usableMemory: 4294967296,
storageSize: 4294967296,
freeStorage: 2147483648,
externalStorageSize: 8589934592,
externalFreeStorage: 2863311530,
bootTime: DateTime.now().toUtc(),
timezone: 'America/Toronto',
)));

final response = await client.captureEvent(event: event);

print('\nReporting a complete event example: ');
if (response.isSuccessful) {
print('SUCCESS\nid: ${response.eventId}');
} else {
print('FAILURE: ${response.error}');
}
/* TODO(rxlabz) Sentry CaptureMessage(message, level) */
}

Future<void> foo() async {
Expand All @@ -133,3 +64,14 @@ Future<void> bar() async {
Future<void> baz() async {
throw StateError('This is a test error');
}

class Options implements OptionsConfiguration<SentryOptions> {
final String dsn;

Options({this.dsn});

@override
void configure(SentryOptions options) {
options.dsn = dsn;
}
}
2 changes: 2 additions & 0 deletions dart/lib/sentry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
/// A pure Dart client for Sentry.io crash reporting.
export 'src/client.dart';
export 'src/protocol.dart';
export 'src/sentry.dart';
export 'src/sentry_options.dart';
export 'src/version.dart';
4 changes: 2 additions & 2 deletions dart/lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ abstract class SentryClient {
/// `dart:html` is available, otherwise it will throw an unsupported error.
factory SentryClient({
@required String dsn,
Event environmentAttributes,
Event environment,
bool compressPayload,
Client httpClient,
dynamic clock,
UuidGenerator uuidGenerator,
}) =>
createSentryClient(
dsn: dsn,
environmentAttributes: environmentAttributes,
environmentAttributes: environment,
httpClient: httpClient,
clock: clock,
uuidGenerator: uuidGenerator,
Expand Down
57 changes: 57 additions & 0 deletions dart/lib/src/sentry.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'dart:async';

import 'package:meta/meta.dart';

import 'client.dart';
import 'protocol.dart';
import 'sentry_options.dart';

/// Sentry SDK main entry point
///
class Sentry {
static SentryClient _client;

Sentry._();

static void init(OptionsConfiguration<SentryOptions> optionsConfiguration) {
final options = SentryOptions();
optionsConfiguration.configure(options);
_client = SentryClient(
dsn: options.dsn,
environment: options.environment,
compressPayload: options.compressPayload,
httpClient: options.httpClient,
clock: options.clock,
uuidGenerator: options.uuidGenerator,
);
}

/// Reports an [event] to Sentry.io.
static Future<SentryResponse> captureEvent(Event event) async {
return _client.captureEvent(event: event);
}

/// Reports the [exception] and optionally its [stackTrace] to Sentry.io.
static Future<SentryResponse> captureException(
dynamic error, {
dynamic stackTrace,
}) async {
return _client.captureException(
exception: error,
stackTrace: stackTrace,
);
}

/// Close the client SDK
static Future<void> close() async => _client.close();

/// client injector only use for testing
@visibleForTesting
static void initClient(SentryClient client) => _client = client;
}

/// Configuration options callback
abstract class OptionsConfiguration<T extends SentryOptions> {
///configure the options
void configure(T options);
}
53 changes: 53 additions & 0 deletions dart/lib/src/sentry_options.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import 'package:http/http.dart';

import 'protocol.dart';
import 'utils.dart';

/// Sentry SDK options
class SentryOptions {
/// Default Log level if not specified Default is DEBUG
static final SeverityLevel defaultDiagnosticLevel = SeverityLevel.debug;

/// The DSN tells the SDK where to send the events to. If this value is not provided, the SDK will
/// just not send any events.
String dsn;

/// Contains [Event] attributes that are automatically mixed into all events
/// captured through this client.
///
/// This event is designed to contain static values that do not change from
/// event to event, such as local operating system version, the version of
/// Dart/Flutter SDK, etc. These attributes have lower precedence than those
/// supplied in the even passed to [capture].
Event environment;

/// If [compressPayload] is `true` the outgoing HTTP payloads are compressed
/// using gzip. Otherwise, the payloads are sent in plain UTF8-encoded JSON
/// text. If not specified, the compression is enabled by default.
bool compressPayload;

/// If [httpClient] is provided, it is used instead of the default client to
/// make HTTP calls to Sentry.io. This is useful in tests.
Client httpClient;

/// If [clock] is provided, it is used to get time instead of the system
/// clock. This is useful in tests. Should be an implementation of [ClockProvider].
/// This parameter is dynamic to maintain backwards compatibility with
/// previous use of [Clock](https://pub.dartlang.org/documentation/quiver/latest/quiver.time/Clock-class.html)
/// from [`package:quiver`](https://pub.dartlang.org/packages/quiver).
dynamic clock;

/// If [uuidGenerator] is provided, it is used to generate the "event_id"
/// field instead of the built-in random UUID v4 generator. This is useful in
/// tests.
UuidGenerator uuidGenerator;

SentryOptions({
this.dsn,
this.environment,
this.compressPayload,
this.httpClient,
this.clock,
this.uuidGenerator,
});
}
Loading