-
-
Notifications
You must be signed in to change notification settings - Fork 203
/
SpanTracer.cs
160 lines (127 loc) · 4.85 KB
/
SpanTracer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
using Sentry.Internal;
using Sentry.Protocol;
namespace Sentry;
/// <summary>
/// Transaction span tracer.
/// </summary>
public class SpanTracer : ISpan
{
private readonly IHub _hub;
private readonly SentryStopwatch _stopwatch = SentryStopwatch.StartNew();
internal TransactionTracer Transaction { get; }
/// <inheritdoc />
public SpanId SpanId { get; internal set; }
/// <inheritdoc />
public SpanId? ParentSpanId { get; }
/// <inheritdoc />
public SentryId TraceId { get; }
/// <inheritdoc />
public DateTimeOffset StartTimestamp { get; internal set; }
/// <inheritdoc />
public DateTimeOffset? EndTimestamp { get; internal set; }
/// <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; }
/// <inheritdoc cref="ISpan.Description" />
public string? Description { get; set; }
/// <inheritdoc cref="ISpan.Status" />
public SpanStatus? Status { get; set; }
/// <summary>
/// Used by the Sentry.OpenTelemetry.SentrySpanProcessor to mark a span as a Sentry request. Ideally we wouldn't
/// create these spans but since we can't avoid doing that, once we detect that it's a Sentry request we mark it
/// as such so that we can filter it when the transaction finishes and the TransactionTracer gets converted into
/// a Transaction.
/// </summary>
internal bool IsSentryRequest { get; set; }
/// <inheritdoc />
public bool? IsSampled { get; internal set; }
internal ConcurrentDictionary<string, string>? InternalTags { get; private set; }
/// <inheritdoc />
public IReadOnlyDictionary<string, string> Tags => InternalTags ??= new ConcurrentDictionary<string, string>();
/// <inheritdoc />
public void SetTag(string key, string value) =>
(InternalTags ??= new ConcurrentDictionary<string, string>())[key] = value;
/// <inheritdoc />
public void UnsetTag(string key) =>
(InternalTags ??= new ConcurrentDictionary<string, string>()).TryRemove(key, out _);
private readonly ConcurrentDictionary<string, object?> _data = new();
/// <inheritdoc />
public IReadOnlyDictionary<string, object?> Extra => _data;
/// <inheritdoc />
public void SetExtra(string key, object? value) => _data[key] = value;
/// <summary>
/// Initializes an instance of <see cref="SpanTracer"/>.
/// </summary>
public SpanTracer(
IHub hub,
TransactionTracer transaction,
SpanId? parentSpanId,
SentryId traceId,
string operation)
{
_hub = hub;
Transaction = transaction;
SpanId = SpanId.Create();
ParentSpanId = parentSpanId;
TraceId = traceId;
Operation = operation;
StartTimestamp = _stopwatch.StartDateTimeOffset;
}
internal SpanTracer(
IHub hub,
TransactionTracer transaction,
SpanId spanId,
SpanId? parentSpanId,
SentryId traceId,
string operation)
{
_hub = hub;
Transaction = transaction;
SpanId = spanId;
ParentSpanId = parentSpanId;
TraceId = traceId;
Operation = operation;
StartTimestamp = _stopwatch.StartDateTimeOffset;
}
/// <inheritdoc />
public ISpan StartChild(string operation) => Transaction.StartChild(null, parentSpanId:SpanId, operation: operation);
/// <summary>
/// Used to mark a span as unfinished when it was previously marked as finished. This allows us to reuse spans for
/// DB Connections that get reused by the underlying connection pool
/// </summary>
internal void Unfinish()
{
Status = null;
EndTimestamp = null;
}
/// <inheritdoc />
public void Finish()
{
Status ??= SpanStatus.Ok;
EndTimestamp ??= _stopwatch.CurrentDateTimeOffset;
}
/// <inheritdoc />
public void Finish(SpanStatus status)
{
Status = status;
Finish();
}
/// <inheritdoc />
public void Finish(Exception exception, SpanStatus status)
{
_hub.BindException(exception, this);
Finish(status);
}
/// <inheritdoc />
public void Finish(Exception exception) => Finish(exception, SpanStatusConverter.FromException(exception));
/// <inheritdoc />
public SentryTraceHeader GetTraceHeader() => new(TraceId, SpanId, IsSampled);
}