Skip to content
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

Add a notification layer to scope mutation #1153

Merged
merged 16 commits into from
Aug 23, 2021
Merged
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Features

- Add Scope observer to SentryOptions ([#1153](https://github.com/getsentry/sentry-dotnet/pull/1153))

### Fixes

- Fix end session from Hub adapter not being passed to SentrySDK ([#1158](https://github.com/getsentry/sentry-dotnet/pull/1158))
Expand Down
35 changes: 35 additions & 0 deletions src/Sentry/IScopeObserver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Collections.Generic;

namespace Sentry
{
/// <summary>
/// Observer for the sync. of Scopes across SDKs.
/// </summary>
public interface IScopeObserver
{
/// <summary>
/// Adds a breadcrumb.
/// </summary>
void AddBreadcrumb(Breadcrumb breadcrumb);

/// <summary>
/// Sets an extra.
/// </summary>
void SetExtra(string key, object? value);

/// <summary>
/// Sets a tag.
/// </summary>
void SetTag(string key, string value);

/// <summary>
/// Removes a tag.
/// </summary>
void UnsetTag(string key);

/// <summary>
/// Sets the user information.
/// </summary>
void SetUser(User? user);
}
}
53 changes: 48 additions & 5 deletions src/Sentry/Scope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,31 @@ public Contexts Contexts
set => _contexts = value;
}

// Internal for testing.
internal Action<User?> UserChanged => (user) =>
{
if (Options.EnableScopeSync &&
Options.ScopeObserver is { } observer)
{
observer.SetUser(user);
}
};

private User? _user;

/// <inheritdoc />
public User User
{
get => _user ??= new User();
set => _user = value;
get => _user ??= new User { PropertyChanged = UserChanged };
set
{
_user = value;
if (_user is not null)
{
_user.PropertyChanged = UserChanged;
}
UserChanged.Invoke(_user);
}
}

/// <inheritdoc />
Expand Down Expand Up @@ -237,16 +255,41 @@ public void AddBreadcrumb(Breadcrumb breadcrumb)
}

_breadcrumbs.Enqueue(breadcrumb);
if (Options.EnableScopeSync)
{
Options.ScopeObserver?.AddBreadcrumb(breadcrumb);
}
}

/// <inheritdoc />
public void SetExtra(string key, object? value) => _extra[key] = value;
public void SetExtra(string key, object? value)
{
_extra[key] = value;
if (Options.EnableScopeSync)
{
Options.ScopeObserver?.SetExtra(key, value);
}
}

/// <inheritdoc />
public void SetTag(string key, string value) => _tags[key] = value;
public void SetTag(string key, string value)
{
_tags[key] = value;
if (Options.EnableScopeSync)
{
Options.ScopeObserver?.SetTag(key, value);
}
}

/// <inheritdoc />
public void UnsetTag(string key) => _tags.TryRemove(key, out _);
public void UnsetTag(string key)
{
_tags.TryRemove(key, out _);
if (Options.EnableScopeSync)
{
Options.ScopeObserver?.UnsetTag(key);
}
}

/// <summary>
/// Adds an attachment.
Expand Down
11 changes: 11 additions & 0 deletions src/Sentry/SentryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ public bool IsGlobalModeEnabled
set => ScopeStackContainer = value ? new GlobalScopeStackContainer() : new AsyncLocalScopeStackContainer();
}

/// <summary>
/// A scope set outside of Sentry SDK. If set, the global parameters from the SDK's scope will be sent to the observed scope.<br/>
/// NOTE: EnableScopeSync must be set true for the scope to be synced.
/// </summary>
public IScopeObserver? ScopeObserver { get; set; }

/// <summary>
/// If true, the SDK's scope will be synced with the observed scope.
/// </summary>
public bool EnableScopeSync { get; set; }

// Override for tests
internal ITransport? Transport { get; set; }

Expand Down
51 changes: 47 additions & 4 deletions src/Sentry/User.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
Expand All @@ -11,37 +12,79 @@ namespace Sentry
/// <see href="https://develop.sentry.dev/sdk/event-payloads/user/"/>
public sealed class User : IJsonSerializable
{
internal Action<User>? PropertyChanged { get; set; }

private string? _email;

/// <summary>
/// The email address of the user.
/// </summary>
/// <value>
/// The user's email address.
/// </value>
public string? Email { get; set; }
public string? Email
{
get => _email;
set
{
_email = value;
PropertyChanged?.Invoke(this);
}
}

private string? _id;

/// <summary>
/// The unique ID of the user.
/// </summary>
/// <value>
/// The unique identifier.
/// </value>
public string? Id { get; set; }
public string? Id
{
get => _id;
set
{
_id = value;
PropertyChanged?.Invoke(this);
}
}

private string? _ipAddress;

/// <summary>
/// The IP of the user.
/// </summary>
/// <value>
/// The user's IP address.
/// </value>
public string? IpAddress { get; set; }
public string? IpAddress
{
get => _ipAddress;
set
{
_ipAddress = value;
PropertyChanged?.Invoke(this);
}
}

private string? _username;

/// <summary>
/// The username of the user.
/// </summary>
/// <value>
/// The user's username.
/// </value>
public string? Username { get; set; }
public string? Username
{
get => _username;
set
{
_username = value;
PropertyChanged?.Invoke(this);
}
}

internal IDictionary<string, string>? InternalOther { get; private set; }

Expand Down
Loading