/
ActivityCreationOptions.cs
187 lines (163 loc) · 7.28 KB
/
ActivityCreationOptions.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace System.Diagnostics
{
/// <summary>
/// ActivityCreationOptions is encapsulating all needed information which will be sent to the ActivityListener to decide about creating the Activity object and with what state.
/// The possible generic type parameters is <see cref="ActivityContext"/> or <see cref="string"/>
/// </summary>
public readonly struct ActivityCreationOptions<T>
{
private readonly ActivityTagsCollection? _samplerTags;
private readonly ActivityContext _context;
private readonly string? _traceState;
/// <summary>
/// Construct a new <see cref="ActivityCreationOptions{T}"/> object.
/// </summary>
/// <param name="source">The trace Activity source<see cref="ActivitySource"/> used to request creating the Activity object.</param>
/// <param name="name">The operation name of the Activity.</param>
/// <param name="parent">The requested parent to create the Activity object with. The parent either be a parent Id represented as string or it can be a parent context <see cref="ActivityContext"/>.</param>
/// <param name="kind"><see cref="ActivityKind"/> to create the Activity object with.</param>
/// <param name="tags">Key-value pairs list for the tags to create the Activity object with.<see cref="ActivityContext"/></param>
/// <param name="links"><see cref="ActivityLink"/> list to create the Activity object with.</param>
/// <param name="idFormat">The default Id format to use.</param>
internal ActivityCreationOptions(ActivitySource source, string name, T parent, ActivityKind kind, IEnumerable<KeyValuePair<string, object?>>? tags, IEnumerable<ActivityLink>? links, ActivityIdFormat idFormat)
{
Source = source;
Name = name;
Kind = kind;
Parent = parent;
Tags = tags;
Links = links;
IdFormat = idFormat;
if (IdFormat == ActivityIdFormat.Unknown && Activity.ForceDefaultIdFormat)
{
IdFormat = Activity.DefaultIdFormat;
}
_samplerTags = null;
_traceState = null;
if (parent is ActivityContext ac && ac != default)
{
_context = ac;
if (IdFormat == ActivityIdFormat.Unknown)
{
IdFormat = ActivityIdFormat.W3C;
}
_traceState = ac.TraceState;
}
else if (parent is string p && p != null)
{
if (IdFormat != ActivityIdFormat.Hierarchical)
{
if (ActivityContext.TryParse(p, null, out _context))
{
IdFormat = ActivityIdFormat.W3C;
}
if (IdFormat == ActivityIdFormat.Unknown)
{
IdFormat =ActivityIdFormat.Hierarchical;
}
}
else
{
_context = default;
}
}
else
{
_context = default;
if (IdFormat == ActivityIdFormat.Unknown)
{
IdFormat = Activity.Current != null ? Activity.Current.IdFormat : Activity.DefaultIdFormat;
}
}
}
/// <summary>
/// Retrieve the <see cref="ActivitySource"/> object.
/// </summary>
public ActivitySource Source { get; }
/// <summary>
/// Retrieve the name which requested to create the Activity object with.
/// </summary>
public string Name { get; }
/// <summary>
/// Retrieve the <see cref="ActivityKind"/> which requested to create the Activity object with.
/// </summary>
public ActivityKind Kind { get; }
/// <summary>
/// Retrieve the parent which requested to create the Activity object with. Parent will be either in form of string or <see cref="ActivityContext"/>.
/// </summary>
public T Parent { get; }
/// <summary>
/// Retrieve the tags which requested to create the Activity object with.
/// </summary>
public IEnumerable<KeyValuePair<string, object?>>? Tags { get; }
/// <summary>
/// Retrieve the list of <see cref="ActivityLink"/> which requested to create the Activity object with.
/// </summary>
public IEnumerable<ActivityLink>? Links { get; }
public ActivityTagsCollection SamplingTags
{
#if ALLOW_PARTIALLY_TRUSTED_CALLERS
[System.Security.SecuritySafeCriticalAttribute]
#endif
get
{
if (_samplerTags == null)
{
// Because the struct is readonly, we cannot directly assign _samplerTags. We have to workaround it by calling Unsafe.AsRef
Unsafe.AsRef(in _samplerTags) = new ActivityTagsCollection();
}
return _samplerTags!;
}
}
public ActivityTraceId TraceId
{
#if ALLOW_PARTIALLY_TRUSTED_CALLERS
[System.Security.SecuritySafeCriticalAttribute]
#endif
get
{
if (Parent is ActivityContext && IdFormat == ActivityIdFormat.W3C && _context == default)
{
Func<ActivityTraceId>? traceIdGenerator = Activity.TraceIdGenerator;
ActivityTraceId id = traceIdGenerator == null ? ActivityTraceId.CreateRandom() : traceIdGenerator();
// Because the struct is readonly, we cannot directly assign _context. We have to workaround it by calling Unsafe.AsRef
Unsafe.AsRef(in _context) = new ActivityContext(id, default, ActivityTraceFlags.None);
}
return _context.TraceId;
}
}
/// <summary>
/// Retrieve or initialize the trace state to use for the Activity we may create.
/// </summary>
public string? TraceState
{
#if ALLOW_PARTIALLY_TRUSTED_CALLERS
[System.Security.SecuritySafeCriticalAttribute]
#endif
get => _traceState;
#if ALLOW_PARTIALLY_TRUSTED_CALLERS
[System.Security.SecuritySafeCriticalAttribute]
#endif
init
{
_traceState = value;
}
}
// SetTraceState is to set the _traceState without the need of copying the whole structure.
#if ALLOW_PARTIALLY_TRUSTED_CALLERS
[System.Security.SecuritySafeCriticalAttribute]
#endif
internal void SetTraceState(string? traceState) => Unsafe.AsRef(in _traceState) = traceState;
/// <summary>
/// Retrieve Id format of to use for the Activity we may create.
/// </summary>
internal ActivityIdFormat IdFormat { get; }
// Helper to access the sampling tags. The SamplingTags Getter can allocate when not necessary.
internal ActivityTagsCollection? GetSamplingTags() => _samplerTags;
internal ActivityContext GetContext() => _context;
}
}