Skip to content

Support user context #17

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 11 commits into from
May 15, 2018
62 changes: 42 additions & 20 deletions lib/sentry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,13 @@ class SentryClient {
/// Attached to the event payload.
final String projectId;

@visibleForTesting
User _userContext;

set userContext(User val) {
_userContext = val;
}
/// The user data that will get sent with every logged event
///
/// Note that a [Event.userContext] that is set on a logged [Event]
/// will override the [User] context set here.
///
/// see: https://docs.sentry.io/learn/context/#capturing-the-user
User userContext;

@visibleForTesting
String get postUri =>
Expand Down Expand Up @@ -178,8 +179,8 @@ class SentryClient {
mergeAttributes(environmentAttributes.toJson(), into: data);

// merge the user context
if (_userContext != null) {
mergeAttributes({'user': _userContext.toJson()}, into: data);
if (userContext != null) {
mergeAttributes({'user': userContext.toJson()}, into: data);
}
mergeAttributes(event.toJson(), into: data);

Expand Down Expand Up @@ -342,6 +343,10 @@ class Event {
/// they must be JSON-serializable.
final Map<String, dynamic> extra;

/// User information that is sent with the logged [Event]
///
/// The value in this field overrides the user context
/// set in [SentryClient.userContext] for this logged event.
final User userContext;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dartdocs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


/// Used to deduplicate events by grouping ones with the same fingerprint
Expand Down Expand Up @@ -415,33 +420,50 @@ class Event {
}
}

/// An interface which describes the authenticated User for a request.
/// You should provide at least either an id (a unique identifier for an
/// authenticated user) or ip_address (their IP address).
///
/// Conforms to the User Interface contract for Sentry
/// https://docs.sentry.io/clientdev/interfaces/user/
///
/// The outgoing json representation is:
/// ```
/// "user": {
/// "id": "unique_id",
/// "username": "my_user",
/// "email": "[email protected]",
/// "ip_address": "127.0.0.1",
/// "subscription": "basic"
///}
///
/// "id": "unique_id",
/// "username": "my_user",
/// "email": "[email protected]",
/// "ip_address": "127.0.0.1",
/// "subscription": "basic"
/// }
/// ```
class User {
/// The unique ID of the user.
final String id;

/// The username of the user
final String username;

/// The email address of the user.
final String email;

/// The IP of the user.
final String ipAddress;
final String subscription;

const User(this.id, this.username, this.email, this.ipAddress, this.subscription);
/// Any other user context information that may be helpful
/// All other keys are stored as extra information but not
/// specifically processed by sentry.
final Map<String, dynamic> extras;

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

Map<String, String> toJson() {
return <String, String>{
Map<String, dynamic> toJson() {
return {
"id": id,
"username": username,
"email": email,
"ip_address": ipAddress,
"subscription": subscription
"extras": extras,
};
}
}
25 changes: 19 additions & 6 deletions test/sentry_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ void main() {
'Content-Type': 'application/json',
'X-Sentry-Auth': 'Sentry sentry_version=6, '
'sentry_client=${SentryClient.sentryClient}, '
'sentry_timestamp=${fakeClock.now().millisecondsSinceEpoch}, '
'sentry_timestamp=${fakeClock
.now()
.millisecondsSinceEpoch}, '
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, did dartfmt do this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it did. it appears that the travis rule runs dartfmt and fails if there is anything changed after running it. so after I ran dartfmt locally and uploaded it now passes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should file a bug.

'sentry_key=public, '
'sentry_secret=secret',
};
Expand Down Expand Up @@ -194,10 +196,17 @@ void main() {
fail('Unexpected invocation of ${invocation.memberName} in HttpMock');
});

const clientUserContext = const User(
"client_user", "username", "[email protected]", "127.0.0.1", "basic");
final clientUserContext = new User(
id: "client_user",
username: "username",
email: "[email protected]",
ipAddress: "127.0.0.1");
final eventUserContext = new User(
"event_user", "username", "[email protected]", "127.0.0.1", "basic");
id: "event_user",
username: "username",
email: "[email protected]",
ipAddress: "127.0.0.1",
extras: {"foo": "bar"});

final SentryClient client = new SentryClient(
dsn: _testDsn,
Expand Down Expand Up @@ -235,7 +244,11 @@ void main() {
group('$Event', () {
test('serializes to JSON', () {
final user = new User(
"user_id", "username", "[email protected]", "127.0.0.1", "basic");
id: "user_id",
username: "username",
email: "[email protected]",
ipAddress: "127.0.0.1",
extras: {"foo": "bar"});
expect(
new Event(
message: 'test-message',
Expand Down Expand Up @@ -270,7 +283,7 @@ void main() {
'username': 'username',
'email': '[email protected]',
'ip_address': '127.0.0.1',
'subscription': 'basic'
'extras': {'foo': 'bar'}
},
},
);
Expand Down