Skip to content

Commit

Permalink
Merged IHasMeasurements into ISpanData (#2659)
Browse files Browse the repository at this point in the history
  • Loading branch information
jamescrosswell committed Oct 2, 2023
1 parent 0aed969 commit 3c3182d
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 86 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -15,6 +15,8 @@ without native/platform specific bindings and SDKs. See [this ticket for more de
- Drop .NET 6 Mobile in favor of .NET 7 ([#2624](https://github.com/getsentry/sentry-dotnet/pull/2604))

API Changes:

- IHasMeasurements was removed. Use ISpanData instead. ([#2659](https://github.com/getsentry/sentry-dotnet/pull/2659))
- If `null` has been supplied as DSN when initializing Sentry, and ArgumentNullException is now thrown ([#2655](https://github.com/getsentry/sentry-dotnet/pull/2655))
- IHasBreadcrumbs was removed. Use IEventLike instead. ([#2670](https://github.com/getsentry/sentry-dotnet/pull/2670))
- ISpanContext was removed. Use ITraceContext instead. ([#2668](https://github.com/getsentry/sentry-dotnet/pull/2668))
Expand Down
63 changes: 0 additions & 63 deletions src/Sentry/IHasMeasurements.cs

This file was deleted.

49 changes: 49 additions & 0 deletions src/Sentry/ISpanData.cs
Expand Up @@ -26,4 +26,53 @@ public interface ISpanData : ITraceContext, IHasTags, IHasExtra
/// Get Sentry trace header.
/// </summary>
SentryTraceHeader GetTraceHeader();

/// <summary>
/// The measurements that have been set on the transaction.
/// </summary>
IReadOnlyDictionary<string, Measurement> Measurements { get; }

/// <summary>
/// Sets a measurement on the transaction.
/// </summary>
/// <param name="name">The name of the measurement.</param>
/// <param name="measurement">The measurement.</param>
void SetMeasurement(string name, Measurement measurement);
}

/// <summary>
/// Extensions for <see cref="ISpanData"/>
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static class SpanDataExtensions
{
/// <summary>
/// Sets a measurement on the transaction.
/// </summary>
/// <param name="spanData">The transaction.</param>
/// <param name="name">The name of the measurement.</param>
/// <param name="value">The value of the measurement.</param>
/// <param name="unit">The optional unit of the measurement.</param>
public static void SetMeasurement(this ISpanData spanData, string name, int value,
MeasurementUnit unit = default) =>
spanData.SetMeasurement(name, new Measurement(value, unit));

/// <inheritdoc cref="SetMeasurement(Sentry.ISpanData,string,int,Sentry.MeasurementUnit)" />
public static void SetMeasurement(this ISpanData spanData, string name, long value,
MeasurementUnit unit = default) =>
spanData.SetMeasurement(name, new Measurement(value, unit));

/// <inheritdoc cref="SetMeasurement(Sentry.ISpanData,string,int,Sentry.MeasurementUnit)" />
#if !__MOBILE__
// ulong parameter is not CLS compliant
[CLSCompliant(false)]
#endif
public static void SetMeasurement(this ISpanData spanData, string name, ulong value,
MeasurementUnit unit = default) =>
spanData.SetMeasurement(name, new Measurement(value, unit));

/// <inheritdoc cref="SetMeasurement(Sentry.ISpanData,string,int,Sentry.MeasurementUnit)" />
public static void SetMeasurement(this ISpanData spanData, string name, double value,
MeasurementUnit unit = default) =>
spanData.SetMeasurement(name, new Measurement(value, unit));
}
8 changes: 8 additions & 0 deletions src/Sentry/Internal/NoOpSpan.cs
@@ -1,3 +1,5 @@
using Sentry.Protocol;

namespace Sentry.Internal;

/// <summary>
Expand Down Expand Up @@ -70,4 +72,10 @@ public void SetExtra(string key, object? value)
}

public SentryTraceHeader GetTraceHeader() => SentryTraceHeader.Empty;

public IReadOnlyDictionary<string, Measurement> Measurements => ImmutableDictionary<string, Measurement>.Empty;

public void SetMeasurement(string name, Measurement measurement)
{
}
}
4 changes: 4 additions & 0 deletions src/Sentry/Internal/NoOpTransaction.cs
@@ -1,3 +1,5 @@
using Sentry.Protocol;

namespace Sentry.Internal;

/// <summary>
Expand Down Expand Up @@ -86,8 +88,10 @@ public IReadOnlyList<string> Fingerprint
}

public IReadOnlyCollection<ISpan> Spans => ImmutableList<ISpan>.Empty;

public IReadOnlyCollection<Breadcrumb> Breadcrumbs => ImmutableList<Breadcrumb>.Empty;

public ISpan? GetLastActiveSpan() => default;

public void AddBreadcrumb(Breadcrumb breadcrumb) { }
}
28 changes: 26 additions & 2 deletions src/Sentry/Span.cs
@@ -1,6 +1,7 @@
using Sentry.Extensibility;
using Sentry.Internal;
using Sentry.Internal.Extensions;
using Sentry.Protocol;

namespace Sentry;

Expand Down Expand Up @@ -28,6 +29,16 @@ public class Span : ISpanData, IJsonSerializable
/// <inheritdoc />
public bool IsFinished => EndTimestamp is not null;

// Not readonly because of deserialization
private Dictionary<string, Measurement>? _measurements;

/// <inheritdoc />
public IReadOnlyDictionary<string, Measurement> Measurements => _measurements ??= new Dictionary<string, Measurement>();

/// <inheritdoc />
public void SetMeasurement(string name, Measurement measurement) =>
(_measurements ??= new Dictionary<string, Measurement>())[name] = measurement;

/// <inheritdoc />
public string Operation { get; set; }

Expand Down Expand Up @@ -88,7 +99,17 @@ public Span(ISpan tracer)
Status = tracer.Status;
IsSampled = tracer.IsSampled;
_extra = tracer.Extra.ToDictionary();
_tags = tracer is SpanTracer s ? s.InternalTags?.ToDictionary() : tracer.Tags.ToDictionary();

if (tracer is SpanTracer spanTracer)
{
_measurements = spanTracer.InternalMeasurements?.ToDictionary();
_tags = spanTracer.InternalTags?.ToDictionary();
}
else
{
_measurements = tracer.Measurements.ToDictionary();
_tags = tracer.Tags.ToDictionary();
}
}

/// <inheritdoc />
Expand All @@ -112,6 +133,7 @@ public void WriteTo(Utf8JsonWriter writer, IDiagnosticLogger? logger)
writer.WriteStringIfNotNull("timestamp", EndTimestamp);
writer.WriteStringDictionaryIfNotEmpty("tags", _tags!);
writer.WriteDictionaryIfNotEmpty("data", _extra!, logger);
writer.WriteDictionaryIfNotEmpty("measurements", _measurements, logger);

writer.WriteEndObject();
}
Expand All @@ -131,6 +153,7 @@ public static Span FromJson(JsonElement json)
var status = json.GetPropertyOrNull("status")?.GetString()?.Replace("_", "").ParseEnum<SpanStatus>();
var isSampled = json.GetPropertyOrNull("sampled")?.GetBoolean();
var tags = json.GetPropertyOrNull("tags")?.GetStringDictionaryOrNull()?.ToDictionary();
var measurements = json.GetPropertyOrNull("measurements")?.GetDictionaryOrNull(Measurement.FromJson);
var data = json.GetPropertyOrNull("data")?.GetDictionaryOrNull()?.ToDictionary();

return new Span(parentSpanId, operation)
Expand All @@ -143,7 +166,8 @@ public static Span FromJson(JsonElement json)
Status = status,
IsSampled = isSampled,
_tags = tags!,
_extra = data!
_extra = data!,
_measurements = measurements,
};
}

Expand Down
21 changes: 15 additions & 6 deletions src/Sentry/SpanTracer.cs
@@ -1,4 +1,5 @@
using Sentry.Internal;
using Sentry.Protocol;

namespace Sentry;

Expand Down Expand Up @@ -30,6 +31,16 @@ public class SpanTracer : ISpan
/// <inheritdoc />
public bool IsFinished => EndTimestamp is not null;

// Not readonly because of deserialization
internal Dictionary<string, Measurement>? InternalMeasurements { get; private set; }

/// <inheritdoc />
public IReadOnlyDictionary<string, Measurement> Measurements => InternalMeasurements ??= new Dictionary<string, Measurement>();

/// <inheritdoc />
public void SetMeasurement(string name, Measurement measurement) =>
(InternalMeasurements ??= new Dictionary<string, Measurement>())[name] = measurement;

/// <inheritdoc cref="ISpan.Operation" />
public string Operation { get; set; }

Expand All @@ -50,20 +61,18 @@ public class SpanTracer : ISpan
/// <inheritdoc />
public bool? IsSampled { get; internal set; }

private ConcurrentDictionary<string, string>? _tags;

internal ConcurrentDictionary<string, string>? InternalTags => _tags;
internal ConcurrentDictionary<string, string>? InternalTags { get; private set; }

/// <inheritdoc />
public IReadOnlyDictionary<string, string> Tags => _tags ??= new ConcurrentDictionary<string, string>();
public IReadOnlyDictionary<string, string> Tags => InternalTags ??= new ConcurrentDictionary<string, string>();

/// <inheritdoc />
public void SetTag(string key, string value) =>
(_tags ??= new ConcurrentDictionary<string, string>())[key] = value;
(InternalTags ??= new ConcurrentDictionary<string, string>())[key] = value;

/// <inheritdoc />
public void UnsetTag(string key) =>
(_tags ??= new ConcurrentDictionary<string, string>()).TryRemove(key, out _);
(InternalTags ??= new ConcurrentDictionary<string, string>()).TryRemove(key, out _);

private readonly ConcurrentDictionary<string, object?> _data = new();

Expand Down
25 changes: 12 additions & 13 deletions src/Sentry/Transaction.cs
Expand Up @@ -9,7 +9,7 @@ namespace Sentry;
/// <summary>
/// Sentry performance transaction.
/// </summary>
public class Transaction : ITransactionData, IJsonSerializable, IHasMeasurements
public class Transaction : ITransactionData, IJsonSerializable
{
/// <summary>
/// Transaction's event ID.
Expand Down Expand Up @@ -68,6 +68,16 @@ public SentryId TraceId
/// <inheritdoc />
public DateTimeOffset? EndTimestamp { get; internal set; } // internal for testing

// Not readonly because of deserialization
private Dictionary<string, Measurement>? _measurements;

/// <inheritdoc />
public IReadOnlyDictionary<string, Measurement> Measurements => _measurements ??= new Dictionary<string, Measurement>();

/// <inheritdoc />
public void SetMeasurement(string name, Measurement measurement) =>
(_measurements ??= new Dictionary<string, Measurement>())[name] = measurement;

/// <inheritdoc />
public string Operation
{
Expand Down Expand Up @@ -181,12 +191,6 @@ public IReadOnlyList<string> Fingerprint
/// </summary>
public IReadOnlyCollection<Span> Spans => _spans;

// Not readonly because of deserialization
private Dictionary<string, Measurement> _measurements = new();

/// <inheritdoc />
public IReadOnlyDictionary<string, Measurement> Measurements => _measurements;

/// <inheritdoc />
public bool IsFinished => EndTimestamp is not null;

Expand Down Expand Up @@ -262,14 +266,14 @@ public Transaction(ITransaction tracer)
_spans = tracer.Spans
.Where(s => s is not SpanTracer { IsSentryRequest: true }) // Filter sentry requests created by Sentry.OpenTelemetry.SentrySpanProcessor
.Select(s => new Span(s)).ToArray();
_measurements = tracer.Measurements.ToDictionary();

// Some items are not on the interface, but we only ever pass in a TransactionTracer anyway.
if (tracer is TransactionTracer transactionTracer)
{
SampleRate = transactionTracer.SampleRate;
DynamicSamplingContext = transactionTracer.DynamicSamplingContext;
TransactionProfiler = transactionTracer.TransactionProfiler;
_measurements = transactionTracer.Measurements.ToDictionary();
}
}

Expand All @@ -289,11 +293,6 @@ public Transaction(ITransaction tracer)
public void UnsetTag(string key) =>
_tags.Remove(key);

/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
public void SetMeasurement(string name, Measurement measurement) =>
_measurements[name] = measurement;

/// <inheritdoc />
public SentryTraceHeader GetTraceHeader() => new(
TraceId,
Expand Down
3 changes: 1 addition & 2 deletions src/Sentry/TransactionTracer.cs
Expand Up @@ -7,7 +7,7 @@ namespace Sentry;
/// <summary>
/// Transaction tracer.
/// </summary>
public class TransactionTracer : ITransaction, IHasMeasurements
public class TransactionTracer : ITransaction
{
private readonly IHub _hub;
private readonly SentryOptions? _options;
Expand Down Expand Up @@ -277,7 +277,6 @@ internal TransactionTracer(IHub hub, ITransactionContext context, TimeSpan? idle
public void UnsetTag(string key) => _tags.TryRemove(key, out _);

/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
public void SetMeasurement(string name, Measurement measurement) => _measurements[name] = measurement;

/// <inheritdoc />
Expand Down

0 comments on commit 3c3182d

Please sign in to comment.