Skip to content

Commit

Permalink
Merge pull request #80 from rollbar/userid
Browse files Browse the repository at this point in the history
Add the ability to track Users
  • Loading branch information
matux authored Oct 26, 2022
2 parents 5e0adc0 + 1dd5e72 commit 647ca33
Show file tree
Hide file tree
Showing 16 changed files with 184 additions and 49 deletions.
2 changes: 1 addition & 1 deletion rollbar_common/lib/src/data/breadcrumb_record.dart
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class PersistableBreadcrumbRecord implements PersistableFor {
BreadcrumbRecord.persistingKeyTypes;
}

extension BreadcrumbRecordAttributes on JsonMap {
extension _KeyValuePaths on JsonMap {
UUID get id => UUID.fromList(this['id'].whereType<int>().toList());
String get breadcrumb => this['breadcrumb'];
DateTime get timestamp => DateTime.fromMicrosecondsSinceEpoch(
Expand Down
2 changes: 1 addition & 1 deletion rollbar_common/lib/src/data/payload_record.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class PersistablePayloadRecord implements PersistableFor {
PayloadRecord.persistingKeyTypes;
}

extension PayloadRecordAttributes on JsonMap {
extension _KeyValuePaths on JsonMap {
UUID get id => UUID.fromList(this['id'].whereType<int>().toList());
String get accessToken => this['accessToken'];
String get endpoint => this['endpoint'];
Expand Down
1 change: 1 addition & 0 deletions rollbar_dart/lib/rollbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export 'src/sender/sender.dart' show Sender;
export 'src/data/payload/client.dart' show Client;
export 'src/data/payload/payload.dart' show Payload;
export 'src/data/payload/breadcrumb.dart' show Breadcrumb, Source;
export 'src/data/payload/user.dart' show User;
export 'src/data/payload/data.dart' show Data;
export 'src/data/payload/body.dart' show Body, Report, Trace, Traces, Message;
export 'src/data/payload/frame.dart' show Frame;
Expand Down
6 changes: 6 additions & 0 deletions rollbar_dart/lib/src/context.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import 'data/payload/user.dart';

/// Context doesn't persist in-between application runs.
class Context {
User? user;
}
2 changes: 1 addition & 1 deletion rollbar_dart/lib/src/data/payload/body.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class Message with Report, EquatableSerializableMixin {
};
}

extension _KeyValuePath on JsonMap {
extension _KeyValuePaths on JsonMap {
ExceptionInfo get exception => ExceptionInfo.fromMap(this['exception']);
String get message => this['message']['body'];
String? get rawTrace => this['raw'];
Expand Down
58 changes: 41 additions & 17 deletions rollbar_dart/lib/src/data/payload/data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:rollbar_common/rollbar_common.dart';

import 'body.dart' show Body;
import 'client.dart' show Client;
import 'user.dart' show User;

/// Contains the data for the occurrence to be sent to Rollbar.
@sealed
Expand All @@ -17,6 +18,7 @@ class Data with EquatableSerializableMixin implements Serializable, Equatable {
final String language;
final String framework;
final String codeVersion;
final User? user;
final JsonMap? custom;
final JsonMap? platformPayload;
final JsonMap server;
Expand All @@ -33,6 +35,7 @@ class Data with EquatableSerializableMixin implements Serializable, Equatable {
required this.level,
required this.timestamp,
required this.body,
this.user,
this.custom,
this.platformPayload,
required this.server,
Expand All @@ -49,6 +52,7 @@ class Data with EquatableSerializableMixin implements Serializable, Equatable {
Level? level,
DateTime? timestamp,
Body? body,
User? user,
JsonMap? custom,
JsonMap? platformPayload,
JsonMap? server,
Expand All @@ -64,6 +68,7 @@ class Data with EquatableSerializableMixin implements Serializable, Equatable {
level: level ?? this.level,
timestamp: timestamp ?? this.timestamp,
body: body ?? this.body,
user: user ?? this.user,
custom: custom ?? this.custom,
platformPayload: platformPayload ?? this.platformPayload,
server: server ?? this.server,
Expand All @@ -81,27 +86,26 @@ class Data with EquatableSerializableMixin implements Serializable, Equatable {
level: other.level,
timestamp: other.timestamp,
body: other.body,
user: other.user,
custom: other.custom,
platformPayload: other.platformPayload,
server: other.server);

factory Data.fromMap(JsonMap map) => Data(
notifier: map['notifier'],
environment: map['environment'],
client: Client.fromMap(map['client']),
platform: map['platform'],
language: map['language'],
framework: map['framework'],
codeVersion: map['code_version'],
level: Level.values.firstWhere((level) => level.name == map['level']),
body: Body.fromMap(map['body']),
custom: map['custom'],
platformPayload: map['platform_payload'],
server: map['server'],
timestamp: DateTime.fromMicrosecondsSinceEpoch(
map['timestamp'],
isUtc: true,
));
factory Data.fromMap(JsonMap json) => Data(
notifier: json.notifier,
environment: json.environment,
client: json.client,
platform: json.platform,
language: json.language,
framework: json.framework,
codeVersion: json.codeVersion,
level: json.level,
body: json.body,
user: json.user,
custom: json.custom,
platformPayload: json.platformPayload,
server: json.server,
timestamp: json.timestamp);

@override
JsonMap toMap() => {
Expand All @@ -113,10 +117,30 @@ class Data with EquatableSerializableMixin implements Serializable, Equatable {
'language': language,
'level': level.name,
'timestamp': timestamp.microsecondsSinceEpoch,
'person': user?.toMap(),
'custom': custom,
'server': server,
'framework': framework,
'code_version': codeVersion,
'platform_payload': platformPayload,
}.compact();
}

extension _KeyValuePaths on JsonMap {
JsonMap get notifier => this['notifier'];
String get environment => this['environment'];
Client get client => Client.fromMap(this['client']);
JsonMap get server => this['server'];
String get platform => this['platform'];
String get language => this['language'];
String get framework => this['framework'];
String get codeVersion => this['code_version'];
Level get level =>
Level.values.firstWhere((level) => level.name == this['level']);
Body get body => Body.fromMap(this['body']);
User? get user => (this['person'] as JsonMap?).map(User.fromMap);
JsonMap? get custom => this['custom'];
JsonMap? get platformPayload => this['platform_payload'];
DateTime get timestamp =>
DateTime.fromMicrosecondsSinceEpoch(this['timestamp'], isUtc: true);
}
30 changes: 30 additions & 0 deletions rollbar_dart/lib/src/data/payload/user.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'package:meta/meta.dart';
import 'package:rollbar_common/rollbar_common.dart';

@sealed
@immutable
class User with EquatableSerializableMixin implements Equatable, Serializable {
final String id;
final String? username;
final String? email;

const User({
required this.id,
this.username,
this.email,
});

factory User.fromMap(JsonMap map) => User(
id: map['id'],
username: map['username'],
email: map['email'],
);

/// Converts the object into a Json encodable map.
@override
JsonMap toMap() => {
'id': id,
'username': username,
'email': email,
}.compact();
}
16 changes: 16 additions & 0 deletions rollbar_dart/lib/src/event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import 'package:meta/meta.dart';
import 'package:rollbar_common/rollbar_common.dart';

import 'data/payload/breadcrumb.dart';
import 'data/payload/user.dart';
import 'context.dart';
import 'telemetry.dart';

@sealed
Expand All @@ -11,15 +13,19 @@ class Event {
final dynamic error;
final StackTrace? stackTrace;
final String? message;
final User? user;
final Breadcrumb? breadcrumb;
final Context? context;
final Telemetry? telemetry;

const Event({
this.level = Level.info,
this.error,
this.stackTrace,
this.message,
this.user,
this.breadcrumb,
this.context,
this.telemetry,
});

Expand All @@ -28,15 +34,19 @@ class Event {
dynamic error,
StackTrace? stackTrace,
String? message,
User? user,
Breadcrumb? breadcrumb,
Context? context,
Telemetry? telemetry,
}) =>
Event(
level: level ?? this.level,
error: error ?? this.error,
stackTrace: stackTrace ?? this.stackTrace,
message: message ?? this.message,
user: user ?? this.user,
breadcrumb: breadcrumb ?? this.breadcrumb,
context: context ?? this.context,
telemetry: telemetry ?? this.telemetry);

@override
Expand All @@ -45,7 +55,9 @@ class Event {
'error: $error, '
'stackTrace: $stackTrace, '
'message: $message, '
'user: $user, '
'breadcrumb: $breadcrumb, '
'context: $context, '
'telemetry: $telemetry)';

@override
Expand All @@ -56,7 +68,9 @@ class Event {
other.error == error &&
other.stackTrace == stackTrace &&
other.message == message &&
other.user == user &&
other.breadcrumb == breadcrumb &&
other.context == context &&
other.telemetry == telemetry);

@override
Expand All @@ -65,7 +79,9 @@ class Event {
error,
stackTrace,
message,
user,
breadcrumb,
context,
telemetry,
);
}
11 changes: 9 additions & 2 deletions rollbar_dart/lib/src/notifier/async_notifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import '../data/payload/breadcrumb.dart';
import '../sender/sender.dart';
import '../wrangler/wrangler.dart';
import '../config.dart';
import '../context.dart';
import '../event.dart';
import '../telemetry.dart';
import 'notifier.dart';
Expand All @@ -20,23 +21,29 @@ class AsyncNotifier implements Notifier {
@override
final Wrangler wrangler;

@override
final Context context;

@override
final Telemetry telemetry;

AsyncNotifier(Config config)
: wrangler = config.wrangler(config),
sender = config.sender(config),
context = Context(),
telemetry = Telemetry(config);

@override
FutureOr<void> notify(Event event) async {
if (event.breadcrumb != null) {
if (event.user != null) {
context.user = event.user;
} else if (event.breadcrumb != null) {
telemetry.add(event.breadcrumb as Breadcrumb);
} else {
telemetry.removeExpired();

final payload = await wrangler.payload(
event: event.copyWith(telemetry: telemetry),
event: event.copyWith(context: context, telemetry: telemetry),
);
await sender.send(payload.toMap());
}
Expand Down
9 changes: 7 additions & 2 deletions rollbar_dart/lib/src/notifier/isolated_notifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import '../data/payload/breadcrumb.dart';
import '../sender/sender.dart';
import '../wrangler/wrangler.dart';
import '../config.dart';
import '../context.dart';
import '../event.dart';
import '../telemetry.dart';
import 'async_notifier.dart';
Expand Down Expand Up @@ -57,6 +58,7 @@ extension _IsolatedNotifier$Isolate on IsolatedNotifier {
static late final Wrangler wrangler;
static late final Sender sender;
static late final Telemetry telemetry;
static late final Context context;

static Future<void> run(Tuple2<SendPort, Config> tuple) async {
final sendPort = tuple.first;
Expand All @@ -67,15 +69,18 @@ extension _IsolatedNotifier$Isolate on IsolatedNotifier {
sender = config.sender(config);
wrangler = config.wrangler(config);
telemetry = Telemetry(config);
context = Context();

await for (final Event event in receivePort) {
if (event.breadcrumb != null) {
if (event.user != null) {
context.user = event.user;
} else if (event.breadcrumb != null) {
telemetry.add(event.breadcrumb as Breadcrumb);
} else {
telemetry.removeExpired();

final payload = await wrangler.payload(
event: event.copyWith(telemetry: telemetry),
event: event.copyWith(context: context, telemetry: telemetry),
);
await sender.send(payload.toMap());
}
Expand Down
2 changes: 2 additions & 0 deletions rollbar_dart/lib/src/notifier/notifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:async';

import '../sender/sender.dart';
import '../wrangler/wrangler.dart';
import '../context.dart';
import '../telemetry.dart';
import '../event.dart';

Expand All @@ -12,6 +13,7 @@ abstract class Notifier {

Sender get sender;
Wrangler get wrangler;
Context get context;
Telemetry get telemetry;

FutureOr<void> notify(Event event);
Expand Down
9 changes: 6 additions & 3 deletions rollbar_dart/lib/src/rollbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:async';

import 'package:meta/meta.dart';
import 'package:rollbar_common/rollbar_common.dart';
import 'package:rollbar_dart/src/data/payload/user.dart';

import 'data/payload/breadcrumb.dart';
import 'notifier/notifier.dart';
Expand Down Expand Up @@ -77,6 +78,10 @@ class Rollbar {
stackTrace: stackTrace,
));

static FutureOr<void> setUser(User? user) {
current._notifier.notify(Event(user: user));
}

/// Drops a breadcrumb with information about state, a change of state, an
/// event such as the user interacting with a widget, or navigating from one
/// place to another or any custom data.
Expand All @@ -87,8 +92,6 @@ class Rollbar {
///
/// - See also: [Breadcrumb].
static FutureOr<void> drop(Breadcrumb breadcrumb) {
current._notifier.notify(Event(
breadcrumb: breadcrumb,
));
current._notifier.notify(Event(breadcrumb: breadcrumb));
}
}
1 change: 1 addition & 0 deletions rollbar_dart/lib/src/wrangler/data_wrangler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ extension _Data on Data {
Data(
body: _Body.from(event: event),
client: _Client.fromPlatform(),
user: event.context?.user,
codeVersion: config.codeVersion,
environment: config.environment,
framework: config.framework,
Expand Down
Loading

0 comments on commit 647ca33

Please sign in to comment.