Commit 83c1f584 authored by Liuhaoyang's avatar Liuhaoyang

Init TracingContext

parent 3fc84f15
......@@ -27,16 +27,34 @@ namespace SkyWalking.Context.Trace
{
public class ExitSpan : StackBasedTracingSpan, IWithPeerInfo
{
private string _peer;
private int _peerId;
private readonly string _peer;
private readonly int _peerId;
protected ExitSpan(int spanId, int parentSpanId, string operationName,string peer) : base(spanId, parentSpanId, operationName)
public ExitSpan(int spanId, int parentSpanId, String operationName, String peer)
: base(spanId, parentSpanId, operationName)
{
_peer = peer;
_peerId = DictionaryUtil.NullValue;
}
protected ExitSpan(int spanId, int parentSpanId, int operationId,int peerId) : base(spanId, parentSpanId, operationId)
public ExitSpan(int spanId, int parentSpanId, int operationId, int peerId)
: base(spanId, parentSpanId, operationId)
{
_peer = null;
_peerId = peerId;
}
public ExitSpan(int spanId, int parentSpanId, int operationId, String peer)
: base(spanId, parentSpanId, operationId)
{
_peer = peer;
_peerId = DictionaryUtil.NullValue;
}
public ExitSpan(int spanId, int parentSpanId, String operationName, int peerId)
: base(spanId, parentSpanId, operationName)
{
_peer = null;
_peerId = peerId;
}
......@@ -54,6 +72,7 @@ namespace SkyWalking.Context.Trace
{
base.Start();
}
return base.Start();
}
......@@ -63,6 +82,7 @@ namespace SkyWalking.Context.Trace
{
base.Tag(key, value);
}
return this;
}
......@@ -72,6 +92,7 @@ namespace SkyWalking.Context.Trace
{
return base.SetLayer(layer);
}
return this;
}
......@@ -81,6 +102,7 @@ namespace SkyWalking.Context.Trace
{
return base.SetComponent(component);
}
return this;
}
......@@ -90,15 +112,13 @@ namespace SkyWalking.Context.Trace
{
return base.SetComponent(componentName);
}
return this;
}
public override string OperationName
{
get
{
return base.OperationName;
}
get { return base.OperationName; }
set
{
if (_stackDepth == 1)
......@@ -110,10 +130,7 @@ namespace SkyWalking.Context.Trace
public override int OperationId
{
get
{
return base.OperationId;
}
get { return base.OperationId; }
set
{
if (_stackDepth == 1)
......@@ -125,7 +142,7 @@ namespace SkyWalking.Context.Trace
public override SpanObject Transform()
{
var spanObject= base.Transform();
var spanObject = base.Transform();
if (_peerId != DictionaryUtil.NullValue)
{
......
......@@ -21,11 +21,11 @@ namespace SkyWalking.Context.Trace
{
public class LocalSpan : StackBasedTracingSpan
{
protected LocalSpan(int spanId, int parentSpanId, string operationName) : base(spanId, parentSpanId, operationName)
public LocalSpan(int spanId, int parentSpanId, string operationName) : base(spanId, parentSpanId, operationName)
{
}
protected LocalSpan(int spanId, int parentSpanId, int operationId) : base(spanId, parentSpanId, operationId)
public LocalSpan(int spanId, int parentSpanId, int operationId) : base(spanId, parentSpanId, operationId)
{
}
......
......@@ -16,19 +16,26 @@
*
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
using SkyWalking.Context.Trace;
using SkyWalking.Dictionary;
using SkyWalking.Dictionarys;
using SkyWalking.Sampling;
using SkyWalking.Utils;
namespace SkyWalking.Context
{
public class TracingContext: ITracerContext
public class TracingContext : ITracerContext
{
private long _lastWarningTimestamp = 0;
private ISampler _sampler;
private ITraceSegment _segment;
private Stack<ISpan> _activeSpanStacks;
private readonly ISampler _sampler;
private readonly ITraceSegment _segment;
private readonly Stack<ISpan> _activeSpanStacks;
private int _spanIdGenerator;
public TracingContext()
......@@ -38,48 +45,343 @@ namespace SkyWalking.Context
_activeSpanStacks = new Stack<ISpan>();
}
/// <summary>
/// Inject the context into the given carrier, only when the active span is an exit one.
/// </summary>
public void Inject(IContextCarrier carrier)
{
throw new System.NotImplementedException();
var span = InternalActiveSpan();
if (!span.IsExit)
{
throw new InvalidOperationException("Inject can be done only in Exit Span");
}
var spanWithPeer = span as IWithPeerInfo;
var peer = spanWithPeer.Peer;
var peerId = spanWithPeer.PeerId;
carrier.TraceSegmentId = _segment.TraceSegmentId;
carrier.SpanId = span.SpanId;
carrier.ParentApplicationInstanceId = _segment.ApplicationInstanceId;
if (DictionaryUtil.IsNull(peerId))
{
carrier.PeerHost = peer;
}
else
{
carrier.PeerId = peerId;
}
var refs = _segment.Refs;
var firstSpan = _activeSpanStacks.First();
var metaValue = GetMetaValue(refs);
carrier.EntryApplicationInstanceId = metaValue.entryApplicationInstanceId;
if (DictionaryUtil.IsNull(metaValue.operationId))
{
carrier.EntryOperationName = metaValue.operationName;
}
else
{
carrier.EntryOperationId = metaValue.operationId;
}
var parentOperationId = firstSpan.OperationId;
if (DictionaryUtil.IsNull(parentOperationId))
{
carrier.ParentOperationName = firstSpan.OperationName;
}
else
{
carrier.ParentOperationId = parentOperationId;
}
carrier.SetDistributedTraceIds(_segment.RelatedGlobalTraces);
}
/// <summary>
/// Extract the carrier to build the reference for the pre segment.
/// </summary>
public void Extract(IContextCarrier carrier)
{
throw new System.NotImplementedException();
var traceSegmentRef = new TraceSegmentRef(carrier);
_segment.Ref(traceSegmentRef);
_segment.RelatedGlobalTrace(carrier.DistributedTraceId);
var span = InternalActiveSpan();
if (span is EntrySpan)
{
span.Ref(traceSegmentRef);
}
}
public IContextSnapshot Capture { get; }
public ISpan ActiveSpan { get; }
/// <summary>
/// Capture the snapshot of current context.
/// </summary>
public IContextSnapshot Capture => InternalCapture();
public ISpan ActiveSpan => InternalActiveSpan();
public void Continued(IContextSnapshot snapshot)
{
throw new System.NotImplementedException();
var segmentRef = new TraceSegmentRef(snapshot);
_segment.Ref(segmentRef);
ActiveSpan.Ref(segmentRef);
_segment.RelatedGlobalTrace(snapshot.DistributedTraceId);
}
public string GetReadableGlobalTraceId()
{
throw new System.NotImplementedException();
return _segment.RelatedGlobalTraces.First()?.ToString();
}
/// <summary>
/// Create an entry span
/// </summary>
public ISpan CreateEntrySpan(string operationName)
{
throw new System.NotImplementedException();
if (!EnsureLimitMechanismWorking(out var noopSpan))
{
return noopSpan;
}
_activeSpanStacks.TryPeek(out var parentSpan);
var parentSpanId = parentSpan?.SpanId ?? -1;
if (parentSpan != null && parentSpan.IsEntry)
{
var entrySpan = (ISpan) DictionaryManager.OperationName.FindOnly(_segment.ApplicationId, operationName)
.InCondition(id =>
{
parentSpan.OperationId = id;
return parentSpan;
}, () =>
{
parentSpan.OperationName = operationName;
return parentSpan;
});
return entrySpan.Start();
}
else
{
var entrySpan = (ISpan) DictionaryManager.OperationName.FindOnly(_segment.ApplicationId, operationName)
.InCondition(id => new EntrySpan(_spanIdGenerator++, parentSpanId, id),
() => new EntrySpan(_spanIdGenerator++, parentSpanId, operationName));
entrySpan.Start();
_activeSpanStacks.Push(entrySpan);
return entrySpan;
}
}
/// <summary>
/// Create a local span
/// </summary>
public ISpan CreateLocalSpan(string operationName)
{
throw new System.NotImplementedException();
if (!EnsureLimitMechanismWorking(out var noopSpan))
{
return noopSpan;
}
_activeSpanStacks.TryPeek(out var parentSpan);
var parentSpanId = parentSpan?.SpanId ?? -1;
var span = (ISpan) DictionaryManager.OperationName
.FindOrPrepareForRegister(_segment.ApplicationId, operationName, false, false)
.InCondition(id => new LocalSpan(_spanIdGenerator++, parentSpanId, operationName),
() => new LocalSpan(_spanIdGenerator++, parentSpanId, operationName));
span.Start();
_activeSpanStacks.Push(span);
return span;
}
/// <summary>
/// Create an exit span
/// </summary>
public ISpan CreateExitSpan(string operationName, string remotePeer)
{
throw new System.NotImplementedException();
_activeSpanStacks.TryPeek(out var parentSpan);
if (parentSpan != null && parentSpan.IsExit)
{
return parentSpan.Start();
}
else
{
var parentSpanId = parentSpan?.SpanId ?? -1;
var exitSpan = (ISpan) DictionaryManager.NetworkAddress.Find(remotePeer)
.InCondition(peerId =>
{
if (IsLimitMechanismWorking())
{
return new NoopExitSpan(peerId);
}
return DictionaryManager.OperationName.FindOnly(_segment.ApplicationId, operationName)
.InCondition(id => new ExitSpan(_spanIdGenerator++, parentSpanId, id, peerId),
() => new ExitSpan(_spanIdGenerator++, parentSpanId, operationName, peerId));
},
() =>
{
if (IsLimitMechanismWorking())
{
return new NoopExitSpan(remotePeer);
}
return DictionaryManager.OperationName.FindOnly(_segment.ApplicationId, operationName)
.InCondition(id => new ExitSpan(_spanIdGenerator++, parentSpanId, id, remotePeer),
() => new ExitSpan(_spanIdGenerator++, parentSpanId, operationName,
remotePeer));
});
_activeSpanStacks.Push(exitSpan);
return exitSpan.Start();
}
}
/// <summary>
/// Stop the given span, if and only if this one is the top element of {@link #activeSpanStack}. Because the tracing
/// core must make sure the span must match in a stack module, like any program did.
/// </summary>
public void StopSpan(ISpan span)
{
throw new System.NotImplementedException();
_activeSpanStacks.TryPeek(out var lastSpan);
if (lastSpan == span)
{
if (lastSpan is AbstractTracingSpan tracingSpan)
{
if (tracingSpan.Finish(_segment))
{
_activeSpanStacks.Pop();
}
}
else
{
_activeSpanStacks.Pop();
}
}
else
{
throw new InvalidOperationException("Stopping the unexpected span = " + span);
}
if (_activeSpanStacks.Count == 0)
{
Finish();
}
}
private void Finish()
{
var finishedSegment = _segment.Finish(IsLimitMechanismWorking());
if (!_segment.HasRef && _segment.IsSingleSpanSegment)
{
if (!_sampler.TrySampling())
{
finishedSegment.IsIgnore = true;
}
}
ListenerManager.NotifyFinish(finishedSegment);
}
private ISpan InternalActiveSpan()
{
if (!_activeSpanStacks.TryPeek(out var span))
{
throw new InvalidOperationException("No active span.");
}
return span;
}
private IContextSnapshot InternalCapture()
{
var refs = _segment.Refs;
var snapshot =
new ContextSnapshot(_segment.TraceSegmentId, ActiveSpan.SpanId, _segment.RelatedGlobalTraces);
var metaValue = GetMetaValue(refs);
snapshot.EntryApplicationInstanceId = metaValue.entryApplicationInstanceId;
if (DictionaryUtil.IsNull(metaValue.operationId))
{
snapshot.EntryOperationName = metaValue.operationName;
}
else
{
snapshot.EntryOperationId = metaValue.operationId;
}
var parentSpan = _activeSpanStacks.First();
if (DictionaryUtil.IsNull(parentSpan.OperationId))
{
snapshot.ParentOperationName = parentSpan.OperationName;
}
else
{
snapshot.ParentOperationId = parentSpan.OperationId;
}
return snapshot;
}
private (string operationName, int operationId, int entryApplicationInstanceId) GetMetaValue(
IEnumerable<ITraceSegmentRef> refs)
{
if (refs != null && refs.Any())
{
var segmentRef = refs.First();
return (segmentRef.EntryOperationName, segmentRef.EntryOperationId,
segmentRef.EntryApplicationInstanceId);
}
else
{
var span = _activeSpanStacks.First();
return (span.OperationName, span.OperationId, _segment.ApplicationInstanceId);
}
}
private bool IsLimitMechanismWorking()
{
if (_spanIdGenerator < Config.AgentConfig.SpanLimitPerSegment)
{
return false;
}
var currentTimeMillis = DateTime.UtcNow.GetTimeMillis();
if (currentTimeMillis - _lastWarningTimestamp > 30 * 1000)
{
//todo log warning
_lastWarningTimestamp = currentTimeMillis;
}
return true;
}
private bool EnsureLimitMechanismWorking(out ISpan noopSpan)
{
if (IsLimitMechanismWorking())
{
var span = new NoopSpan();
_activeSpanStacks.Push(span);
noopSpan = span;
return false;
}
noopSpan = null;
return true;
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment