Skip to content

Commit b963566

Browse files
committed
[refactor] ISpan直接关联ITracer,避免长时间埋点完成时,发现Builder已经被上传处理,导致埋点丢失。
1 parent f66fef5 commit b963566

File tree

8 files changed

+82
-37
lines changed

8 files changed

+82
-37
lines changed

NewLife.Core/Log/ISpan.cs

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public interface ISpan : IDisposable
2222
/// <summary>唯一标识。随线程上下文、Http、Rpc传递,作为内部片段的父级</summary>
2323
String Id { get; set; }
2424

25+
/// <summary>埋点名</summary>
26+
String Name { get; set; }
27+
2528
/// <summary>父级片段标识</summary>
2629
String? ParentId { get; set; }
2730

@@ -64,13 +67,22 @@ public interface ISpan : IDisposable
6467
public class DefaultSpan : ISpan
6568
{
6669
#region 属性
70+
/// <summary>跟踪器</summary>
71+
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
72+
public ITracer? Tracer { get; set; }
73+
6774
/// <summary>构建器</summary>
75+
[Obsolete]
6876
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
6977
public ISpanBuilder? Builder { get; set; }
7078

7179
/// <summary>唯一标识。随线程上下文、Http、Rpc传递,作为内部片段的父级</summary>
7280
public String Id { get; set; } = null!;
7381

82+
/// <summary>埋点名</summary>
83+
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
84+
public String Name { get; set; } = null!;
85+
7486
/// <summary>父级片段标识</summary>
7587
public String? ParentId { get; set; }
7688

@@ -115,8 +127,8 @@ public class DefaultSpan : ISpan
115127
public DefaultSpan() { }
116128

117129
/// <summary>实例化</summary>
118-
/// <param name="builder"></param>
119-
public DefaultSpan(ISpanBuilder builder) => Builder = builder;
130+
/// <param name="tracer"></param>
131+
public DefaultSpan(ITracer tracer) => Tracer = tracer;
120132

121133
static DefaultSpan()
122134
{
@@ -214,28 +226,32 @@ protected virtual void Finish()
214226
// 从本线程中清除跟踪标识
215227
Current = _parent;
216228

217-
var builder = Builder;
218-
if (builder == null) return;
229+
var tracer = Tracer;
230+
if (tracer == null) return;
219231

220-
var name = builder.Name;
232+
var name = Name;
221233
if (!name.IsNullOrEmpty())
222234
{
223-
// Builder这一批可能已经上传,重新取一次,以防万一
224-
builder = builder.Tracer?.BuildSpan(name);
235+
//!!! Builder这一批可能已经上传,重新取一次,以防万一。如果在星尘平台没见到埋点数据,大概率是这里的问题
236+
var builder = tracer?.BuildSpan(name);
225237
builder?.Finish(this);
226238
}
227239

228240
// 打断对Builder的引用,当前Span可能还被放在AsyncLocal字典中
229241
// 也有可能原来的Builder已经上传,现在加入了新的builder集合
242+
#pragma warning disable CS0612 // 类型或成员已过时
230243
Builder = null;
244+
#pragma warning restore CS0612 // 类型或成员已过时
231245
}
232246

233247
/// <summary>抛弃埋点,不计入采集</summary>
234248
/// <remarks>在Web应用中,经常遇到各种扫描,导致记录大量并不存在的异常埋点,此时需要抛弃这些404埋点</remarks>
235249
public virtual void Abandon()
236250
{
237251
_finished = 1;
238-
Builder = null;
252+
//Builder = null;
253+
254+
// 不能还给对象池,因为外部还有引用,Dispose尚未调用
239255
}
240256

241257
/// <summary>设置错误信息,ApiException除外</summary>
@@ -259,7 +275,7 @@ public virtual void SetError(Exception ex, Object? tag)
259275
Error = ex.GetMessage();
260276

261277
// 所有异常,独立记录埋点,便于按异常分类统计
262-
using var span = Builder?.Tracer?.NewSpan(name, tag);
278+
using var span = Tracer?.NewSpan(name, tag);
263279
span?.AppendTag(ex.ToString());
264280
if (span != null) span.StartTime = StartTime;
265281
}
@@ -271,7 +287,7 @@ public virtual void SetTag(Object? tag)
271287
{
272288
if (tag == null) return;
273289

274-
var len = Builder?.Tracer?.MaxTagLength ?? 1024;
290+
var len = Tracer?.MaxTagLength ?? 1024;
275291
if (len <= 0) return;
276292

277293
if (tag is String str)
@@ -296,8 +312,12 @@ public virtual void SetTag(Object? tag)
296312
/// <summary>清空已有数据</summary>
297313
public void Clear()
298314
{
315+
Tracer = null;
316+
#pragma warning disable CS0612 // 类型或成员已过时
299317
Builder = null;
318+
#pragma warning restore CS0612 // 类型或成员已过时
300319
Id = null!;
320+
Name = null!;
301321
ParentId = null;
302322
TraceId = null!;
303323
StartTime = 0;
@@ -323,8 +343,7 @@ public static class SpanExtension
323343
#region 扩展方法
324344
private static String? GetAttachParameter(ISpan span)
325345
{
326-
var builder = (span as DefaultSpan)?.Builder;
327-
var tracer = (builder as DefaultSpanBuilder)?.Tracer;
346+
var tracer = (span as DefaultSpan)?.Tracer;
328347
return tracer?.AttachParameter;
329348
}
330349

@@ -520,7 +539,7 @@ public static void AppendTag(this ISpan span, Object tag, Int64 value)
520539

521540
if (tag != null && span is DefaultSpan ds && ds.TraceFlag > 0)
522541
{
523-
var maxLength = ds.Builder?.Tracer?.MaxTagLength ?? 1024;
542+
var maxLength = ds.Tracer?.MaxTagLength ?? 1024;
524543
if (span.Tag.IsNullOrEmpty())
525544
span.SetTag(tag);
526545
else if (span.Tag.Length < maxLength)
@@ -546,7 +565,7 @@ public static void AppendTag(this ISpan span, HttpResponseMessage response)
546565

547566
if (span is DefaultSpan ds && ds.TraceFlag > 0)
548567
{
549-
var maxLength = ds.Builder?.Tracer?.MaxTagLength ?? 1024;
568+
var maxLength = ds.Tracer?.MaxTagLength ?? 1024;
550569
if (span.Tag.IsNullOrEmpty() || span.Tag.Length < maxLength)
551570
{
552571
// 判断类型和长度

NewLife.Core/Log/ISpanBuilder.cs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public class DefaultSpanBuilder : ISpanBuilder
6565
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
6666
public ITracer? Tracer { get; set; }
6767

68-
/// <summary>操作名</summary>
68+
/// <summary>埋点名</summary>
6969
public String Name { get; set; } = null!;
7070

7171
/// <summary>开始时间。Unix毫秒</summary>
@@ -133,17 +133,25 @@ public void Init(String name)
133133
public virtual ISpan Start()
134134
{
135135
DefaultSpan? span = null;
136-
if (Tracer is DefaultTracer tracer)
136+
var tracer = Tracer;
137+
if (tracer is DefaultTracer tracer2)
137138
{
138-
span = tracer.SpanPool.Get() as DefaultSpan;
139-
if (span != null) span.Builder = this;
139+
span = tracer2.SpanPool.Get() as DefaultSpan;
140+
if (span != null)
141+
{
142+
span.Tracer = tracer2;
143+
span.Name = Name;
144+
#pragma warning disable CS0612 // 类型或成员已过时
145+
span.Builder = this;
146+
#pragma warning restore CS0612 // 类型或成员已过时
147+
}
140148
}
141149

142-
span ??= new DefaultSpan(this);
150+
span ??= new DefaultSpan(tracer!);
143151
span.Start();
144152

145153
// 指示当前节点开始的后续节点强制采样
146-
if (span.TraceFlag == 0 && Tracer != null && Total < Tracer.MaxSamples) span.TraceFlag = 1;
154+
if (span.TraceFlag == 0 && tracer != null && Total < tracer.MaxSamples) span.TraceFlag = 1;
147155

148156
return span;
149157
}
@@ -205,9 +213,9 @@ public virtual void Finish(ISpan span)
205213
}
206214

207215
// 如果埋点没有加入链表,则归还对象池
208-
if (!flag && Tracer is DefaultTracer tracer2 && ds != null)
216+
if (!flag && Tracer is DefaultTracer tracer2)
209217
{
210-
ds.Clear();
218+
ds?.Clear();
211219
tracer2.SpanPool.Return(span);
212220
}
213221
}
@@ -232,13 +240,21 @@ internal void Return(IList<ISpan>? spans)
232240
/// <summary>清空已有数据</summary>
233241
public void Clear()
234242
{
243+
//!!! 不能清空Tracer,否则长时间Span完成时,Builder已被处理,Span无法创建新的Builder来统计埋点数据
235244
Tracer = null;
245+
236246
Name = null!;
237247
StartTime = 0;
238248
EndTime = 0;
239249
Value = 0;
240250
Samples = null;
241251
ErrorSamples = null;
252+
253+
_Total = 0;
254+
_Errors = 0;
255+
_Cost = 0;
256+
MaxCost = 0;
257+
MinCost = 0;
242258
}
243259

244260
/// <summary>已重载。</summary>

NewLife.Core/Log/ITracer.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ static DefaultTracer()
6666
{
6767
// 注册默认类型,便于Json反序列化时为接口属性创造实例
6868
var ioc = ObjectContainer.Current;
69-
ioc.AddTransient<ITracer, DefaultTracer>();
70-
ioc.AddTransient<ISpanBuilder, DefaultSpanBuilder>();
71-
ioc.AddTransient<ISpan, DefaultSpan>();
69+
ioc.TryAddTransient<ITracer, DefaultTracer>();
70+
ioc.TryAddTransient<ISpanBuilder, DefaultSpanBuilder>();
71+
ioc.TryAddTransient<ISpan, DefaultSpan>();
7272
}
7373
#endregion
7474

@@ -248,7 +248,7 @@ public virtual ISpan NewSpan(String name, Object? tag)
248248
{
249249
// 头尾是Xml/Json时,使用字符串格式
250250
var total = pk.Total;
251-
if (total >= 2 && (pk[0] == '{' || pk[0] == '<' || pk[total - 1] == '}' || pk[total - 1] == '>'))
251+
if (total >= 2 && (pk[0] == '{' || pk[0] == '<') && (pk[total - 1] == '}' || pk[total - 1] == '>'))
252252
span.Tag = pk.ToStr(null, 0, len);
253253
else
254254
span.Tag = pk.ToHex(len / 2);
@@ -406,7 +406,7 @@ private static ISpan CreateSpan(ITracer tracer, String method, Uri uri, HttpRequ
406406

407407
if (span is DefaultSpan ds && ds.TraceFlag > 0 && request != null)
408408
{
409-
var maxLength = ds.Builder?.Tracer?.MaxTagLength ?? 1024;
409+
var maxLength = ds.Tracer?.MaxTagLength ?? 1024;
410410
if (request.Content is ByteArrayContent content &&
411411
content.Headers.ContentLength != null &&
412412
content.Headers.ContentLength < 1024 * 8 &&

NewLife.Core/Model/Actor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ protected override void Dispose(Boolean disposing)
113113
{
114114
if (Active) return _task;
115115

116-
if (Tracer == null && TracerParent is DefaultSpan ds) Tracer = ds.Builder?.Tracer;
116+
if (Tracer == null && TracerParent is DefaultSpan ds) Tracer = ds.Tracer;
117117

118118
using var span = Tracer?.NewSpan("actor:Start", Name);
119119

NewLife.Core/Net/SessionBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ public Int32 Send(ReadOnlySpan<Byte> data)
337337

338338
if (!Open() || Client == null) return null;
339339

340-
using var span = Tracer?.NewSpan($"net:{Name}:Receive", BufferSize + "");
340+
using var span = Tracer?.NewSpan($"net:{Name}:Receive");
341341
try
342342
{
343343
var pk = new OwnerPacket(BufferSize);

NewLife.Core/Net/UdpSession.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ public IOwnerPacket Receive()
290290
if (Disposed) throw new ObjectDisposedException(GetType().Name);
291291
if (Server?.Client == null) throw new InvalidOperationException(nameof(Server));
292292

293-
using var span = Tracer?.NewSpan($"net:{Name}:Receive", Server.BufferSize + "");
293+
using var span = Tracer?.NewSpan($"net:{Name}:Receive");
294294
try
295295
{
296296
var ep = Remote.EndPoint as EndPoint;
@@ -314,7 +314,7 @@ public IOwnerPacket Receive()
314314
if (Disposed) throw new ObjectDisposedException(GetType().Name);
315315
if (Server?.Client == null) throw new InvalidOperationException(nameof(Server));
316316

317-
using var span = Tracer?.NewSpan($"net:{Name}:Receive", Server.BufferSize + "");
317+
using var span = Tracer?.NewSpan($"net:{Name}:Receive");
318318
try
319319
{
320320
var ep = Remote.EndPoint as EndPoint;

Samples/Zero.HttpServer/ClientTest.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ public static async Task HttpClientTest()
1717
XTrace.WriteLine("");
1818
XTrace.WriteLine("Http客户端开始连接!");
1919

20+
var tracer = DefaultTracer.Instance;
21+
using var span = tracer?.NewSpan(nameof(HttpClientTest));
22+
2023
// 基础请求
2124
var client = new HttpClient
2225
{
@@ -27,8 +30,11 @@ public static async Task HttpClientTest()
2730
XTrace.WriteLine(html);
2831

2932
// Api接口请求
30-
var http = new ApiHttpClient("http://127.0.0.5:8080");
31-
http.Log = XTrace.Log;
33+
var http = new ApiHttpClient("http://127.0.0.5:8080")
34+
{
35+
Tracer = tracer,
36+
Log = XTrace.Log
37+
};
3238

3339
// 请求接口,返回data部分
3440
var rs = await http.GetAsync<String>("/user", new { act = "Delete", uid = 1234 });
@@ -68,9 +74,13 @@ public static async Task WebSocketClientTest()
6874
XTrace.WriteLine("");
6975
XTrace.WriteLine("WebSocketClient开始连接!");
7076

77+
var tracer = DefaultTracer.Instance;
78+
using var span = tracer?.NewSpan(nameof(WebSocketClientTest));
79+
7180
var client = new WebSocketClient("ws://127.0.0.7:8080/ws")
7281
{
7382
Name = "小ws客户",
83+
Tracer = tracer,
7484
Log = XTrace.Log
7585
};
7686
if (client is TcpSession tcp) tcp.MaxAsync = 0;

XUnitTest.Core/Log/TracerTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ public void HttpRequestMessageUriTest()
380380
var request = new HttpRequestMessage(HttpMethod.Get, url);
381381
var span = tracer.NewSpan(request) as DefaultSpan;
382382

383-
Assert.Equal("http://sso.newlifex.com/user/query", span.Builder.Name);
383+
Assert.Equal("http://sso.newlifex.com/user/query", span.Name);
384384
Assert.StartsWith("GET http://sso.newlifex.com/user/query?id=12345", span.Tag);
385385
}
386386

@@ -389,7 +389,7 @@ public void HttpRequestMessageUriTest()
389389
var request = new HttpRequestMessage(HttpMethod.Get, url);
390390
var span = tracer.NewSpan(request) as DefaultSpan;
391391

392-
Assert.Equal("user/query", span.Builder.Name);
392+
Assert.Equal("user/query", span.Name);
393393
Assert.StartsWith("GET user/query?id=12345", span.Tag);
394394
}
395395
}
@@ -404,7 +404,7 @@ public void WebRequestUriTest()
404404
var request = WebRequest.CreateHttp(url);
405405
var span = tracer.NewSpan(request) as DefaultSpan;
406406

407-
Assert.Equal("http://sso.newlifex.com/user/query", span.Builder.Name);
407+
Assert.Equal("http://sso.newlifex.com/user/query", span.Name);
408408
Assert.Equal("GET http://sso.newlifex.com/user/query?id=12345", span.Tag);
409409
}
410410

@@ -413,7 +413,7 @@ public void WebRequestUriTest()
413413
// var request = WebRequest.CreateHttp(new Uri(url, UriKind.RelativeOrAbsolute));
414414
// var span = tracer.NewSpan(request) as DefaultSpan;
415415

416-
// Assert.Equal("http://sso.newlifex.com/user/query", span.Builder.Name);
416+
// Assert.Equal("http://sso.newlifex.com/user/query", span.Name);
417417
// Assert.Equal("/user/query?id=12345", span.Tag);
418418
//}
419419
}

0 commit comments

Comments
 (0)