Unverified Commit 2f240672 authored by Lemon's avatar Lemon Committed by GitHub

Refactor tracing context (#139)

* Delete `ISkyWalkingClient` interface

* Use segment protocol V2

* Forget the old api. All context apis will be overwritten.

* Add segments define

* Add some apis

* Add carrierParser

* Add SegmentContextAccessor API

* Add SampledDelegate interface

* Add thread-safe  SamplerChainBuilder

* Add SegmentContextFactory

* Add ITracingContext Interface

* Refactoring the core API for tracing context

* remove utils package

* Resolve issue #57 : Provide percentage-based sampling

* Refactor HttpClient Tracing

* Fix header carrier

* Add async exitSpan sample

* Add Task.WhenAll sample

* Refactor EntityFrameworkCore tracing

* Refactor SqlClient & CAP Tracing

* Refactor Asp.Net tracing

* Remove outdated APIs
parent 91ab544c
{ {
"SkyWalking": { "SkyWalking": {
"ApplicationCode": "SkyWalking.Sample.AspNet", "ServiceName": "aspnet-sample",
"SpanLimitPerSegment": 300,
"Sampling": {
"SamplePer3Secs": -1
},
"Logging": { "Logging": {
"Level": "Information", "Level": "Debug",
"FilePath": "logs\\SkyWalking-{Date}.log" "FilePath": "/tmp/logs/SkyWalking-{Date}.log"
}, },
"Transport": { "Transport": {
"Interval": 3000, "Interval": 3000,
"PendingSegmentLimit": 30000,
"PendingSegmentTimeout": 1000,
"gRPC": { "gRPC": {
"Servers": "localhost:11800", "Servers": "localhost:11800",
"Timeout": 2000, "Timeout": 10000,
"ConnectTimeout": 10000 "ConnectTimeout": 10000
} }
} }
......
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace SkyWalking.Sample.Backend.Controllers
{
[Route("api/[controller]")]
public class DelayController : Controller
{
// GET
[HttpGet("{delay}")]
public async Task<string> Get(int delay)
{
await Task.Delay(delay);
return $"delay {delay}ms";
}
}
}
\ No newline at end of file
using SkyWalking.Tracing;
namespace SkyWalking.Sample.Backend.Sampling
{
public class CustomSamplingInterceptor : ISamplingInterceptor
{
public int Priority { get; } = 0;
public bool Invoke(SamplingContext samplingContext, Sampler next)
{
return next(samplingContext);
}
}
}
\ No newline at end of file
...@@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore; ...@@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using SkyWalking.Sample.Backend.Models; using SkyWalking.Sample.Backend.Models;
using SkyWalking.Sample.Backend.Sampling;
using SkyWalking.Tracing;
namespace SkyWalking.Sample.Backend namespace SkyWalking.Sample.Backend
{ {
...@@ -26,6 +28,8 @@ namespace SkyWalking.Sample.Backend ...@@ -26,6 +28,8 @@ namespace SkyWalking.Sample.Backend
sqliteConnection.Open(); sqliteConnection.Open();
services.AddEntityFrameworkSqlite().AddDbContext<SampleDbContext>(c => c.UseSqlite(sqliteConnection)); services.AddEntityFrameworkSqlite().AddDbContext<SampleDbContext>(c => c.UseSqlite(sqliteConnection));
services.AddSingleton<ISamplingInterceptor, CustomSamplingInterceptor>();
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
......
...@@ -9,11 +9,21 @@ namespace SkyWalking.Sample.Frontend.Controllers ...@@ -9,11 +9,21 @@ namespace SkyWalking.Sample.Frontend.Controllers
public class ValuesController : Controller public class ValuesController : Controller
{ {
// GET api/values // GET api/values
[HttpGet("/values")] [HttpGet]
public async Task<IEnumerable<string>> Get() public async Task<IEnumerable<string>> Get()
{ {
await new HttpClient().GetAsync("http://localhost:5002/api/values"); await new HttpClient().GetAsync("http://localhost:5002/api/values");
return new string[] { "value1", "value2" }; return new string[] {"value1", "value2"};
} }
[HttpGet("{id}")]
public async Task<string> Get(int id)
{
var client = new HttpClient();
Task.WhenAll(client.GetAsync("http://localhost:5002/api/delay/2000"),
client.GetAsync("http://localhost:5002/api/values"),
client.GetAsync("http://localhost:5002/api/delay/200"));
return await client.GetStringAsync("http://localhost:5002/api/delay/100");
}
} }
} }
\ No newline at end of file
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
} }
}, },
"SkyWalking": { "SkyWalking": {
"ApplicationCode": "asp-net-core-frontend" "ServiceName": "asp-net-core-frontend"
} }
} }
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,44 +16,26 @@ ...@@ -16,44 +16,26 @@
* *
*/ */
using System.Collections.Generic; namespace SkyWalking.Common
using SkyWalking.Context.Ids;
namespace SkyWalking.Context
{ {
public interface IContextCarrier public static class Components
{ {
public static readonly StringOrIntValue ASPNETCORE= new StringOrIntValue("AspNetCore");
DistributedTraceId DistributedTraceId { get; } public static readonly StringOrIntValue HTTPCLIENT = new StringOrIntValue("HttpClient");
int EntryApplicationInstanceId { get; set; }
string EntryOperationName { get; set; }
int EntryOperationId { get; set; } public static readonly StringOrIntValue ENTITYFRAMEWORKCORE = new StringOrIntValue("EntityFrameworkCore");
int ParentApplicationInstanceId { get; set; }
string ParentOperationName { get; set; }
int ParentOperationId { get; set; } public static readonly StringOrIntValue SQLCLIENT = new StringOrIntValue("SqlClient");
string PeerHost { get; set; }
int PeerId { get; set; } public static readonly StringOrIntValue CAP = new StringOrIntValue("CAP");
int SpanId { get; set; } public static readonly StringOrIntValue ENTITYFRAMEWORKCORE_SQLITE = new StringOrIntValue("EntityFrameworkCore.Sqlite");
ID TraceSegmentId { get; set; } public static readonly StringOrIntValue POMELO_ENTITYFRAMEWORKCORE_MYSQL = new StringOrIntValue("Pomelo.EntityFrameworkCore.MySql");
bool IsValid { get; } public static readonly StringOrIntValue NPGSQL_ENTITYFRAMEWORKCORE_POSTGRESQL = new StringOrIntValue("Npgsql.EntityFrameworkCore.PostgreSQL");
IContextCarrier Deserialize(string text); public static readonly StringOrIntValue ASPNET = new StringOrIntValue("AspNet");
string Serialize();
CarrierItem Items { get; }
void SetDistributedTraceIds(IEnumerable<DistributedTraceId> distributedTraceIds);
} }
} }
\ No newline at end of file
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* *
*/ */
namespace SkyWalking namespace SkyWalking.Common
{ {
public struct NullableValue public struct NullableValue
{ {
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* *
*/ */
namespace SkyWalking namespace SkyWalking.Common
{ {
public struct StringOrIntValue public struct StringOrIntValue
{ {
...@@ -29,6 +29,8 @@ namespace SkyWalking ...@@ -29,6 +29,8 @@ namespace SkyWalking
_stringValue = null; _stringValue = null;
} }
public bool HasValue => HasIntValue || HasStringValue;
public bool HasIntValue => _intValue != 0; public bool HasIntValue => _intValue != 0;
public bool HasStringValue => _stringValue != null; public bool HasStringValue => _stringValue != null;
...@@ -53,5 +55,11 @@ namespace SkyWalking ...@@ -53,5 +55,11 @@ namespace SkyWalking
{ {
return (_stringValue, _intValue); return (_stringValue, _intValue);
} }
public override string ToString()
{
if (HasIntValue) return _intValue.ToString();
return _stringValue;
}
} }
} }
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,30 +16,27 @@ ...@@ -16,30 +16,27 @@
* *
*/ */
using SkyWalking.Context.Ids; namespace SkyWalking.Common
namespace SkyWalking.Context
{ {
public interface IContextSnapshot public static class Tags
{ {
string EntryOperationName { get; set; } public static readonly string URL = "url";
string ParentOperationName { get; set; } public static readonly string PATH = "path";
DistributedTraceId DistributedTraceId { get; }
int EntryApplicationInstanceId { get; set; }
int SpanId { get; }
bool IsFromCurrent { get; } public static readonly string HTTP_METHOD = "http.method";
bool IsValid { get; } public static readonly string STATUS_CODE = "status_code";
ID TraceSegmentId { get; } public static readonly string DB_TYPE = "db.type";
int EntryOperationId { set; } public static readonly string DB_INSTANCE = "db.instance";
public static readonly string DB_STATEMENT = "db.statement";
int ParentOperationId { set; } public static readonly string DB_BIND_VARIABLES = "db.bind_vars";
public static readonly string MQ_TOPIC = "mq.topic";
} }
} }
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections.Generic;
namespace SkyWalking.Components
{
public class ComponentsDefine
{
public static readonly IComponent HttpClient = new OfficialComponent(2, "HttpClient");
public static readonly IComponent AspNetCore = new OfficialComponent(3001, "AspNetCore");
public static readonly IComponent EntityFrameworkCore = new OfficialComponent(3002, "EntityFrameworkCore");
public static readonly IComponent SqlClient = new OfficialComponent(3003, "SqlClient");
public static readonly IComponent CAP = new OfficialComponent(3004, "CAP");
public static readonly IComponent StackExchange_Redis = new OfficialComponent(3005, "StackExchange.Redis");
public static readonly IComponent SqlServer = new OfficialComponent(3006, "SqlServer");
public static readonly IComponent Npgsql = new OfficialComponent(3007, "Npgsql");
public static readonly IComponent MySqlConnector = new OfficialComponent(3008, "MySqlConnector");
public static readonly IComponent EntityFrameworkCore_InMemory = new OfficialComponent(3009, "EntityFrameworkCore.InMemory");
public static readonly IComponent EntityFrameworkCore_SqlServer = new OfficialComponent(3010, "EntityFrameworkCore.SqlServer");
public static readonly IComponent EntityFrameworkCore_Sqlite = new OfficialComponent(3011, "EntityFrameworkCore.Sqlite");
public static readonly IComponent Pomelo_EntityFrameworkCore_MySql = new OfficialComponent(3012, "Pomelo.EntityFrameworkCore.MySql");
public static readonly IComponent Npgsql_EntityFrameworkCore_PostgreSQL = new OfficialComponent(3013, "Npgsql.EntityFrameworkCore.PostgreSQL");
public static readonly IComponent InMemoryDatabase = new OfficialComponent(3014, "InMemoryDatabase");
public static readonly IComponent AspNet = new OfficialComponent(3015, "AspNet");
public static readonly IComponent MySqlData = new OfficialComponent(3016, "MySql.Data");
}
}
...@@ -21,7 +21,7 @@ using System; ...@@ -21,7 +21,7 @@ using System;
namespace SkyWalking.Config namespace SkyWalking.Config
{ {
[Config("SkyWalking")] [Config("SkyWalking")]
public class InstrumentationConfig public class InstrumentConfig
{ {
public string Namespace { get; set; } public string Namespace { get; set; }
...@@ -29,7 +29,14 @@ namespace SkyWalking.Config ...@@ -29,7 +29,14 @@ namespace SkyWalking.Config
public string ApplicationCode { get; set; } public string ApplicationCode { get; set; }
public string ServiceName { get; set; } public string ServiceName { get; set; }
public string[] HeaderVersions { get; set; }
}
public int SpanLimitPerSegment { get; set; } = 300; public static class HeaderVersions
{
public static string SW3 { get; } = "sw3";
public static string SW6 { get; } = "sw6";
} }
} }
\ No newline at end of file
...@@ -22,5 +22,7 @@ namespace SkyWalking.Config ...@@ -22,5 +22,7 @@ namespace SkyWalking.Config
public class SamplingConfig public class SamplingConfig
{ {
public int SamplePer3Secs { get; set; } = -1; public int SamplePer3Secs { get; set; } = -1;
public double Percentage { get; set; } = -1d;
} }
} }
\ No newline at end of file
...@@ -21,7 +21,7 @@ namespace SkyWalking.Config ...@@ -21,7 +21,7 @@ namespace SkyWalking.Config
[Config("SkyWalking", "Transport")] [Config("SkyWalking", "Transport")]
public class TransportConfig public class TransportConfig
{ {
public int PendingSegmentLimit { get; set; } = 30000; public int QueueSize { get; set; } = 30000;
/// <summary> /// <summary>
/// Flush Interval Millisecond /// Flush Interval Millisecond
...@@ -31,7 +31,7 @@ namespace SkyWalking.Config ...@@ -31,7 +31,7 @@ namespace SkyWalking.Config
/// <summary> /// <summary>
/// Data queued beyond this time will be discarded. /// Data queued beyond this time will be discarded.
/// </summary> /// </summary>
public int PendingSegmentTimeout { get; set; } = 1000; public int BatchSize { get; set; } = 3000;
public string ProtocolVersion { get; set; } = ProtocolVersions.V6; public string ProtocolVersion { get; set; } = ProtocolVersions.V6;
} }
......
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
namespace SkyWalking.Context
{
public interface IInjectable
{
IContextCarrier GetCarrier();
/// <summary>
/// @return peer, represent ipv4, ipv6, hostname, or cluster addresses list.
/// </summary>
/// <returns></returns>
String GetPeer();
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using SkyWalking.Transport;
namespace SkyWalking.Context.Ids
{
/// <inheritdoc />
/// <summary>
/// The <code>DistributedTraceId</code> presents a distributed call chain.
/// This call chain has an unique (service) entrance,
/// such as: Service : http://www.skywalking.com/cust/query, all the remote, called behind this service, rest remote,
/// db executions, are using the same <code>DistributedTraceId</code> even in different CLR process.
/// The <code>DistributedTraceId</code> contains only one string, and can NOT be reset, creating a new instance is the only option.
/// </summary>
public abstract class DistributedTraceId : IEquatable<DistributedTraceId>
{
private readonly ID _id;
protected DistributedTraceId(ID id)
{
_id = id;
}
protected DistributedTraceId(string id)
{
_id = new ID(id);
}
public string Encode => _id?.Encode;
public UniqueIdRequest ToUniqueId() => _id?.Transform();
public bool Equals(DistributedTraceId other)
{
if (other == null)
return false;
return _id?.Equals(other._id) ?? other._id == null;
}
public override bool Equals(object obj)
{
var id = obj as DistributedTraceId;
return Equals(id);
}
public override int GetHashCode() => _id != null ? _id.GetHashCode() : 0;
public override string ToString() => _id?.ToString();
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using SkyWalking.Transport;
namespace SkyWalking.Context.Ids
{
public class ID : IEquatable<ID>
{
private readonly long _part1;
private readonly long _part2;
private readonly long _part3;
private string _encoding;
public bool IsValid { get; }
public string Encode => _encoding ?? (_encoding = ToString());
public ID(long part1, long part2, long part3)
{
_part1 = part1;
_part2 = part2;
_part3 = part3;
IsValid = true;
}
public ID(string encodingString)
{
if (encodingString == null)
{
throw new ArgumentNullException(nameof(encodingString));
}
string[] idParts = encodingString.Split("\\.".ToCharArray(), 3);
for (int part = 0; part < 3; part++)
{
if (part == 0)
{
IsValid = long.TryParse(idParts[part], out _part1);
}
else if (part == 1)
{
IsValid = long.TryParse(idParts[part], out _part2);
}
else
{
IsValid = long.TryParse(idParts[part], out _part3);
}
if (!IsValid)
{
break;
}
}
}
public override string ToString()
{
return $"{_part1}.{_part2}.{_part3}";
}
public override int GetHashCode()
{
var result = (int)(_part1 ^ (_part1 >> 32));
result = 31 * result + (int)(_part2 ^ (_part2 >> 32));
result = 31 * result + (int)(_part3 ^ (_part3 >> 32));
return result;
}
public override bool Equals(object obj)
{
var id = obj as ID;
return Equals(id);
}
public bool Equals(ID other)
{
if (other == null)
return false;
if (this == other)
return true;
if (_part1 != other._part1)
return false;
if (_part2 != other._part2)
return false;
return _part3 == other._part3;
}
public UniqueIdRequest Transform()
{
var uniqueId = new UniqueIdRequest {Part1 = _part1, Part2 = _part2, Part3 = _part3};
return uniqueId;
}
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections.Generic;
using SkyWalking.Transport;
using SkyWalking.Components;
namespace SkyWalking.Context.Trace
{
/// <summary>
/// The <code>AbstractTracingSpan</code> represents a group of {@link ISpan} implementations, which belongs a real distributed trace.
/// </summary>
public abstract class AbstractTracingSpan : ISpan
{
protected readonly int _spanId;
protected readonly int _parnetSpanId;
protected Dictionary<string, string> _tags;
protected string _operationName;
protected int _operationId;
protected SpanLayer? _layer;
/// <summary>
/// The start time of this Span.
/// </summary>
protected long _startTime;
/// <summary>
/// The end time of this Span.
/// </summary>
protected long _endTime;
protected bool _errorOccurred = false;
protected int _componentId = 0;
protected string _componentName;
/// <summary>
/// Log is a concept from OpenTracing spec. <p> {@see https://github.com/opentracing/specification/blob/master/specification.md#log-structured-data}
/// </summary>
protected ICollection<LogDataEntity> _logs;
/// <summary>
/// The refs of parent trace segments, except the primary one. For most RPC call, {@link #refs} contains only one
/// element, but if this segment is a start span of batch process, the segment faces multi parents, at this moment,
/// we use this {@link #refs} to link them.
/// </summary>
protected ICollection<ITraceSegmentRef> _refs;
protected AbstractTracingSpan(int spanId, int parentSpanId, string operationName)
{
_operationName = operationName;
_spanId = spanId;
_parnetSpanId = parentSpanId;
}
protected AbstractTracingSpan(int spanId, int parentSpanId, int operationId)
{
_operationName = null;
_operationId = operationId;
_spanId = spanId;
_parnetSpanId = parentSpanId;
}
public abstract bool IsEntry { get; }
public abstract bool IsExit { get; }
public virtual int SpanId => _spanId;
public virtual string OperationName
{
get => _operationName;
set
{
_operationName = value;
_operationId = 0;
}
}
public virtual int OperationId
{
get => _operationId;
set
{
_operationId = value;
_operationName = null;
}
}
public virtual ISpan SetComponent(IComponent component)
{
_componentId = component.Id;
return this;
}
public virtual ISpan SetComponent(string componentName)
{
_componentName = componentName;
return this;
}
public virtual ISpan Tag(string key, string value)
{
if (_tags == null)
{
_tags = new Dictionary<string, string>();
}
_tags.Add(key, value);
return this;
}
public virtual ISpan SetLayer(SpanLayer layer)
{
_layer = layer;
return this;
}
/// <summary>
/// Record an exception event of the current walltime timestamp.
/// </summary>
public virtual ISpan Log(Exception exception)
{
EnsureLogs();
_logs.Add(new LogDataEntity.Builder()
.Add("event", "error")
.Add("error.kind", exception.GetType().FullName)
.Add("message", exception.Message)
.Add("stack", exception.StackTrace)
.Build(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()));
return this;
}
public virtual ISpan ErrorOccurred()
{
_errorOccurred = true;
return this;
}
public virtual ISpan Log(long timestamp, IDictionary<string, object> events)
{
EnsureLogs();
var builder = new LogDataEntity.Builder();
foreach (var @event in events)
{
builder.Add(@event.Key, @event.Value.ToString());
}
_logs.Add(builder.Build(timestamp));
return this;
}
public virtual ISpan Start()
{
_startTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
return this;
}
public virtual ISpan Start(long timestamp)
{
_startTime = timestamp;
return this;
}
public virtual void Ref(ITraceSegmentRef traceSegmentRef)
{
if (_refs == null)
{
_refs = new List<ITraceSegmentRef>();
}
if (!_refs.Contains(traceSegmentRef))
{
_refs.Add(traceSegmentRef);
}
}
/// <summary>
/// Finish the active Span. When it is finished, it will be archived by the given {@link TraceSegment}, which owners it
/// </summary>
/// <param name="owner"></param>
/// <returns></returns>
public virtual bool Finish(ITraceSegment owner)
{
_endTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
owner.Archive(this);
return true;
}
public virtual SpanRequest Transform()
{
var spanRequest = new SpanRequest
{
SpanId = _spanId,
ParentSpanId = _parnetSpanId,
StartTime = _startTime,
EndTime = _endTime,
OperationName = new StringOrIntValue(_operationId, _operationName),
Component = new StringOrIntValue(_componentId, _componentName),
IsError = _errorOccurred
};
if (IsEntry)
{
spanRequest.SpanType = 0;
}
else if (IsExit)
{
spanRequest.SpanType = 1;
}
else
{
spanRequest.SpanType = 2;
}
if (_layer.HasValue)
{
spanRequest.SpanLayer = (int) _layer.Value;
}
foreach (var tag in _tags)
{
spanRequest.Tags.Add(new KeyValuePair<string, string>(tag.Key, tag.Value));
}
if (_logs != null)
{
foreach (var logDataEntity in _logs)
{
spanRequest.Logs.Add(logDataEntity.Transform());
}
}
if (_refs == null) return spanRequest;
foreach (var traceSegmentRef in _refs)
{
spanRequest.References.Add(traceSegmentRef.Transform());
}
return spanRequest;
}
private void EnsureLogs()
{
if (_logs == null)
{
_logs = new LinkedList<LogDataEntity>();
}
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections.Generic;
using SkyWalking.Components;
namespace SkyWalking.Context.Trace
{
/// <summary>
/// The <code>AbstractSpan</code> represents the span's skeleton, which contains all open methods.
/// </summary>
public interface ISpan
{
/// <summary>
/// Set the component id, which defines in ComponentsDefine
/// </summary>
/// <param name="component"></param>
/// <returns></returns>
ISpan SetComponent(IComponent component);
/// <summary>
/// Only use this method in explicit skyWalking, like opentracing-skywalking-bridge. It it higher recommend
/// don't use this for performance consideration.
/// </summary>
/// <param name="componentName"></param>
/// <returns></returns>
ISpan SetComponent(string componentName);
/// <summary>
/// Set a key:value tag on the Span.
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
ISpan Tag(string key, string value);
ISpan SetLayer(SpanLayer layer);
/// <summary>
/// Record an exception event of the current walltime timestamp.
/// </summary>
/// <param name="exception"></param>
/// <returns></returns>
ISpan Log(Exception exception);
ISpan ErrorOccurred();
bool IsEntry { get; }
bool IsExit { get; }
ISpan Log(long timestamp, IDictionary<string, object> @event);
ISpan Start();
int SpanId { get; }
string OperationName { get; set; }
int OperationId { get; set; }
ISpan Start(long timestamp);
void Ref(ITraceSegmentRef traceSegmentRef);
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections.Generic;
using SkyWalking.Transport;
using SkyWalking.Context.Ids;
namespace SkyWalking.Context.Trace
{
public interface ITraceSegment
{
void Archive(AbstractTracingSpan finishedSpan);
ITraceSegment Finish(bool isSizeLimited);
int ApplicationId { get; }
int ApplicationInstanceId { get; }
IEnumerable<ITraceSegmentRef> Refs { get; }
IEnumerable<DistributedTraceId> RelatedGlobalTraces { get; }
ID TraceSegmentId { get; }
bool HasRef { get; }
bool IsIgnore { get; set; }
bool IsSingleSpanSegment { get; }
void Ref(ITraceSegmentRef refSegment);
void RelatedGlobalTrace(DistributedTraceId distributedTraceId);
SegmentRequest Transform();
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections.Generic;
using System.Collections.ObjectModel;
using SkyWalking.Transport;
namespace SkyWalking.Context.Trace
{
public class LogDataEntity
{
private readonly long _timestamp;
private readonly Dictionary<string, string> _logs;
private LogDataEntity(long timestamp, Dictionary<string, string> logs)
{
_timestamp = timestamp;
_logs = logs;
}
public IReadOnlyDictionary<string, string> Logs => new ReadOnlyDictionary<string, string>(_logs);
public class Builder
{
private readonly Dictionary<string, string> _logs;
public Builder()
{
_logs = new Dictionary<string, string>();
}
public Builder Add(IDictionary<string, string> fields)
{
foreach (var field in fields)
_logs.Add(field.Key, field.Value);
return this;
}
public Builder Add(string key, string value)
{
_logs.Add(key, value);
return this;
}
public LogDataEntity Build(long timestamp)
{
return new LogDataEntity(timestamp, _logs);
}
}
public LogDataRequest Transform()
{
var logMessage = new LogDataRequest();
logMessage.Timestamp = _timestamp;
foreach (var log in _logs)
{
logMessage.Data.Add(new KeyValuePair<string, string>(log.Key, log.Value));
}
return logMessage;
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace SkyWalking.Context.Trace
{
public enum SpanLayer
{
DB = 1,
RPC_FRAMEWORK = 2,
HTTP = 3,
MQ = 4,
CACHE = 5
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace SkyWalking.Context.Trace
{
public abstract class StackBasedTracingSpan : AbstractTracingSpan
{
protected int _stackDepth;
protected StackBasedTracingSpan(int spanId, int parentSpanId, string operationName)
: base(spanId, parentSpanId, operationName)
{
_stackDepth = 0;
}
protected StackBasedTracingSpan(int spanId, int parentSpanId, int operationId)
: base(spanId, parentSpanId, operationId)
{
_stackDepth = 0;
}
}
}
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,12 +16,12 @@ ...@@ -16,12 +16,12 @@
* *
*/ */
namespace SkyWalking.Context.Trace namespace SkyWalking
{ {
public interface IWithPeerInfo public interface IBase64Formatter
{ {
int PeerId { get; } string Decode(string value);
string Peer { get; } string Encode(string value);
} }
} }
\ No newline at end of file
...@@ -21,7 +21,7 @@ using System.Threading.Tasks; ...@@ -21,7 +21,7 @@ using System.Threading.Tasks;
namespace SkyWalking namespace SkyWalking
{ {
public interface ISkyWalkingAgentStartup public interface IInstrumentStartup
{ {
Task StartAsync(CancellationToken cancellationToken = default(CancellationToken)); Task StartAsync(CancellationToken cancellationToken = default(CancellationToken));
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
*/ */
using System; using System;
using SkyWalking.Common;
namespace SkyWalking namespace SkyWalking
{ {
......
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -17,28 +17,27 @@ ...@@ -17,28 +17,27 @@
*/ */
using System; using System;
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Context.Trace namespace SkyWalking.Tracing
{ {
public class NoopExitSpan : NoopSpan, IWithPeerInfo public static class SegmentSpanExtensions
{ {
public int PeerId => peerId; public static void ErrorOccurred(this SegmentSpan span, Exception exception = null)
public string Peer => peer;
private String peer;
private int peerId;
public NoopExitSpan(int peerId)
{ {
this.peerId = peerId; if (span == null)
} {
return;
}
public NoopExitSpan(String peer) span.IsError = true;
{ if (exception != null)
this.peer = peer; {
span.AddLog(LogEvent.Event("error"),
LogEvent.ErrorKind(exception.GetType().FullName),
LogEvent.Message(exception.Message),
LogEvent.ErrorStack(exception.StackTrace));
}
} }
public override bool IsExit { get; } = true;
} }
} }
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,19 +16,30 @@ ...@@ -16,19 +16,30 @@
* *
*/ */
using System; using SkyWalking.Common;
using SkyWalking.Transport;
namespace SkyWalking.Context.Trace namespace SkyWalking.Tracing
{ {
public interface ITraceSegmentRef : IEquatable<ITraceSegmentRef> public interface ICarrier
{ {
string EntryOperationName { get; } bool HasValue { get; }
int EntryOperationId { get; } bool? Sampled { get; }
int EntryApplicationInstanceId { get; } UniqueId TraceId { get; }
UniqueId ParentSegmentId { get; }
int ParentSpanId { get; }
SegmentReferenceRequest Transform(); int ParentServiceInstanceId { get; }
int EntryServiceInstanceId { get; }
StringOrIntValue NetworkAddress { get; }
StringOrIntValue EntryEndpoint { get; }
StringOrIntValue ParentEndpoint { get; }
} }
} }
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Tracing
{
public interface ICarrierFormatter
{
string Key { get; }
bool Enable { get; }
ICarrier Decode(string content);
string Encode(ICarrier carrier);
}
}
\ No newline at end of file
using System.Collections.Generic;
namespace SkyWalking.Tracing
{
public interface ICarrierHeaderCollection : IEnumerable<KeyValuePair<string, string>>
{
void Add(string key, string value);
}
}
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,14 +16,14 @@ ...@@ -16,14 +16,14 @@
* *
*/ */
using System.Collections.Generic; using SkyWalking.Tracing.Segments;
namespace SkyWalking.Context.Ids namespace SkyWalking.Tracing
{ {
public interface IDistributedTraceIdCollection public interface ICarrierPropagator
{ {
IReadOnlyList<DistributedTraceId> GetRelatedGlobalTraces(); void Inject(SegmentContext segmentContext, ICarrierHeaderCollection carrier);
void Append(DistributedTraceId distributedTraceId); ICarrier Extract(ICarrierHeaderCollection carrier);
} }
} }
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Tracing
{
public interface IEntrySegmentContextAccessor
{
SegmentContext Context { get; set; }
}
}
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,10 +16,12 @@ ...@@ -16,10 +16,12 @@
* *
*/ */
namespace SkyWalking.Context using SkyWalking.Tracing.Segments;
namespace SkyWalking.Tracing
{ {
public interface IIgnoreTracerContextListener public interface IExitSegmentContextAccessor
{ {
void AfterFinish(ITracerContext tracerContext); SegmentContext Context { get; set; }
} }
} }
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Tracing
{
public interface ILocalSegmentContextAccessor
{
SegmentContext Context { get; set; }
}
}
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,12 +16,10 @@ ...@@ -16,12 +16,10 @@
* *
*/ */
namespace SkyWalking namespace SkyWalking.Tracing
{ {
public interface ISampler public interface ISamplerChainBuilder
{ {
bool Sampled(); Sampler Build();
void ForceSampled();
} }
} }
\ No newline at end of file
...@@ -16,12 +16,14 @@ ...@@ -16,12 +16,14 @@
* *
*/ */
namespace SkyWalking.Config using SkyWalking.Tracing.Segments;
namespace SkyWalking.Tracing
{ {
public class RuntimeConfig public interface ISamplingInterceptor
{ {
public NullableValue ApplicationId { get; set; } int Priority { get; }
public NullableValue ApplicationInstance { get; set; } bool Invoke(SamplingContext samplingContext, Sampler next);
} }
} }
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0 * The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
*/ */
namespace SkyWalking.Components using SkyWalking.Common;
{ using SkyWalking.Tracing.Segments;
/// <summary>
/// The <code>Component</code> represents component library , which has been supported by skywalking namespace SkyWalking.Tracing
/// </summary> {
public interface IComponent public interface ISegmentContextFactory
{ {
int Id { get; } SegmentContext CreateEntrySegment(string operationName, ICarrier carrier);
string Name { get; } SegmentContext CreateLocalSegment(string operationName);
}
SegmentContext CreateExitSegment(string operationName, StringOrIntValue networkAddress);
void Release(SegmentContext segmentContext);
}
} }
\ No newline at end of file
...@@ -16,22 +16,19 @@ ...@@ -16,22 +16,19 @@
* *
*/ */
using SkyWalking.Config; using SkyWalking.Tracing.Segments;
namespace SkyWalking.Context namespace SkyWalking.Tracing
{ {
public class ContextCarrierFactory : IContextCarrierFactory public interface ITracingContext
{ {
private readonly InstrumentationConfig _config; SegmentContext CreateEntrySegmentContext(string operationName, ICarrierHeaderCollection carrierHeader);
public ContextCarrierFactory(IConfigAccessor configAccessor) SegmentContext CreateLocalSegmentContext(string operationName);
{
_config = configAccessor.Get<InstrumentationConfig>();
}
public IContextCarrier Create() SegmentContext CreateExitSegmentContext(string operationName, string networkAddress,
{ ICarrierHeaderCollection carrierHeader = default(ICarrierHeaderCollection));
return new ContextCarrier(_config.Namespace);
} void Release(SegmentContext segmentContext);
} }
} }
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,11 +16,10 @@ ...@@ -16,11 +16,10 @@
* *
*/ */
namespace SkyWalking.Context.Trace namespace SkyWalking.Tracing
{ {
public enum SegmentRefType public interface IUniqueIdGenerator
{ {
CrossProcess = 0, UniqueId Generate();
CrossThread = 1
} }
} }
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0 * The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
*/ */
namespace SkyWalking.Context namespace SkyWalking.Tracing
{ {
public interface IContextCarrierFactory public interface IUniqueIdParser
{ {
IContextCarrier Create(); bool TryParse(string text, out UniqueId uniqueId);
} }
} }
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using SkyWalking.Common;
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Tracing
{
public delegate bool Sampler(SamplingContext samplingContext);
public class SamplingContext
{
public string OperationName { get; }
public StringOrIntValue Peer { get; }
public StringOrIntValue EntryEndpoint { get; }
public StringOrIntValue ParentEndpoint { get; }
public SamplingContext(string operationName, StringOrIntValue peer, StringOrIntValue entryEndpoint,
StringOrIntValue parentEndpoint)
{
OperationName = operationName;
Peer = peer;
EntryEndpoint = entryEndpoint;
ParentEndpoint = parentEndpoint;
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace SkyWalking.Tracing.Segments
{
public class SegmentContext
{
public UniqueId SegmentId { get; }
public UniqueId TraceId { get; }
public SegmentSpan Span { get; }
public int ServiceId { get; }
public int ServiceInstanceId { get; }
public bool Sampled { get; }
public bool IsSizeLimited { get; } = false;
public SegmentReferenceCollection References { get; } = new SegmentReferenceCollection();
public SegmentContext(UniqueId traceId, UniqueId segmentId, bool sampled, int serviceId, int serviceInstanceId,
string operationName, SpanType spanType)
{
TraceId = traceId;
Sampled = sampled;
SegmentId = segmentId;
ServiceId = serviceId;
ServiceInstanceId = serviceInstanceId;
Span = new SegmentSpan(operationName, spanType);
}
}
}
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0 * The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
*/ */
using System; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using SkyWalking.Components; using SkyWalking.Common;
namespace SkyWalking.Context.Trace namespace SkyWalking.Tracing.Segments
{ {
public class NoopSpan : ISpan public class SegmentReference
{ {
public int SpanId => 0; public Reference Reference { get; set; }
public string OperationName { get => string.Empty; set { } } public UniqueId ParentSegmentId { get; set; }
public int OperationId { get => 0; set { } } public int ParentSpanId { get; set; }
public ISpan ErrorOccurred() public int ParentServiceInstanceId { get; set; }
{
return this; public int EntryServiceInstanceId { get; set; }
}
public StringOrIntValue NetworkAddress { get; set; }
public ISpan Log(Exception exception)
{ public StringOrIntValue EntryEndpoint { get; set; }
return this;
} public StringOrIntValue ParentEndpoint { get; set; }
}
public ISpan Log(long timestamp, IDictionary<string, object> @event)
{ public enum Reference
return this; {
} CrossProcess = 0,
CrossThread = 1
public void Ref(ITraceSegmentRef traceSegmentRef) }
{
} public class SegmentReferenceCollection : IEnumerable<SegmentReference>
{
public ISpan SetComponent(IComponent component) private readonly HashSet<SegmentReference> _references = new HashSet<SegmentReference>();
{
return this; public bool Add(SegmentReference reference)
} {
return _references.Add(reference);
public ISpan SetComponent(string componentName) }
{
return this; public IEnumerator<SegmentReference> GetEnumerator()
} {
return _references.GetEnumerator();
public ISpan SetLayer(SpanLayer layer) }
{
return this; IEnumerator IEnumerable.GetEnumerator()
} {
return _references.GetEnumerator();
public ISpan Start() }
{
return this; public int Count => _references.Count;
} }
}
public ISpan Start(long timestamp) \ No newline at end of file
{
return this;
}
public ISpan Tag(string key, string value)
{
return this;
}
public virtual bool IsEntry => false;
public virtual bool IsExit => false;
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using SkyWalking.Common;
namespace SkyWalking.Tracing.Segments
{
public class SegmentSpan
{
public int SpanId { get; } = 0;
public int ParentSpanId { get; } = -1;
public long StartTime { get; } = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
public long EndTime { get; private set; }
public StringOrIntValue OperationName { get; }
public StringOrIntValue Peer { get; set; }
public SpanType SpanType { get; }
public SpanLayer SpanLayer { get; set; }
public StringOrIntValue Component { get; set; }
public bool IsError { get; set; }
public TagCollection Tags { get; } = new TagCollection();
public LogCollection Logs { get; } = new LogCollection();
public SegmentSpan(string operationName, SpanType spanType)
{
OperationName = new StringOrIntValue(operationName);
SpanType = spanType;
}
public SegmentSpan AddTag(string key, string value)
{
Tags.AddTag(key, value);
return this;
}
public SegmentSpan AddTag(string key, long value)
{
Tags.AddTag(key, value.ToString());
return this;
}
public SegmentSpan AddTag(string key, bool value)
{
Tags.AddTag(key, value.ToString());
return this;
}
public void AddLog(params LogEvent[] events)
{
var log = new SpanLog(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), events);
Logs.AddLog(log);
}
public void Finish()
{
EndTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
}
}
public class TagCollection : IEnumerable<KeyValuePair<string, string>>
{
private readonly Dictionary<string, string> tags = new Dictionary<string, string>();
internal void AddTag(string key, string value)
{
tags[key] = value;
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return tags.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return tags.GetEnumerator();
}
}
public enum SpanType
{
Entry = 0,
Exit = 1,
Local = 2
}
public enum SpanLayer
{
DB = 1,
RPC_FRAMEWORK = 2,
HTTP = 3,
MQ = 4,
CACHE = 5
}
public class LogCollection : IEnumerable<SpanLog>
{
private readonly List<SpanLog> _logs = new List<SpanLog>();
internal void AddLog(SpanLog log)
{
_logs.Add(log);
}
public IEnumerator<SpanLog> GetEnumerator()
{
return _logs.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _logs.GetEnumerator();
}
}
public class SpanLog
{
private static readonly Dictionary<string, string> Empty = new Dictionary<string, string>();
public long Timestamp { get; }
public IReadOnlyDictionary<string, string> Data { get; }
public SpanLog(long timestamp, params LogEvent[] events)
{
Timestamp = timestamp;
Data = events?.ToDictionary(x => x.Key, x => x.Value) ?? Empty;
}
}
public class LogEvent
{
public string Key { get; }
public string Value { get; }
public LogEvent(string key, string value)
{
Key = key;
Value = value;
}
public static LogEvent Event(string value)
{
return new LogEvent("event", value);
}
public static LogEvent Message(string value)
{
return new LogEvent("message", value);
}
public static LogEvent ErrorKind(string value)
{
return new LogEvent("error.kind", value);
}
public static LogEvent ErrorStack(string value)
{
return new LogEvent("stack", value);
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
namespace SkyWalking.Tracing
{
public class UniqueId : IEquatable<UniqueId>
{
public long Part1 { get; }
public long Part2 { get; }
public long Part3 { get; }
public UniqueId(long part1, long part2, long part3)
{
Part1 = part1;
Part2 = part2;
Part3 = part3;
}
public override string ToString() => $"{Part1}.{Part2}.{Part3}";
public bool Equals(UniqueId other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (Part1 != other.Part1) return false;
if (Part2 != other.Part2) return false;
return Part3 == other.Part3;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (!(obj is UniqueId id)) return false;
return Equals(id);
}
public override int GetHashCode()
{
throw new NotImplementedException();
}
}
}
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,12 +16,12 @@ ...@@ -16,12 +16,12 @@
* *
*/ */
using SkyWalking.Context.Trace; using SkyWalking.Tracing.Segments;
namespace SkyWalking.Context namespace SkyWalking.Transport
{ {
public interface ITracingContextListener public interface ISegmentContextMapper
{ {
void AfterFinished(ITraceSegment traceSegment); SegmentRequest Map(SegmentContext segmentContext);
} }
} }
\ No newline at end of file
...@@ -18,12 +18,13 @@ ...@@ -18,12 +18,13 @@
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Transport namespace SkyWalking.Transport
{ {
public interface ISegmentDispatcher public interface ISegmentDispatcher
{ {
bool Dispatch(SegmentRequest segment); bool Dispatch(SegmentContext segmentContext);
Task Flush(CancellationToken token = default(CancellationToken)); Task Flush(CancellationToken token = default(CancellationToken));
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Common;
using SkyWalking.Transport; using SkyWalking.Transport;
namespace SkyWalking.Transport namespace SkyWalking.Transport
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
*/ */
using System.Collections.Generic; using System.Collections.Generic;
using SkyWalking.Common;
namespace SkyWalking.Transport namespace SkyWalking.Transport
{ {
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Common;
namespace SkyWalking.Transport namespace SkyWalking.Transport
{ {
...@@ -31,4 +32,4 @@ namespace SkyWalking.Transport ...@@ -31,4 +32,4 @@ namespace SkyWalking.Transport
Task HeartbeatAsync(int applicationInstance, long heartbeatTime, CancellationToken cancellationToken = default(CancellationToken)); Task HeartbeatAsync(int applicationInstance, long heartbeatTime, CancellationToken cancellationToken = default(CancellationToken));
} }
} }
\ No newline at end of file
...@@ -21,7 +21,6 @@ using Microsoft.Extensions.DependencyInjection; ...@@ -21,7 +21,6 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using SkyWalking.AspNetCore.Diagnostics; using SkyWalking.AspNetCore.Diagnostics;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Context;
using SkyWalking.Diagnostics; using SkyWalking.Diagnostics;
using SkyWalking.Diagnostics.EntityFrameworkCore; using SkyWalking.Diagnostics.EntityFrameworkCore;
using SkyWalking.Diagnostics.HttpClient; using SkyWalking.Diagnostics.HttpClient;
...@@ -30,7 +29,9 @@ using SkyWalking.Utilities.Configuration; ...@@ -30,7 +29,9 @@ using SkyWalking.Utilities.Configuration;
using SkyWalking.Utilities.DependencyInjection; using SkyWalking.Utilities.DependencyInjection;
using SkyWalking.Utilities.Logging; using SkyWalking.Utilities.Logging;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.Sampling;
using SkyWalking.Service; using SkyWalking.Service;
using SkyWalking.Tracing;
using SkyWalking.Transport; using SkyWalking.Transport;
using SkyWalking.Transport.Grpc; using SkyWalking.Transport.Grpc;
using SkyWalking.Transport.Grpc.V5; using SkyWalking.Transport.Grpc.V5;
...@@ -46,27 +47,51 @@ namespace SkyWalking.Agent.AspNetCore ...@@ -46,27 +47,51 @@ namespace SkyWalking.Agent.AspNetCore
{ {
throw new ArgumentNullException(nameof(services)); throw new ArgumentNullException(nameof(services));
} }
services.AddSingleton<IContextCarrierFactory, ContextCarrierFactory>();
services.AddSingleton<ISegmentDispatcher, AsyncQueueSegmentDispatcher>(); services.AddSingleton<ISegmentDispatcher, AsyncQueueSegmentDispatcher>();
services.AddSingleton<IExecutionService, SegmentReportService>();
services.AddSingleton<IExecutionService, RegisterService>(); services.AddSingleton<IExecutionService, RegisterService>();
services.AddSingleton<IExecutionService, PingService>(); services.AddSingleton<IExecutionService, PingService>();
services.AddSingleton<IExecutionService, SamplingRefreshService>();
services.AddSingleton<IExecutionService, ServiceDiscoveryV5Service>(); services.AddSingleton<IExecutionService, ServiceDiscoveryV5Service>();
services.AddSingleton<ISkyWalkingAgentStartup, SkyWalkingAgentStartup>(); services.AddSingleton<IExecutionService, SegmentReportService>();
services.AddSingleton<ISampler>(DefaultSampler.Instance); services.AddSingleton<IInstrumentStartup, InstrumentStartup>();
services.AddSingleton<IRuntimeEnvironment>(RuntimeEnvironment.Instance); services.AddSingleton<IRuntimeEnvironment>(RuntimeEnvironment.Instance);
services.AddSingleton<TracingDiagnosticProcessorObserver>(); services.AddSingleton<TracingDiagnosticProcessorObserver>();
services.AddSingleton<IConfigAccessor, ConfigAccessor>(); services.AddSingleton<IConfigAccessor, ConfigAccessor>();
services.AddSingleton<IHostedService, InstrumentationHostedService>(); services.AddSingleton<IHostedService, InstrumentationHostedService>();
services.AddSingleton<IEnvironmentProvider, HostingEnvironmentProvider>(); services.AddSingleton<IEnvironmentProvider, HostingEnvironmentProvider>();
services.AddGrpcTransport().AddLogging(); services.AddTracing().AddSampling().AddGrpcTransport().AddLogging();
services.AddSkyWalkingExtensions().AddAspNetCoreHosting().AddHttpClient().AddSqlClient() services.AddSkyWalkingExtensions().AddAspNetCoreHosting().AddHttpClient().AddSqlClient()
.AddEntityFrameworkCore(c => c.AddPomeloMysql().AddNpgsql().AddSqlite()); .AddEntityFrameworkCore(c => c.AddPomeloMysql().AddNpgsql().AddSqlite());
return services; return services;
} }
private static IServiceCollection AddTracing(this IServiceCollection services)
{
services.AddSingleton<ITracingContext, Tracing.TracingContext>();
services.AddSingleton<ICarrierPropagator, CarrierPropagator>();
services.AddSingleton<ICarrierFormatter, Sw3CarrierFormatter>();
services.AddSingleton<ICarrierFormatter, Sw6CarrierFormatter>();
services.AddSingleton<ISegmentContextFactory, SegmentContextFactory>();
services.AddSingleton<IEntrySegmentContextAccessor, EntrySegmentContextAccessor>();
services.AddSingleton<ILocalSegmentContextAccessor, LocalSegmentContextAccessor>();
services.AddSingleton<IExitSegmentContextAccessor, ExitSegmentContextAccessor>();
services.AddSingleton<ISamplerChainBuilder, SamplerChainBuilder>();
services.AddSingleton<IUniqueIdGenerator, UniqueIdGenerator>();
services.AddSingleton<IUniqueIdParser, UniqueIdParser>();
services.AddSingleton<ISegmentContextMapper, SegmentContextMapper>();
services.AddSingleton<IBase64Formatter, Base64Formatter>();
return services;
}
private static IServiceCollection AddSampling(this IServiceCollection services)
{
services.AddSingleton<SimpleCountSamplingInterceptor>();
services.AddSingleton<ISamplingInterceptor>(p => p.GetService<SimpleCountSamplingInterceptor>());
services.AddSingleton<IExecutionService>(p => p.GetService<SimpleCountSamplingInterceptor>());
services.AddSingleton<ISamplingInterceptor, RandomSamplingInterceptor>();
return services;
}
private static IServiceCollection AddGrpcTransport(this IServiceCollection services) private static IServiceCollection AddGrpcTransport(this IServiceCollection services)
{ {
services.AddSingleton<ISkyWalkingClientV5, SkyWalkingClientV5>(); services.AddSingleton<ISkyWalkingClientV5, SkyWalkingClientV5>();
......
...@@ -24,9 +24,9 @@ namespace SkyWalking.Agent.AspNetCore ...@@ -24,9 +24,9 @@ namespace SkyWalking.Agent.AspNetCore
{ {
internal class InstrumentationHostedService : IHostedService internal class InstrumentationHostedService : IHostedService
{ {
private readonly ISkyWalkingAgentStartup _startup; private readonly IInstrumentStartup _startup;
public InstrumentationHostedService(ISkyWalkingAgentStartup startup) public InstrumentationHostedService(IInstrumentStartup startup)
{ {
_startup = startup; _startup = startup;
} }
......
...@@ -18,10 +18,11 @@ ...@@ -18,10 +18,11 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Context;
using SkyWalking.Diagnostics; using SkyWalking.Diagnostics;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.Sampling;
using SkyWalking.Service; using SkyWalking.Service;
using SkyWalking.Tracing;
using SkyWalking.Transport; using SkyWalking.Transport;
using SkyWalking.Transport.Grpc; using SkyWalking.Transport.Grpc;
using SkyWalking.Transport.Grpc.V5; using SkyWalking.Transport.Grpc.V5;
...@@ -35,26 +36,45 @@ namespace SkyWalking.AspNet.Extensions ...@@ -35,26 +36,45 @@ namespace SkyWalking.AspNet.Extensions
{ {
public static IServiceCollection AddSkyWalkingCore(this IServiceCollection services) public static IServiceCollection AddSkyWalkingCore(this IServiceCollection services)
{ {
services.AddSingleton<IContextCarrierFactory, ContextCarrierFactory>();
services.AddSingleton<ISegmentDispatcher, AsyncQueueSegmentDispatcher>(); services.AddSingleton<ISegmentDispatcher, AsyncQueueSegmentDispatcher>();
services.AddSingleton<IExecutionService, SegmentReportService>();
services.AddSingleton<IExecutionService, RegisterService>(); services.AddSingleton<IExecutionService, RegisterService>();
services.AddSingleton<IExecutionService, PingService>(); services.AddSingleton<IExecutionService, PingService>();
services.AddSingleton<IExecutionService, SamplingRefreshService>();
services.AddSingleton<IExecutionService, ServiceDiscoveryV5Service>(); services.AddSingleton<IExecutionService, ServiceDiscoveryV5Service>();
services.AddSingleton<ISkyWalkingAgentStartup, SkyWalkingAgentStartup>(); services.AddSingleton<IExecutionService, SegmentReportService>();
services.AddSingleton<ISampler>(DefaultSampler.Instance); services.AddSingleton<IInstrumentStartup, InstrumentStartup>();
services.AddSingleton<IRuntimeEnvironment>(RuntimeEnvironment.Instance); services.AddSingleton<IRuntimeEnvironment>(RuntimeEnvironment.Instance);
services.AddSingleton<TracingDiagnosticProcessorObserver>(); services.AddSingleton<TracingDiagnosticProcessorObserver>();
services.AddSingleton<IConfigAccessor, ConfigAccessor>(); services.AddSingleton<IConfigAccessor, ConfigAccessor>();
services.AddSingleton<IEnvironmentProvider, HostingEnvironmentProvider>(); services.AddSingleton<IEnvironmentProvider, HostingEnvironmentProvider>();
services.AddSingleton<InstrumentRequestCallback>();
services.AddSingleton<ITracingContext, Tracing.TracingContext>();
services.AddSingleton<ICarrierPropagator, CarrierPropagator>();
services.AddSingleton<ICarrierFormatter, Sw3CarrierFormatter>();
services.AddSingleton<ICarrierFormatter, Sw6CarrierFormatter>();
services.AddSingleton<ISegmentContextFactory, SegmentContextFactory>();
services.AddSingleton<IEntrySegmentContextAccessor, EntrySegmentContextAccessor>();
services.AddSingleton<ILocalSegmentContextAccessor, LocalSegmentContextAccessor>();
services.AddSingleton<IExitSegmentContextAccessor, ExitSegmentContextAccessor>();
services.AddSingleton<ISamplerChainBuilder, SamplerChainBuilder>();
services.AddSingleton<IUniqueIdGenerator, UniqueIdGenerator>();
services.AddSingleton<IUniqueIdParser, UniqueIdParser>();
services.AddSingleton<ISegmentContextMapper, SegmentContextMapper>();
services.AddSingleton<IBase64Formatter, Base64Formatter>();
services.AddSingleton<SimpleCountSamplingInterceptor>();
services.AddSingleton<ISamplingInterceptor>(p => p.GetService<SimpleCountSamplingInterceptor>());
services.AddSingleton<IExecutionService>(p => p.GetService<SimpleCountSamplingInterceptor>());
services.AddSingleton<ISamplingInterceptor, RandomSamplingInterceptor>();
services.AddSingleton<ISkyWalkingClientV5, SkyWalkingClientV5>();
services.AddSingleton<ISegmentReporter, SegmentReporter>(); services.AddSingleton<ISegmentReporter, SegmentReporter>();
services.AddSingleton<ConnectionManager>(); services.AddSingleton<ConnectionManager>();
services.AddSingleton<IPingCaller, PingCaller>(); services.AddSingleton<IPingCaller, PingCaller>();
services.AddSingleton<IServiceRegister, ServiceRegister>(); services.AddSingleton<IServiceRegister, ServiceRegister>();
services.AddSingleton<IExecutionService, ConnectService>(); services.AddSingleton<IExecutionService, ConnectService>();
services.AddSingleton<ILoggerFactory, DefaultLoggerFactory>(); services.AddSingleton<ILoggerFactory, DefaultLoggerFactory>();
services.AddSingleton<ISkyWalkingClientV5, SkyWalkingClientV5>();
return services; return services;
} }
} }
......
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,34 +16,39 @@ ...@@ -16,34 +16,39 @@
* *
*/ */
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Web;
using SkyWalking.Tracing;
namespace SkyWalking.Context.Ids namespace SkyWalking.AspNet
{ {
public class DistributedTraceIdCollection : IDistributedTraceIdCollection public class HttpRequestCarrierHeaderCollection : ICarrierHeaderCollection
{ {
private readonly List<DistributedTraceId> _relatedGlobalTraces; private readonly Dictionary<string, string> _headers;
public DistributedTraceIdCollection() public HttpRequestCarrierHeaderCollection(HttpRequest httpRequest)
{ {
_relatedGlobalTraces = new List<DistributedTraceId>(); _headers = new Dictionary<string, string>();
foreach (var key in httpRequest.Headers.AllKeys)
{
_headers[key] = httpRequest.Headers[key];
}
} }
public IReadOnlyList<DistributedTraceId> GetRelatedGlobalTraces() public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{ {
return _relatedGlobalTraces.AsReadOnly(); return _headers.GetEnumerator();
} }
public void Append(DistributedTraceId distributedTraceId) IEnumerator IEnumerable.GetEnumerator()
{ {
if (_relatedGlobalTraces.Count > 0 && _relatedGlobalTraces[0] is NewDistributedTraceId) return _headers.GetEnumerator();
{ }
_relatedGlobalTraces.RemoveAt(0);
} public void Add(string key, string value)
if (!_relatedGlobalTraces.Contains(distributedTraceId)) {
{ throw new System.NotImplementedException();
_relatedGlobalTraces.Add(distributedTraceId);
}
} }
} }
} }
\ No newline at end of file
...@@ -17,74 +17,88 @@ ...@@ -17,74 +17,88 @@
*/ */
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Components; using CommonServiceLocator;
using SkyWalking.Context; using SkyWalking.Tracing;
using SkyWalking.Context.Tag; using SpanLayer = SkyWalking.Tracing.Segments.SpanLayer;
using SkyWalking.Context.Trace;
namespace SkyWalking.AspNet namespace SkyWalking.AspNet
{ {
public class HttpTracingHandler : DelegatingHandler public class HttpTracingHandler : DelegatingHandler
{ {
private readonly IContextCarrierFactory _contextCarrierFactory;
public HttpTracingHandler() public HttpTracingHandler()
: this(new HttpClientHandler()) : this(new HttpClientHandler())
{ {
} }
public HttpTracingHandler(HttpMessageHandler innerHandler) public HttpTracingHandler(HttpMessageHandler innerHandler)
: this(innerHandler, CommonServiceLocator.ServiceLocator.Current.GetInstance<IContextCarrierFactory>())
{
}
private HttpTracingHandler(HttpMessageHandler innerHandler, IContextCarrierFactory contextCarrierFactory)
{ {
InnerHandler = innerHandler; InnerHandler = innerHandler;
_contextCarrierFactory = contextCarrierFactory;
} }
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var peer = $"{request.RequestUri.Host}:{request.RequestUri.Port}"; var tracingContext = ServiceLocator.Current.GetInstance<ITracingContext>();
var contextCarrier = _contextCarrierFactory.Create(); var operationName = request.RequestUri.ToString();
var span = ContextManager.CreateExitSpan(request.RequestUri.ToString(), contextCarrier, peer); var networkAddress = $"{request.RequestUri.Host}:{request.RequestUri.Port}";
var context = tracingContext.CreateExitSegmentContext(operationName, networkAddress,
new CarrierHeaderCollection(request.Headers));
try try
{ {
Tags.Url.Set(span, request.RequestUri.ToString()); context.Span.SpanLayer = SpanLayer.HTTP;
span.AsHttp(); context.Span.Component = Common.Components.HTTPCLIENT;
span.SetComponent(ComponentsDefine.HttpClient); context.Span.AddTag(Common.Tags.URL, request.RequestUri.ToString());
Tags.HTTP.Method.Set(span, request.Method.ToString()); context.Span.AddTag(Common.Tags.PATH, request.RequestUri.PathAndQuery);
foreach (var item in contextCarrier.Items) context.Span.AddTag(Common.Tags.HTTP_METHOD, request.Method.ToString());
request.Headers.Add(item.HeadKey, item.HeadValue); var response = await base.SendAsync(request, cancellationToken);
var statusCode = (int) response.StatusCode;
if (request.Method.Method != "GET") if (statusCode >= 400)
{ {
// record request body data context.Span.ErrorOccurred();
if (!request.Content.Headers.ContentType?.MediaType.ToLower().Contains("multipart/form-data")??false)
{
string bodyStr = await request.Content.ReadAsStringAsync();
span.Log(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), new Dictionary<string, object> { { "Body", bodyStr } });
}
} }
var response = await base.SendAsync(request, cancellationToken); context.Span.AddTag(Common.Tags.STATUS_CODE, statusCode);
Tags.StatusCode.Set(span, response.StatusCode.ToString());
return response; return response;
} }
catch (Exception e) catch (Exception exception)
{ {
span.ErrorOccurred().Log(e); context.Span.ErrorOccurred(exception);
throw; throw;
} }
finally finally
{ {
ContextManager.StopSpan(span); tracingContext.Release(context);
}
}
private class CarrierHeaderCollection : ICarrierHeaderCollection
{
private readonly HttpRequestHeaders _headers;
public CarrierHeaderCollection(HttpRequestHeaders headers)
{
_headers = headers;
}
public void Add(string key, string value)
{
_headers.Add(key, value);
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
} }
} }
} }
......
...@@ -19,13 +19,14 @@ ...@@ -19,13 +19,14 @@
using CommonServiceLocator; using CommonServiceLocator;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System.Web; using System.Web;
using Nito.AsyncEx;
using SkyWalking.AspNet.Extensions; using SkyWalking.AspNet.Extensions;
namespace SkyWalking.AspNet namespace SkyWalking.AspNet
{ {
public class SkyWalkingModule : IHttpModule public class InstrumentModule : IHttpModule
{ {
public SkyWalkingModule() public InstrumentModule()
{ {
var serviceProvider = new ServiceCollection().AddSkyWalkingCore().BuildServiceProvider(); var serviceProvider = new ServiceCollection().AddSkyWalkingCore().BuildServiceProvider();
var serviceLocatorProvider = new ServiceProviderLocator(serviceProvider); var serviceLocatorProvider = new ServiceProviderLocator(serviceProvider);
...@@ -34,15 +35,17 @@ namespace SkyWalking.AspNet ...@@ -34,15 +35,17 @@ namespace SkyWalking.AspNet
public void Init(HttpApplication application) public void Init(HttpApplication application)
{ {
var startup = ServiceLocator.Current.GetInstance<ISkyWalkingAgentStartup>(); var startup = ServiceLocator.Current.GetInstance<IInstrumentStartup>();
AsyncContext.Run(() => startup.StartAsync()); AsyncContext.Run(() => startup.StartAsync());
var requestCallback = ServiceLocator.Current.GetInstance<SkyWalkingApplicationRequestCallback>(); var requestCallback = ServiceLocator.Current.GetInstance<InstrumentRequestCallback>();
application.BeginRequest += requestCallback.ApplicationOnBeginRequest; application.BeginRequest += requestCallback.ApplicationOnBeginRequest;
application.EndRequest += requestCallback.ApplicationOnEndRequest; application.EndRequest += requestCallback.ApplicationOnEndRequest;
} }
public void Dispose() public void Dispose()
{ {
var startup = ServiceLocator.Current.GetInstance<IInstrumentStartup>();
AsyncContext.Run(() => startup.StopAsync());
} }
} }
} }
\ No newline at end of file
...@@ -20,15 +20,15 @@ using Microsoft.Web.Infrastructure.DynamicModuleHelper; ...@@ -20,15 +20,15 @@ using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using System.Web; using System.Web;
using SkyWalking.AspNet; using SkyWalking.AspNet;
[assembly:PreApplicationStartMethod(typeof(SkyWalkingModuleRegister), "Register")] [assembly:PreApplicationStartMethod(typeof(InstrumentModuleFactory), nameof(InstrumentModuleFactory.Create))]
namespace SkyWalking.AspNet namespace SkyWalking.AspNet
{ {
public class SkyWalkingModuleRegister public class InstrumentModuleFactory
{ {
public static void Register() public static void Create()
{ {
DynamicModuleUtility.RegisterModule(typeof(SkyWalkingModule)); DynamicModuleUtility.RegisterModule(typeof(InstrumentModule));
} }
} }
} }
\ No newline at end of file
...@@ -17,26 +17,27 @@ ...@@ -17,26 +17,27 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.IO;
using System.Web; using System.Web;
using SkyWalking.Components; using SkyWalking.Common;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Context; using SkyWalking.Tracing;
using SkyWalking.Context.Tag; using SkyWalking.Tracing.Segments;
using SkyWalking.Context.Trace; using SpanLayer = SkyWalking.Tracing.Segments.SpanLayer;
namespace SkyWalking.AspNet namespace SkyWalking.AspNet
{ {
internal class SkyWalkingApplicationRequestCallback internal class InstrumentRequestCallback
{ {
private readonly IContextCarrierFactory _contextCarrierFactory; private readonly InstrumentConfig _config;
private readonly InstrumentationConfig _config; private readonly ITracingContext _tracingContext;
private readonly IEntrySegmentContextAccessor _contextAccessor;
public SkyWalkingApplicationRequestCallback(IConfigAccessor configAccessor, IContextCarrierFactory carrierFactory) public InstrumentRequestCallback(IConfigAccessor configAccessor, ITracingContext tracingContext,
IEntrySegmentContextAccessor contextAccessor)
{ {
_config = configAccessor.Get<InstrumentationConfig>(); _config = configAccessor.Get<InstrumentConfig>();
_contextCarrierFactory = carrierFactory; _tracingContext = tracingContext;
_contextAccessor = contextAccessor;
} }
public void ApplicationOnBeginRequest(object sender, EventArgs e) public void ApplicationOnBeginRequest(object sender, EventArgs e)
...@@ -44,113 +45,57 @@ namespace SkyWalking.AspNet ...@@ -44,113 +45,57 @@ namespace SkyWalking.AspNet
var httpApplication = sender as HttpApplication; var httpApplication = sender as HttpApplication;
var httpContext = httpApplication.Context; var httpContext = httpApplication.Context;
if(httpContext.Request.HttpMethod == "OPTIONS") if (httpContext.Request.HttpMethod == "OPTIONS")
{ {
//asp.net Exclude OPTIONS request //asp.net Exclude OPTIONS request
return; return;
} }
var context = _tracingContext.CreateEntrySegmentContext(httpContext.Request.Path,
var carrier = _contextCarrierFactory.Create(); new HttpRequestCarrierHeaderCollection(httpContext.Request));
foreach (var item in carrier.Items) context.Span.SpanLayer = SpanLayer.HTTP;
item.HeadValue = httpContext.Request.Headers[item.HeadKey]; context.Span.Peer = new StringOrIntValue(httpContext.Request.UserHostAddress);
var httpRequestSpan = ContextManager.CreateEntrySpan($"{_config.ApplicationCode} {httpContext.Request.Path}", carrier); context.Span.Component = Common.Components.ASPNET;
httpRequestSpan.AsHttp(); context.Span.AddTag(Tags.URL, httpContext.Request.Url.OriginalString);
httpRequestSpan.SetComponent(ComponentsDefine.AspNet); context.Span.AddTag(Tags.PATH, httpContext.Request.Path);
Tags.Url.Set(httpRequestSpan, httpContext.Request.Path); context.Span.AddTag(Tags.HTTP_METHOD, httpContext.Request.HttpMethod);
Tags.HTTP.Method.Set(httpRequestSpan, httpContext.Request.HttpMethod); context.Span.AddLog(LogEvent.Event("AspNet BeginRequest"),
LogEvent.Message(
var dictLog = new Dictionary<string, object> $"Request starting {httpContext.Request.Url.Scheme} {httpContext.Request.HttpMethod} {httpContext.Request.Url.OriginalString}"));
{
{"event", "AspNet BeginRequest"},
{"message", $"Request starting {httpContext.Request.Url.Scheme} {httpContext.Request.HttpMethod} {httpContext.Request.Url.OriginalString}"}
};
// record request body data
SetBodyData(httpContext.Request, dictLog);
httpRequestSpan.Log(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), dictLog);
httpContext.Items.Add("span_Context", ContextManager.ActiveContext);
} }
public void ApplicationOnEndRequest(object sender, EventArgs e) public void ApplicationOnEndRequest(object sender, EventArgs e)
{ {
var context = _contextAccessor.Context;
if (context == null)
{
return;
}
var httpApplication = sender as HttpApplication; var httpApplication = sender as HttpApplication;
var httpContext = httpApplication.Context; var httpContext = httpApplication.Context;
ITracerContext context=null;
if (httpContext.Request.HttpMethod == "OPTIONS") if (httpContext.Request.HttpMethod == "OPTIONS")
{ {
//asp.net Exclude OPTIONS request //asp.net Exclude OPTIONS request
return; return;
} }
var httpRequestSpan = ContextManager.ActiveSpan;
if (httpRequestSpan == null)
{
// ContextManager.ActiveSpan is null, from httpContext.Items
if(!httpContext.Items.Contains("span_Context"))
return;
context = httpContext.Items["span_Context"] as ITracerContext;
if (context == null)
return;
httpRequestSpan = context.ActiveSpan;
if (httpRequestSpan == null)
return;
}
var statusCode = httpContext.Response.StatusCode; var statusCode = httpContext.Response.StatusCode;
if (statusCode >= 400) if (statusCode >= 400)
{ {
httpRequestSpan.ErrorOccurred(); context.Span.ErrorOccurred();
} }
Tags.StatusCode.Set(httpRequestSpan, statusCode.ToString());
var exception = httpContext.Error; var exception = httpContext.Error;
if (exception != null) if (exception != null)
{ {
httpRequestSpan.ErrorOccurred().Log(exception); context.Span.ErrorOccurred(exception);
} }
httpRequestSpan.Log(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), context.Span.AddLog(LogEvent.Event("AspNet EndRequest"),
new Dictionary<string, object> LogEvent.Message(
{ $"Request finished {httpContext.Response.StatusCode} {httpContext.Response.ContentType}"));
{"event", "AspNet EndRequest"},
{"message", $"Request finished {httpContext.Response.StatusCode} {httpContext.Response.ContentType}"}
});
ContextManager.StopSpan(httpRequestSpan, context); _tracingContext.Release(context);
}
/// <summary>
/// record request body data
/// </summary>
/// <param name="request"></param>
/// <param name="dict"></param>
private void SetBodyData(HttpRequest request, Dictionary<string, object> dict)
{
if (request.HttpMethod == "GET")
{
return;
}
if (dict == null)
dict = new Dictionary<string, object>();
if (request.ContentType?.ToLower().Contains("multipart/form-data")??false)
{
dict.Add("ContentLength", request.ContentLength);
return;
}
var stearm = request.GetBufferedInputStream();
using (StreamReader sr = new StreamReader(stearm))
{
var bodyStr = sr.ReadToEnd();
dict.Add("Body", bodyStr);
}
} }
} }
} }
\ No newline at end of file
...@@ -28,5 +28,6 @@ ...@@ -28,5 +28,6 @@
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="Microsoft.Web.Infrastructure" Version="1.0.0" /> <PackageReference Include="Microsoft.Web.Infrastructure" Version="1.0.0" />
<PackageReference Include="Nito.AsyncEx.Context" Version="1.1.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,19 +16,21 @@ ...@@ -16,19 +16,21 @@
* *
*/ */
using SkyWalking.Context.Trace; using System;
using System.Text;
namespace SkyWalking.Context.Tag namespace SkyWalking
{ {
public class StringTag : AbstractTag<string> public class Base64Formatter : IBase64Formatter
{ {
public StringTag(string tagKey) : base(tagKey) public string Decode(string value)
{ {
return value == null ? value : Encoding.UTF8.GetString(Convert.FromBase64String(value));
} }
public override void Set(ISpan span, string tagValue) public string Encode(string value)
{ {
span.Tag(Key, tagValue); return value == null ? value : Convert.ToBase64String(Encoding.UTF8.GetBytes(value));
} }
} }
} }
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
using System.Threading; using System.Threading;
namespace SkyWalking.Utils namespace SkyWalking.Common
{ {
public class AtomicInteger public class AtomicInteger
{ {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
...@@ -20,7 +20,7 @@ using System.Linq; ...@@ -20,7 +20,7 @@ using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
namespace SkyWalking.Utils namespace SkyWalking.Common
{ {
public static class DnsHelpers public static class DnsHelpers
{ {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace SkyWalking.Utils namespace SkyWalking.Common
{ {
internal static class EnumerableExtensions internal static class EnumerableExtensions
{ {
......
...@@ -16,36 +16,32 @@ ...@@ -16,36 +16,32 @@
* *
*/ */
using System; using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
namespace SkyWalking.AspNet namespace SkyWalking.Common
{ {
internal static class AsyncContext internal static class PlatformInformation
{ {
public static void Run(Func<Task> task) private const string OSX = "Mac OS X";
private const string LINUX = "Linux";
private const string WINDOWS = "Windows";
public static string GetOSName()
{ {
using (new ContextScope()) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
Task.Run(async () => await task()).GetAwaiter().GetResult(); return WINDOWS;
} }
} if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
private class ContextScope : IDisposable
{
private readonly SynchronizationContext _current;
public ContextScope()
{ {
_current = SynchronizationContext.Current; return LINUX;
SynchronizationContext.SetSynchronizationContext(null);
} }
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
public void Dispose()
{ {
SynchronizationContext.SetSynchronizationContext(_current); return OSX;
} }
return "Unknown";
} }
} }
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace SkyWalking.Utils namespace SkyWalking.Common
{ {
public static class StackExtensions public static class StackExtensions
{ {
......
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0 * The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
*/ */
namespace SkyWalking.Components using System;
{
public class OfficialComponent : IComponent namespace SkyWalking.Common
{ {
public OfficialComponent(int id, string name) public static class StringOrIntValueHelpers
{ {
Id = id; public static StringOrIntValue ParseStringOrIntValue(string value)
Name = name; {
} return value.StartsWith("#") ? new StringOrIntValue(new string(value.AsSpan().Slice(1, value.Length - 1).ToArray())) : new StringOrIntValue(int.Parse(value));
}
public int Id { get; } }
public string Name { get; }
}
} }
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace SkyWalking.Context
{
public class CarrierItemHead : CarrierItem
{
public CarrierItemHead(CarrierItem next, string @namespace) : base(string.Empty, string.Empty, next, @namespace)
{
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections.Generic;
using System.Linq;
using SkyWalking.Context.Ids;
namespace SkyWalking.Context
{
public class ContextCarrier : IContextCarrier
{
private ID _traceSegmentId;
/// <summary>
/// id of parent span
/// </summary>
private int _spanId = -1;
/// <summary>
/// id of parent application instance
/// </summary>
private int _parentApplicationInstanceId = 0;
/// <summary>
/// id of first application instance in this distributed trace
/// </summary>
private int _entryApplicationInstanceId = 0;
/// <summary>
/// peer(ipv4/ipv6/hostname + port) of the server , from client side .
/// </summary>
private string _peerHost;
private int _peerId;
/// <summary>
/// Operation/Service name of the first one in this distributed trace .
/// </summary>
private string _entryOperationName;
private int _entryOperationId;
/// <summary>
/// Operation/Service name of the parent one in this distributed trace .
/// </summary>
private string _parentOperationName;
private int _parentOperationId;
private DistributedTraceId _primaryDistributedTraceId;
private readonly string _namespace;
public ContextCarrier(string @namespace)
{
_namespace = @namespace;
}
public DistributedTraceId DistributedTraceId => _primaryDistributedTraceId;
public int EntryApplicationInstanceId
{
get => _entryApplicationInstanceId;
set => _entryApplicationInstanceId = value;
}
public string EntryOperationName
{
get => _entryOperationName;
set => _entryOperationName = "#" + value;
}
public int EntryOperationId
{
get => _entryOperationId;
set => _entryOperationId = value;
}
public int ParentApplicationInstanceId
{
get => _parentApplicationInstanceId;
set => _parentApplicationInstanceId = value;
}
public string ParentOperationName
{
get => _parentOperationName;
set => _parentOperationName = "#" + value;
}
public int ParentOperationId
{
get => _parentOperationId;
set => _parentOperationId = value;
}
public string PeerHost
{
get => _peerHost;
set => _peerHost = "#" + value;
}
public int PeerId
{
get => _peerId;
set => _peerId = value;
}
public int SpanId
{
get => _spanId;
set => _spanId = value;
}
public ID TraceSegmentId
{
get => _traceSegmentId;
set => _traceSegmentId = value;
}
public bool IsValid
{
get
{
return _traceSegmentId != null
&& _traceSegmentId.IsValid
&& _spanId > -1
&& _parentApplicationInstanceId != 0
&& _entryApplicationInstanceId != 0
&& !string.IsNullOrEmpty(_peerHost)
&& !string.IsNullOrEmpty(_parentOperationName)
&& !string.IsNullOrEmpty(_entryOperationName)
&& _primaryDistributedTraceId != null;
}
}
public IContextCarrier Deserialize(string text)
{
string[] parts = text?.Split("|".ToCharArray(), 8);
if (parts?.Length == 8)
{
_traceSegmentId = new ID(parts[0]);
_spanId = int.Parse(parts[1]);
_parentApplicationInstanceId = int.Parse(parts[2]);
_entryApplicationInstanceId = int.Parse(parts[3]);
_peerHost = parts[4];
_entryOperationName = parts[5];
_parentOperationName = parts[6];
_primaryDistributedTraceId = new PropagatedTraceId(parts[7]);
}
return this;
}
public string Serialize()
{
if (!IsValid)
{
return string.Empty;
}
return string.Join("|",
TraceSegmentId.Encode,
SpanId.ToString(),
ParentApplicationInstanceId.ToString(),
EntryApplicationInstanceId.ToString(),
PeerHost,
EntryOperationName,
ParentOperationName,
PrimaryDistributedTraceId.Encode);
}
public DistributedTraceId PrimaryDistributedTraceId => _primaryDistributedTraceId;
public CarrierItem Items
{
get
{
var carrierItem = new SW3CarrierItem(this, null, _namespace);
var head = new CarrierItemHead(carrierItem, _namespace);
return head;
}
}
public void SetDistributedTraceIds(IEnumerable<DistributedTraceId> distributedTraceIds)
{
_primaryDistributedTraceId = distributedTraceIds.FirstOrDefault();
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections.Generic;
using System.Threading;
using SkyWalking.Context.Trace;
namespace SkyWalking.Context
{
/// <summary>
/// Context manager controls the whole context of tracing. Since .NET server application runs as same as Java,
/// We also provide the CONTEXT propagation based on ThreadLocal mechanism.
/// Meaning, each segment also related to singe thread.
/// </summary>
public class ContextManager : ITracingContextListener, IIgnoreTracerContextListener
{
static ContextManager()
{
var manager = new ContextManager();
TracingContext.ListenerManager.Add(manager);
IgnoredTracerContext.ListenerManager.Add(manager);
}
private static readonly AsyncLocal<ITracerContext> _context = new AsyncLocal<ITracerContext>();
private static ITracerContext GetOrCreateContext(string operationName, bool forceSampling)
{
var context = _context.Value;
if (context == null)
{
if (string.IsNullOrEmpty(operationName))
{
// logger.debug("No operation name, ignore this trace.");
_context.Value = new IgnoredTracerContext();
}
else
{
if (RuntimeEnvironment.Instance.Initialized)
{
// var suffixIdx = operationName.LastIndexOf('.');
// if (suffixIdx > -1 && AgentConfig.IgnoreSuffix.Contains(operationName.Substring(suffixIdx)))
// {
// _context.Value = new IgnoredTracerContext();
// }
// else
// {
var sampler = DefaultSampler.Instance;
if (forceSampling || sampler.Sampled())
{
_context.Value = new TracingContext();
}
else
{
_context.Value = new IgnoredTracerContext();
}
// }
}
else
{
_context.Value = new IgnoredTracerContext();
}
}
}
return _context.Value;
}
private static ITracerContext Context => _context.Value;
public static string GlobalTraceId
{
get
{
if (_context.Value != null)
{
return _context.Value.GetReadableGlobalTraceId();
}
return "N/A";
}
}
public static IContextSnapshot Capture => _context.Value?.Capture;
public static IDictionary<string, object> ContextProperties => _context.Value?.Properties;
public static ISpan CreateEntrySpan(string operationName, IContextCarrier carrier)
{
var samplingService = DefaultSampler.Instance;
if (carrier != null && carrier.IsValid)
{
samplingService.ForceSampled();
var context = GetOrCreateContext(operationName, true);
var span = context.CreateEntrySpan(operationName);
context.Extract(carrier);
return span;
}
else
{
var context = GetOrCreateContext(operationName, false);
return context.CreateEntrySpan(operationName);
}
}
public static ISpan CreateLocalSpan(string operationName)
{
var context = GetOrCreateContext(operationName, false);
return context.CreateLocalSpan(operationName);
}
public static ISpan CreateExitSpan(string operationName, IContextCarrier carrier, string remotePeer)
{
var context = GetOrCreateContext(operationName, false);
var span = context.CreateExitSpan(operationName, remotePeer);
context.Inject(carrier);
return span;
}
public static ISpan CreateExitSpan(string operationName, string remotePeer)
{
var context = GetOrCreateContext(operationName, false);
var span = context.CreateExitSpan(operationName, remotePeer);
return span;
}
public static void Inject(IContextCarrier carrier)
{
Context?.Inject(carrier);
}
public static void Extract(IContextCarrier carrier)
{
Context?.Extract(carrier);
}
public static void Continued(IContextSnapshot snapshot)
{
if (snapshot.IsValid && !snapshot.IsFromCurrent)
{
Context?.Continued(snapshot);
}
}
public static void StopSpan()
{
StopSpan(ActiveSpan);
}
public static ISpan ActiveSpan
{
get { return Context?.ActiveSpan; }
}
public static ITracerContext ActiveContext
{
get
{
return Context;
}
}
public static void StopSpan(ISpan span, ITracerContext context=null)
{
if (Context != null)
{
Context.StopSpan(span);
}
else if (context != null)
{
context.StopSpan(span);
}
}
public void AfterFinished(ITraceSegment traceSegment)
{
_context.Value = null;
}
public void AfterFinish(ITracerContext tracerContext)
{
_context.Value = null;
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections.Generic;
using System.Linq;
using SkyWalking.Context.Ids;
namespace SkyWalking.Context
{
public class ContextSnapshot : IContextSnapshot
{
/// <summary>
/// Trace Segment Id of the parent trace segment
/// </summary>
private readonly ID _traceSegmentId;
/// <summary>
/// span id of the parent span , in parent trace segment
/// </summary>
private readonly int _spanId = -1;
private string _entryOperationName;
private string _parentOperationName;
private readonly DistributedTraceId _primaryDistributedTraceId;
private NullableValue _entryApplicationInstanceId = NullableValue.Null;
public ContextSnapshot(ID traceSegmentId, int spanId, IEnumerable<DistributedTraceId> distributedTraceIds)
{
_traceSegmentId = traceSegmentId;
_spanId = spanId;
_primaryDistributedTraceId = distributedTraceIds?.FirstOrDefault();
}
public string EntryOperationName
{
get => _entryOperationName;
set => _entryOperationName = "#" + value;
}
public string ParentOperationName
{
get => _parentOperationName;
set => _parentOperationName = "#" + value;
}
public DistributedTraceId DistributedTraceId => _primaryDistributedTraceId;
public int EntryApplicationInstanceId
{
get => _entryApplicationInstanceId.Value;
set => _entryApplicationInstanceId = new NullableValue(value);
}
public int SpanId => _spanId;
public bool IsFromCurrent => _traceSegmentId.Equals(ContextManager.Capture.TraceSegmentId);
public bool IsValid => _traceSegmentId != null
&& _spanId > -1
&& _entryApplicationInstanceId.HasValue
&& _primaryDistributedTraceId != null
&& string.IsNullOrEmpty(_entryOperationName)
&& string.IsNullOrEmpty(_parentOperationName);
public ID TraceSegmentId => _traceSegmentId;
public int EntryOperationId
{
set => _entryOperationName = value + "";
}
public int ParentOperationId
{
set => _parentOperationName = value + "";
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace SkyWalking.Context.Ids
{
public class NewDistributedTraceId : DistributedTraceId
{
public NewDistributedTraceId()
:base(GlobalIdGenerator.Generate())
{
}
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace SkyWalking.Context.Ids
{
/// <summary>
/// The <code>PropagatedTraceId</code> represents a {@link DistributedTraceId}, which is propagated from the peer.
/// </summary>
public class PropagatedTraceId : DistributedTraceId
{
public PropagatedTraceId(string id)
:base(id)
{
}
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using SkyWalking.Context.Trace;
using SkyWalking.Utils;
namespace SkyWalking.Context
{
public class IgnoredTracerContext : ITracerContext
{
private static readonly NoopSpan noopSpan = new NoopSpan();
private static readonly NoopEntrySpan noopEntrySpan=new NoopEntrySpan();
private readonly Stack<ISpan> _spans = new Stack<ISpan>();
public void Inject(IContextCarrier carrier)
{
}
public void Extract(IContextCarrier carrier)
{
}
public IContextSnapshot Capture { get; }
public ISpan ActiveSpan
{
get
{
_spans.TryPeek(out var span);
return span;
}
}
public IDictionary<string, object> Properties { get; } = new Dictionary<string, object>();
public void Continued(IContextSnapshot snapshot)
{
}
public string GetReadableGlobalTraceId()
{
return string.Empty;
}
public ISpan CreateEntrySpan(string operationName)
{
_spans.Push(noopEntrySpan);
return noopEntrySpan;
}
public ISpan CreateLocalSpan(string operationName)
{
_spans.Push(noopSpan);
return noopSpan;
}
public ISpan CreateExitSpan(string operationName, string remotePeer)
{
var exitSpan = new NoopExitSpan(remotePeer);
_spans.Push(exitSpan);
return exitSpan;
}
public void StopSpan(ISpan span)
{
_spans.TryPop(out _);
if (_spans.Count == 0)
{
ListenerManager.NotifyFinish(this);
foreach (var item in Properties)
{
if (item.Value is IDisposable disposable)
{
disposable.Dispose();
}
}
}
}
public static class ListenerManager
{
private static readonly List<IIgnoreTracerContextListener> _listeners = new List<IIgnoreTracerContextListener>();
[MethodImpl(MethodImplOptions.Synchronized)]
public static void Add(IIgnoreTracerContextListener listener)
{
_listeners.Add(listener);
}
public static void NotifyFinish(ITracerContext tracerContext)
{
foreach (var listener in _listeners)
{
listener.AfterFinish(tracerContext);
}
}
[MethodImpl(MethodImplOptions.Synchronized)]
public static void Remove(IIgnoreTracerContextListener listener)
{
_listeners.Remove(listener);
}
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
namespace SkyWalking.Context
{
public class SW3CarrierItem : CarrierItem
{
private const string HEADER_NAME = "sw3";
private readonly IContextCarrier _carrier;
public SW3CarrierItem(IContextCarrier carrier, CarrierItem next, string @namespace)
: base(HEADER_NAME, carrier.Serialize(), next, @namespace)
{
_carrier = carrier;
}
public override string HeadValue
{
get => base.HeadValue;
set => _carrier.Deserialize(value);
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace SkyWalking.Context.Tag
{
/// <summary>
/// The span tags are supported by sky-walking engine.
/// As default, all tags will be stored, but these ones have particular meanings.
/// </summary>
public static class Tags
{
public static readonly StringTag Url = new StringTag("url");
/// <summary>
/// STATUS_CODE records the http status code of the response.
/// </summary>
public static readonly StringTag StatusCode = new StringTag("status_code");
/// <summary>
/// DB_TYPE records database type, such as sql, redis, cassandra and so on.
/// </summary>
public static readonly StringTag DbType = new StringTag("db.type");
/// <summary>
/// DB_INSTANCE records database instance name.
/// </summary>
public static readonly StringTag DbInstance = new StringTag("db.instance");
/// <summary>
/// DB_STATEMENT records the sql statement of the database access.
/// </summary>
public static readonly StringTag DbStatement = new StringTag("db.statement");
/// <summary>
/// DB_BIND_VARIABLES records the bind variables of sql statement.
/// </summary>
public static readonly StringTag DbBindVariables = new StringTag("db.bind_vars");
/// <summary>
/// MQ_BROKER records the broker address of message-middleware
/// </summary>
public static readonly StringTag MqBorker = new StringTag("mq.broker");
/// <summary>
/// MQ_TOPIC records the topic name of message-middleware
/// </summary>
public static readonly StringTag MqTopic = new StringTag("mq.topic");
public static class HTTP
{
public static readonly StringTag Method = new StringTag("http.method");
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using SkyWalking.Components;
namespace SkyWalking.Context.Trace
{
public class EntrySpan : StackBasedTracingSpan
{
private int _currentMaxDepth;
public EntrySpan(int spanId, int parentSpanId, string operationName)
: base(spanId, parentSpanId, operationName)
{
_stackDepth = 0;
}
public EntrySpan(int spanId, int parentSpanId, int operationId)
: base(spanId, parentSpanId, operationId)
{
_stackDepth = 0;
}
public override bool IsEntry => true;
public override bool IsExit => false;
public override ISpan Start()
{
if ((_currentMaxDepth = ++_stackDepth) == 1)
{
base.Start();
}
ClearWhenRestart();
return this;
}
public override ISpan Tag(string key, string value)
{
if (_stackDepth == _currentMaxDepth)
{
base.Tag(key, value);
}
return this;
}
public override ISpan SetLayer(SpanLayer layer)
{
if (_stackDepth == _currentMaxDepth)
{
return base.SetLayer(layer);
}
return this;
}
public override ISpan SetComponent(IComponent component)
{
if (_stackDepth == _currentMaxDepth)
{
return base.SetComponent(component);
}
return this;
}
public override ISpan SetComponent(string componentName)
{
if (_stackDepth == _currentMaxDepth)
{
return base.SetComponent(componentName);
}
return this;
}
public override string OperationName
{
get
{
return base.OperationName;
}
set
{
if (_stackDepth == _currentMaxDepth)
{
base.OperationName = value;
}
}
}
public override int OperationId
{
get
{
return base.OperationId;
}
set
{
if (_stackDepth == _currentMaxDepth)
{
base.OperationId = value;
}
}
}
private void ClearWhenRestart()
{
_componentId = 0;
_componentName = null;
_layer = null;
_logs = null;
_tags = null;
}
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using SkyWalking.Transport;
using SkyWalking.Components;
namespace SkyWalking.Context.Trace
{
public class ExitSpan : StackBasedTracingSpan, IWithPeerInfo
{
private readonly string _peer;
private readonly int _peerId;
public ExitSpan(int spanId, int parentSpanId, String operationName, String peer)
: base(spanId, parentSpanId, operationName)
{
_peer = peer;
_peerId = 0;
}
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 = 0;
}
public ExitSpan(int spanId, int parentSpanId, String operationName, int peerId)
: base(spanId, parentSpanId, operationName)
{
_peer = null;
_peerId = peerId;
}
public override bool IsEntry => false;
public override bool IsExit => true;
public int PeerId => _peerId;
public string Peer => _peer;
public override ISpan Start()
{
if (++_stackDepth == 1)
{
base.Start();
}
return base.Start();
}
public override ISpan Tag(string key, string value)
{
if (_stackDepth == 1)
{
base.Tag(key, value);
}
return this;
}
public override ISpan SetLayer(SpanLayer layer)
{
if (_stackDepth == 1)
{
return base.SetLayer(layer);
}
return this;
}
public override ISpan SetComponent(IComponent component)
{
if (_stackDepth == 1)
{
return base.SetComponent(component);
}
return this;
}
public override ISpan SetComponent(string componentName)
{
return _stackDepth == 1 ? base.SetComponent(componentName) : this;
}
public override string OperationName
{
get => base.OperationName;
set
{
if (_stackDepth == 1)
{
base.OperationName = value;
}
}
}
public override int OperationId
{
get => base.OperationId;
set
{
if (_stackDepth == 1)
{
base.OperationId = value;
}
}
}
public override SpanRequest Transform()
{
var spanObject = base.Transform();
spanObject.Peer = new StringOrIntValue(_peerId, _peer);
return spanObject;
}
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace SkyWalking.Context.Trace
{
public class LocalSpan : StackBasedTracingSpan
{
public LocalSpan(int spanId, int parentSpanId, string operationName) : base(spanId, parentSpanId, operationName)
{
}
public LocalSpan(int spanId, int parentSpanId, int operationId) : base(spanId, parentSpanId, operationId)
{
}
public override bool IsEntry => false;
public override bool IsExit => false;
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace SkyWalking.Context.Trace
{
public class NoopEntrySpan:NoopSpan
{
public override bool IsEntry { get; } = true;
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections.Generic;
using System.Linq;
using SkyWalking.Transport;
using SkyWalking.Context.Ids;
namespace SkyWalking.Context.Trace
{
public class TraceSegment : ITraceSegment
{
private readonly IList<ITraceSegmentRef> _refs;
private readonly IList<AbstractTracingSpan> _spans;
private readonly DistributedTraceIdCollection _relatedGlobalTraces;
private bool _isSizeLimited;
public int ApplicationId => RuntimeEnvironment.Instance.ServiceId.Value;
public int ApplicationInstanceId => RuntimeEnvironment.Instance.ServiceInstanceId.Value;
public IEnumerable<ITraceSegmentRef> Refs => _refs;
public IEnumerable<DistributedTraceId> RelatedGlobalTraces => _relatedGlobalTraces.GetRelatedGlobalTraces();
public ID TraceSegmentId { get; }
public bool HasRef => _refs.Count > 0;
public bool IsIgnore { get; set; }
public bool IsSingleSpanSegment => _spans.Count == 1;
public TraceSegment()
{
TraceSegmentId = GlobalIdGenerator.Generate();
_spans = new List<AbstractTracingSpan>();
_relatedGlobalTraces = new DistributedTraceIdCollection();
_relatedGlobalTraces.Append(new NewDistributedTraceId());
_refs = new List<ITraceSegmentRef>();
}
public void Archive(AbstractTracingSpan finishedSpan)
{
_spans.Add(finishedSpan);
}
public ITraceSegment Finish(bool isSizeLimited)
{
_isSizeLimited = isSizeLimited;
return this;
}
/// <summary>
/// Establish the link between this segment and its parents.
/// </summary>
public void Ref(ITraceSegmentRef refSegment)
{
if (!_refs.Contains(refSegment))
{
_refs.Add(refSegment);
}
}
public void RelatedGlobalTrace(DistributedTraceId distributedTraceId)
{
_relatedGlobalTraces.Append(distributedTraceId);
}
public SegmentRequest Transform()
{
var upstreamSegment = new SegmentRequest
{
UniqueIds = _relatedGlobalTraces.GetRelatedGlobalTraces()
.Select(x => x.ToUniqueId()).ToArray()
};
upstreamSegment.Segment = new SegmentObjectRequest
{
SegmentId = TraceSegmentId.Transform(),
Spans = _spans.Select(x => x.Transform()).ToArray(),
ServiceId = ApplicationId,
ServiceInstanceId = ApplicationInstanceId
};
return upstreamSegment;
}
public override string ToString()
{
return "TraceSegment{"
+
$"traceSegmentId='{TraceSegmentId}', refs={_refs}, spans={_spans}, relatedGlobalTraces={_relatedGlobalTraces}"
+ "}";
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Linq;
using SkyWalking.Transport;
using SkyWalking.Config;
using SkyWalking.Context.Ids;
namespace SkyWalking.Context.Trace
{
public class TraceSegmentRef : ITraceSegmentRef
{
private readonly SegmentRefType _type;
private readonly ID _traceSegmentId;
private readonly int _spanId = -1;
private readonly int _peerId = 0;
private readonly string _peerHost;
private readonly int _entryApplicationInstanceId = 0;
private readonly int _parentApplicationInstanceId = 0;
private readonly string _entryOperationName;
private readonly int _entryOperationId = 0;
private readonly string _parentOperationName;
private readonly int _parentOperationId = 0;
public TraceSegmentRef(IContextCarrier carrier)
{
_type = SegmentRefType.CrossProcess;
_traceSegmentId = carrier.TraceSegmentId;
_spanId = carrier.SpanId;
_parentApplicationInstanceId = carrier.ParentApplicationInstanceId;
_entryApplicationInstanceId = carrier.EntryApplicationInstanceId;
string host = carrier.PeerHost;
if (host.ToCharArray()[0] == '#')
{
_peerHost = host.Substring(1);
}
else
{
int.TryParse(host, out _peerId);
}
string entryOperationName = carrier.EntryOperationName;
if (entryOperationName.First() == '#')
{
_entryOperationName = entryOperationName.Substring(1);
}
else
{
int.TryParse(entryOperationName, out _entryOperationId);
}
string parentOperationName = carrier.EntryOperationName;
if (parentOperationName.First() == '#')
{
_parentOperationName = parentOperationName.Substring(1);
}
else
{
int.TryParse(parentOperationName, out _parentOperationId);
}
}
public TraceSegmentRef(IContextSnapshot contextSnapshot)
{
_type = SegmentRefType.CrossThread;
_traceSegmentId = contextSnapshot.TraceSegmentId;
_spanId = contextSnapshot.SpanId;
_parentApplicationInstanceId = RuntimeEnvironment.Instance.ServiceInstanceId.Value;
_entryApplicationInstanceId = contextSnapshot.EntryApplicationInstanceId;
string entryOperationName = contextSnapshot.EntryOperationName;
if (entryOperationName.First() == '#')
{
_entryOperationName = entryOperationName.Substring(1);
}
else
{
int.TryParse(entryOperationName, out _entryOperationId);
}
string parentOperationName = contextSnapshot.ParentOperationName;
if (parentOperationName.First() == '#')
{
_parentOperationName = parentOperationName.Substring(1);
}
else
{
int.TryParse(parentOperationName, out _parentOperationId);
}
}
public bool Equals(ITraceSegmentRef other)
{
if (other == null)
{
return false;
}
if (other == this)
{
return true;
}
if (!(other is TraceSegmentRef segmentRef))
{
return false;
}
if (_spanId != segmentRef._spanId)
{
return false;
}
return _traceSegmentId.Equals(segmentRef._traceSegmentId);
}
public override bool Equals(object obj)
{
var other = obj as ITraceSegmentRef;
return Equals(other);
}
public override int GetHashCode()
{
int result = _traceSegmentId.GetHashCode();
result = 31 * result + _spanId;
return result;
}
public string EntryOperationName => _entryOperationName;
public int EntryOperationId => _entryOperationId;
public int EntryApplicationInstanceId => _entryApplicationInstanceId;
public SegmentReferenceRequest Transform()
{
SegmentReferenceRequest segmentReference = new SegmentReferenceRequest();
if (_type == SegmentRefType.CrossProcess)
{
segmentReference.RefType = (int) SegmentRefType.CrossProcess;
segmentReference.NetworkAddress = new StringOrIntValue(_peerId, _peerHost);
}
else
{
segmentReference.RefType = (int) SegmentRefType.CrossThread;
segmentReference.NetworkAddress = new StringOrIntValue();
}
segmentReference.ParentServiceInstanceId = _parentApplicationInstanceId;
segmentReference.EntryServiceInstanceId = _entryApplicationInstanceId;
segmentReference.ParentSegmentId = _traceSegmentId.Transform();
segmentReference.ParentSpanId = _spanId;
segmentReference.EntryEndpointName = new StringOrIntValue(_entryOperationId, _entryOperationName);
segmentReference.ParentEndpointName = new StringOrIntValue(_parentOperationId, _parentOperationName);
return segmentReference;
}
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace SkyWalking.Context
{
public class TraceContextCarrierItem : CarrierItem
{
private const string HEAD_NAME = "Trace-Context";
public TraceContextCarrierItem(string headValue, CarrierItem next, string @namespace)
: base(HEAD_NAME, headValue, next, @namespace)
{
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using SkyWalking.Context.Trace;
using SkyWalking.Utils;
namespace SkyWalking.Context
{
public class TracingContext : ITracerContext
{
private long _lastWarningTimestamp = 0;
private readonly ISampler _sampler;
private readonly ITraceSegment _segment;
private readonly Stack<ISpan> _activeSpanStacks;
private int _spanIdGenerator;
public TracingContext()
{
_sampler = DefaultSampler.Instance;
_segment = new TraceSegment();
_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)
{
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 (peerId == 0)
{
carrier.PeerHost = peer;
}
else
{
carrier.PeerId = peerId;
}
var refs = _segment.Refs;
var firstSpan = _activeSpanStacks.Last();
var metaValue = GetMetaValue(refs);
carrier.EntryApplicationInstanceId = metaValue.entryApplicationInstanceId;
if (metaValue.operationId == 0)
{
carrier.EntryOperationName = metaValue.operationName;
}
else
{
carrier.EntryOperationId = metaValue.operationId;
}
var parentOperationId = firstSpan.OperationId;
if (parentOperationId == 0)
{
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)
{
var traceSegmentRef = new TraceSegmentRef(carrier);
_segment.Ref(traceSegmentRef);
_segment.RelatedGlobalTrace(carrier.DistributedTraceId);
var span = InternalActiveSpan();
if (span is EntrySpan)
{
span.Ref(traceSegmentRef);
}
}
/// <summary>
/// Capture the snapshot of current context.
/// </summary>
public IContextSnapshot Capture => InternalCapture();
public ISpan ActiveSpan => InternalActiveSpan();
public IDictionary<string, object> Properties { get; } = new Dictionary<string, object>();
public void Continued(IContextSnapshot snapshot)
{
var segmentRef = new TraceSegmentRef(snapshot);
_segment.Ref(segmentRef);
ActiveSpan.Ref(segmentRef);
_segment.RelatedGlobalTrace(snapshot.DistributedTraceId);
}
public string GetReadableGlobalTraceId()
{
return _segment.RelatedGlobalTraces.FirstOrDefault()?.ToString();
}
/// <summary>
/// Create an entry span
/// </summary>
public ISpan CreateEntrySpan(string operationName)
{
if (!EnsureLimitMechanismWorking(out var noopSpan))
{
return noopSpan;
}
_activeSpanStacks.TryPeek(out var parentSpan);
var parentSpanId = parentSpan?.SpanId ?? -1;
if (parentSpan != null && parentSpan.IsEntry)
{
parentSpan.OperationName = operationName;
return parentSpan.Start();
}
else
{
var entrySpan = new EntrySpan(_spanIdGenerator++, parentSpanId, operationName);
entrySpan.Start();
_activeSpanStacks.Push(entrySpan);
return entrySpan;
}
}
/// <summary>
/// Create a local span
/// </summary>
public ISpan CreateLocalSpan(string operationName)
{
if (!EnsureLimitMechanismWorking(out var noopSpan))
{
return noopSpan;
}
_activeSpanStacks.TryPeek(out var parentSpan);
var parentSpanId = parentSpan?.SpanId ?? -1;
var span = 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)
{
_activeSpanStacks.TryPeek(out var parentSpan);
if (parentSpan != null && parentSpan.IsExit)
{
return parentSpan.Start();
}
else
{
var parentSpanId = parentSpan?.SpanId ?? -1;
var exitSpan = IsLimitMechanismWorking() ? (ISpan)new NoopExitSpan(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)
{
_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.Sampled())
{
finishedSegment.IsIgnore = true;
}
}
ListenerManager.NotifyFinish(finishedSegment);
foreach (var item in Properties)
{
if (item.Value is IDisposable disposable)
{
disposable.Dispose();
}
}
}
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 (metaValue.operationId == 0)
{
snapshot.EntryOperationName = metaValue.operationName;
}
else
{
snapshot.EntryOperationId = metaValue.operationId;
}
var parentSpan = _activeSpanStacks.Last();
if (parentSpan.OperationId == 0)
{
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.Last();
return (span.OperationName, span.OperationId, _segment.ApplicationInstanceId);
}
}
private bool IsLimitMechanismWorking()
{
if (_spanIdGenerator < 300)
{
return false;
}
var currentTimeMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
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;
}
public static class ListenerManager
{
private static readonly IList<ITracingContextListener> _listeners = new List<ITracingContextListener>();
[MethodImpl(MethodImplOptions.Synchronized)]
public static void Add(ITracingContextListener listener)
{
_listeners.Add(listener);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public static void Remove(ITracingContextListener listener)
{
_listeners.Remove(listener);
}
public static void NotifyFinish(ITraceSegment traceSegment)
{
foreach (var listener in _listeners)
{
listener.AfterFinished(traceSegment);
}
}
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Runtime.CompilerServices;
using SkyWalking.Utils;
namespace SkyWalking
{
public class DefaultSampler : ISampler
{
public static DefaultSampler Instance { get; } = new DefaultSampler();
private readonly AtomicInteger _idx = new AtomicInteger();
private int _samplePer3Secs;
private bool _sample_on;
public bool Sampled()
{
if (!_sample_on)
{
return true;
}
return _idx.Increment() < _samplePer3Secs;
}
public void ForceSampled()
{
if (_sample_on)
{
_idx.Increment();
}
}
[MethodImpl(MethodImplOptions.Synchronized)]
internal void SetSamplePer3Secs(int samplePer3Secs)
{
_samplePer3Secs = samplePer3Secs;
_sample_on = samplePer3Secs > -1;
}
internal void Reset()
{
_idx.Value = 0;
}
}
}
\ No newline at end of file
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using SkyWalking.Common;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.Utils;
namespace SkyWalking.Diagnostics namespace SkyWalking.Diagnostics
{ {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
...@@ -27,17 +27,17 @@ using SkyWalking.Logging; ...@@ -27,17 +27,17 @@ using SkyWalking.Logging;
namespace SkyWalking namespace SkyWalking
{ {
public class SkyWalkingAgentStartup : ISkyWalkingAgentStartup public class InstrumentStartup : IInstrumentStartup
{ {
private readonly TracingDiagnosticProcessorObserver _observer; private readonly TracingDiagnosticProcessorObserver _observer;
private readonly IEnumerable<IExecutionService> _services; private readonly IEnumerable<IExecutionService> _services;
private readonly ILogger _logger; private readonly ILogger _logger;
public SkyWalkingAgentStartup(TracingDiagnosticProcessorObserver observer, IEnumerable<IExecutionService> services, ILoggerFactory loggerFactory) public InstrumentStartup(TracingDiagnosticProcessorObserver observer, IEnumerable<IExecutionService> services, ILoggerFactory loggerFactory)
{ {
_observer = observer; _observer = observer;
_services = services; _services = services;
_logger = loggerFactory.CreateLogger(typeof(SkyWalkingAgentStartup)); _logger = loggerFactory.CreateLogger(typeof(InstrumentStartup));
} }
public async Task StartAsync(CancellationToken cancellationToken = default(CancellationToken)) public async Task StartAsync(CancellationToken cancellationToken = default(CancellationToken))
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
*/ */
using System; using System;
using SkyWalking.Common;
namespace SkyWalking namespace SkyWalking
{ {
......
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -17,40 +17,35 @@ ...@@ -17,40 +17,35 @@
*/ */
using System; using System;
using System.ComponentModel; using SkyWalking.Config;
using System.Diagnostics; using SkyWalking.Tracing;
using System.Text;
namespace SkyWalking.Context namespace SkyWalking.Sampling
{ {
public static class ExceptionExtensions public class RandomSamplingInterceptor : ISamplingInterceptor
{ {
public static string ConvertToString(Exception exception, int maxLength) private readonly Random _random;
{ private readonly int _samplingRate;
var message = new StringBuilder(); private readonly bool _sample_on;
while (exception != null) public RandomSamplingInterceptor(IConfigAccessor configAccessor)
{
var percentage = configAccessor.Get<SamplingConfig>().Percentage;
_sample_on = percentage > 0;
if (_sample_on)
{ {
message.Append(exception.Message); _samplingRate = (int)(percentage * 100d);
PrintStackFrame(message, exception.StackTrace, maxLength, out var overMaxLength);
if (overMaxLength)
{
break;
}
exception = exception.InnerException;
} }
_random = new Random();
return message.ToString();
} }
private static void PrintStackFrame(StringBuilder message, string stackTrace, public int Priority { get; } = int.MinValue + 1000;
int maxLength, out bool overMaxLength)
public bool Invoke(SamplingContext samplingContext, Sampler next)
{ {
message.AppendLine(stackTrace); if (!_sample_on) return next(samplingContext);
overMaxLength = message.Length > maxLength; var r = _random.Next(10000);
return r <= _samplingRate && next(samplingContext);
} }
} }
} }
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0 * The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
*/ */
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Config; using SkyWalking.Common;
using SkyWalking.Logging; using SkyWalking.Config;
using SkyWalking.Logging;
namespace SkyWalking.Service using SkyWalking.Tracing;
{
public class SamplingRefreshService : ExecutionService namespace SkyWalking.Sampling
{ {
private readonly SamplingConfig _config; public class SimpleCountSamplingInterceptor : ExecutionService, ISamplingInterceptor
{
public SamplingRefreshService(IConfigAccessor configAccessor, private readonly bool _sample_on;
IRuntimeEnvironment runtimeEnvironment, ILoggerFactory loggerFactory) private readonly int _samplePer3Secs;
: base(runtimeEnvironment, loggerFactory) private readonly AtomicInteger _idx = new AtomicInteger();
{
_config = configAccessor.Get<SamplingConfig>(); public SimpleCountSamplingInterceptor(IConfigAccessor configAccessor,IRuntimeEnvironment runtimeEnvironment, ILoggerFactory loggerFactory) :
DefaultSampler.Instance.SetSamplePer3Secs(_config.SamplePer3Secs); base(runtimeEnvironment, loggerFactory)
} {
var samplingConfig = configAccessor.Get<SamplingConfig>();
protected override TimeSpan DueTime { get; } = TimeSpan.Zero; _samplePer3Secs = samplingConfig.SamplePer3Secs;
_sample_on = _samplePer3Secs > -1;
protected override TimeSpan Period { get; } = TimeSpan.FromSeconds(3); }
protected override Task ExecuteAsync(CancellationToken cancellationToken) public int Priority { get; } = int.MinValue + 999;
{
DefaultSampler.Instance.Reset(); public bool Invoke(SamplingContext samplingContext, Sampler next)
return Task.CompletedTask; {
} if (!_sample_on) return next(samplingContext);
} return _idx.Increment() <= _samplePer3Secs && next(samplingContext);
}
protected override TimeSpan DueTime { get; } = TimeSpan.Zero;
protected override TimeSpan Period { get; } = TimeSpan.FromSeconds(3);
protected override bool CanExecute() => _sample_on && base.CanExecute();
protected override Task ExecuteAsync(CancellationToken cancellationToken)
{
Reset();
return Task.CompletedTask;
}
private void Reset()
{
_idx.Value = 0;
}
}
} }
\ No newline at end of file
...@@ -20,16 +20,16 @@ using System; ...@@ -20,16 +20,16 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Common;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.Transport; using SkyWalking.Transport;
using SkyWalking.Utils;
namespace SkyWalking.Service namespace SkyWalking.Service
{ {
public class RegisterService : ExecutionService public class RegisterService : ExecutionService
{ {
private readonly InstrumentationConfig _config; private readonly InstrumentConfig _config;
private readonly IServiceRegister _serviceRegister; private readonly IServiceRegister _serviceRegister;
private readonly TransportConfig _transportConfig; private readonly TransportConfig _transportConfig;
...@@ -38,7 +38,7 @@ namespace SkyWalking.Service ...@@ -38,7 +38,7 @@ namespace SkyWalking.Service
loggerFactory) loggerFactory)
{ {
_serviceRegister = serviceRegister; _serviceRegister = serviceRegister;
_config = configAccessor.Get<InstrumentationConfig>(); _config = configAccessor.Get<InstrumentConfig>();
_transportConfig = configAccessor.Get<TransportConfig>(); _transportConfig = configAccessor.Get<TransportConfig>();
} }
......
...@@ -20,14 +20,12 @@ using System; ...@@ -20,14 +20,12 @@ using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Context;
using SkyWalking.Context.Trace;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.Transport; using SkyWalking.Transport;
namespace SkyWalking.Service namespace SkyWalking.Service
{ {
public class SegmentReportService : ExecutionService, ITracingContextListener public class SegmentReportService : ExecutionService
{ {
private readonly TransportConfig _config; private readonly TransportConfig _config;
private readonly ISegmentDispatcher _dispatcher; private readonly ISegmentDispatcher _dispatcher;
...@@ -39,7 +37,6 @@ namespace SkyWalking.Service ...@@ -39,7 +37,6 @@ namespace SkyWalking.Service
_dispatcher = dispatcher; _dispatcher = dispatcher;
_config = configAccessor.Get<TransportConfig>(); _config = configAccessor.Get<TransportConfig>();
Period = TimeSpan.FromMilliseconds(_config.Interval); Period = TimeSpan.FromMilliseconds(_config.Interval);
TracingContext.ListenerManager.Add(this);
} }
protected override TimeSpan DueTime { get; } = TimeSpan.FromSeconds(3); protected override TimeSpan DueTime { get; } = TimeSpan.FromSeconds(3);
...@@ -54,14 +51,7 @@ namespace SkyWalking.Service ...@@ -54,14 +51,7 @@ namespace SkyWalking.Service
protected override Task Stopping(CancellationToken cancellationToke) protected override Task Stopping(CancellationToken cancellationToke)
{ {
_dispatcher.Close(); _dispatcher.Close();
TracingContext.ListenerManager.Remove(this);
return Task.CompletedTask; return Task.CompletedTask;
} }
public void AfterFinished(ITraceSegment traceSegment)
{
if (!traceSegment.IsIgnore)
_dispatcher.Dispatch(traceSegment.Transform());
}
} }
} }
\ No newline at end of file
...@@ -20,16 +20,16 @@ using System; ...@@ -20,16 +20,16 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Common;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.Transport; using SkyWalking.Transport;
using SkyWalking.Utils;
namespace SkyWalking.Service namespace SkyWalking.Service
{ {
public class ServiceDiscoveryV5Service : ExecutionService public class ServiceDiscoveryV5Service : ExecutionService
{ {
private readonly InstrumentationConfig _config; private readonly InstrumentConfig _config;
private readonly TransportConfig _transportConfig; private readonly TransportConfig _transportConfig;
private readonly ISkyWalkingClientV5 _skyWalkingClient; private readonly ISkyWalkingClientV5 _skyWalkingClient;
...@@ -41,7 +41,7 @@ namespace SkyWalking.Service ...@@ -41,7 +41,7 @@ namespace SkyWalking.Service
IRuntimeEnvironment runtimeEnvironment, ILoggerFactory loggerFactory) IRuntimeEnvironment runtimeEnvironment, ILoggerFactory loggerFactory)
: base(runtimeEnvironment, loggerFactory) : base(runtimeEnvironment, loggerFactory)
{ {
_config = configAccessor.Get<InstrumentationConfig>(); _config = configAccessor.Get<InstrumentConfig>();
_transportConfig = configAccessor.Get<TransportConfig>(); _transportConfig = configAccessor.Get<TransportConfig>();
_skyWalkingClient = skyWalkingClient; _skyWalkingClient = skyWalkingClient;
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="4.5.1" /> <PackageReference Include="System.Diagnostics.DiagnosticSource" Version="4.5.1" />
<PackageReference Include="System.Memory" Version="4.5.2" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> <PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using SkyWalking.Common;
namespace SkyWalking.Tracing
{
public class Carrier : ICarrier
{
public bool HasValue { get; } = true;
public bool? Sampled { get; set; }
public UniqueId TraceId { get; }
public UniqueId ParentSegmentId { get; }
public int ParentSpanId { get; }
public int ParentServiceInstanceId { get; }
public int EntryServiceInstanceId { get; }
public StringOrIntValue NetworkAddress { get; set; }
public StringOrIntValue EntryEndpoint { get; set; }
public StringOrIntValue ParentEndpoint { get; set; }
public Carrier(UniqueId traceId, UniqueId parentSegmentId, int parentSpanId, int parentServiceInstanceId,
int entryServiceInstanceId)
{
TraceId = traceId;
ParentSegmentId = parentSegmentId;
ParentSpanId = parentSpanId;
ParentServiceInstanceId = parentServiceInstanceId;
EntryServiceInstanceId = entryServiceInstanceId;
}
}
}
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,84 +16,77 @@ ...@@ -16,84 +16,77 @@
* *
*/ */
using System; using System.Collections.Generic;
using System.Threading; using System.Linq;
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Context.Ids namespace SkyWalking.Tracing
{ {
public static class GlobalIdGenerator public class CarrierPropagator : ICarrierPropagator
{ {
private static readonly ThreadLocal<IDContext> threadIdSequence = new ThreadLocal<IDContext>(() => new IDContext(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), 0)); private readonly IEnumerable<ICarrierFormatter> _carrierFormatters;
private readonly ISegmentContextFactory _segmentContextFactory;
public static ID Generate() public CarrierPropagator(IEnumerable<ICarrierFormatter> carrierFormatters,
ISegmentContextFactory segmentContextFactory)
{ {
if (!RuntimeEnvironment.Instance.ServiceInstanceId.HasValue) _carrierFormatters = carrierFormatters;
{ _segmentContextFactory = segmentContextFactory;
throw new InvalidOperationException();
}
IDContext context = threadIdSequence.Value;
return new ID(
RuntimeEnvironment.Instance.ServiceInstanceId.Value,
Thread.CurrentThread.ManagedThreadId,
context.NextSeq()
);
} }
private class IDContext public void Inject(SegmentContext segmentContext, ICarrierHeaderCollection headerCollection)
{ {
private long _lastTimestamp; var reference = segmentContext.References.FirstOrDefault();
private short _threadSeq;
// Just for considering time-shift-back only. var carrier = new Carrier(segmentContext.TraceId, segmentContext.SegmentId, segmentContext.Span.SpanId,
private long _runRandomTimestamp; segmentContext.ServiceInstanceId, reference?.EntryServiceInstanceId ?? segmentContext.ServiceInstanceId)
private int _lastRandomValue; {
private readonly Random _random; NetworkAddress = segmentContext.Span.Peer,
EntryEndpoint = reference?.EntryEndpoint ?? segmentContext.Span.OperationName,
ParentEndpoint = segmentContext.Span.OperationName,
Sampled = segmentContext.Sampled
};
public IDContext(long lastTimestamp, short threadSeq) foreach (var formatter in _carrierFormatters)
{ {
_lastTimestamp = lastTimestamp; if (formatter.Enable){}
_threadSeq = threadSeq; headerCollection.Add(formatter.Key, formatter.Encode(carrier));
_random = new Random();
} }
}
public long NextSeq() public ICarrier Extract(ICarrierHeaderCollection headerCollection)
{
ICarrier carrier = NullableCarrier.Instance;
if (headerCollection == null)
{ {
return GetTimestamp() * 10000 + NextThreadSeq(); return carrier;
} }
foreach (var formatter in _carrierFormatters.OrderByDescending(x => x.Key))
private long GetTimestamp()
{ {
long currentTimeMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); if (!formatter.Enable)
if (currentTimeMillis < _lastTimestamp)
{ {
// Just for considering time-shift-back by Ops or OS. @hanahmily 's suggestion. continue;
if (_runRandomTimestamp != currentTimeMillis)
{
_lastRandomValue = _random.Next();
_runRandomTimestamp = currentTimeMillis;
}
return _lastRandomValue;
} }
else
foreach (var header in headerCollection)
{ {
_lastTimestamp = currentTimeMillis; if (formatter.Key == header.Key)
return _lastTimestamp; {
} carrier = formatter.Decode(header.Value);
} if (carrier.HasValue)
{
if (formatter.Key.EndsWith("sw3") && carrier is Carrier c)
{
c.Sampled = true;
}
private short NextThreadSeq() return carrier;
{ }
if (_threadSeq == 10000) }
{
_threadSeq = 0;
} }
return _threadSeq++;
} }
return carrier;
} }
} }
} }
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Threading;
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Tracing
{
public class EntrySegmentContextAccessor : IEntrySegmentContextAccessor
{
private readonly AsyncLocal<SegmentContext> _segmentContext = new AsyncLocal<SegmentContext>();
public SegmentContext Context
{
get => _segmentContext.Value;
set => _segmentContext.Value = value;
}
}
}
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,23 +16,19 @@ ...@@ -16,23 +16,19 @@
* *
*/ */
using SkyWalking.Context.Trace; using System.Threading;
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Context.Tag namespace SkyWalking.Tracing
{ {
public abstract class AbstractTag<T> public class ExitSegmentContextAccessor : IExitSegmentContextAccessor
{ {
private readonly AsyncLocal<SegmentContext> _segmentContext = new AsyncLocal<SegmentContext>();
public AbstractTag(string tagKey) public SegmentContext Context
{ {
Key = tagKey; get => _segmentContext.Value;
set => _segmentContext.Value = value;
} }
public abstract void Set(ISpan span, T tagValue);
/**
* @return the key of this tag.
*/
public string Key { get; protected set; }
} }
} }
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections.Concurrent;
using System.Threading;
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Tracing
{
public class LocalSegmentContextAccessor : ILocalSegmentContextAccessor
{
private readonly AsyncLocal<ConcurrentStack<SegmentContext>> _segmentContextStack =
new AsyncLocal<ConcurrentStack<SegmentContext>>();
public SegmentContext Context
{
get
{
var stack = _segmentContextStack.Value;
if (stack == null)
{
return null;
}
stack.TryPeek(out var context);
return context;
}
set
{
var stack = _segmentContextStack.Value;
if (stack == null)
{
if (value == null) return;
stack = new ConcurrentStack<SegmentContext>();
stack.Push(value);
_segmentContextStack.Value = stack;
}
else
{
if (value == null)
{
stack.TryPop(out _);
if (stack.IsEmpty)
{
_segmentContextStack.Value = null;
}
}
else
{
stack.Push(value);
}
}
}
}
}
}
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,33 +16,32 @@ ...@@ -16,33 +16,32 @@
* *
*/ */
using System.Collections.Generic; using SkyWalking.Common;
using SkyWalking.Context.Trace;
namespace SkyWalking.Context namespace SkyWalking.Tracing
{ {
public interface ITracerContext public class NullableCarrier : ICarrier
{ {
void Inject(IContextCarrier carrier); public static NullableCarrier Instance { get; } = new NullableCarrier();
void Extract(IContextCarrier carrier);
IContextSnapshot Capture { get; } public bool HasValue { get; } = false;
ISpan ActiveSpan { get; } public bool? Sampled { get; }
IDictionary<string,object> Properties { get; } public UniqueId TraceId { get; }
void Continued(IContextSnapshot snapshot); public UniqueId ParentSegmentId { get; }
string GetReadableGlobalTraceId(); public int ParentSpanId { get; }
ISpan CreateEntrySpan(string operationName); public int ParentServiceInstanceId { get; }
ISpan CreateLocalSpan(string operationName); public int EntryServiceInstanceId { get; }
ISpan CreateExitSpan(string operationName, string remotePeer); public StringOrIntValue NetworkAddress { get; }
void StopSpan(ISpan span); public StringOrIntValue EntryEndpoint { get; }
public StringOrIntValue ParentEndpoint { get; }
} }
} }
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace SkyWalking.Tracing
{
public class SamplerChainBuilder : ISamplerChainBuilder
{
private volatile int state = 0;
private readonly IEnumerable<ISamplingInterceptor> _sampledInterceptors;
private Sampler _sampler;
public SamplerChainBuilder(IEnumerable<ISamplingInterceptor> sampledInterceptors)
{
_sampledInterceptors = sampledInterceptors;
}
public Sampler Build()
{
if (_sampler != null)
return _sampler;
if (Interlocked.CompareExchange(ref state, 1, 0) == 0)
{
var samplers = _sampledInterceptors.OrderBy(x => x.Priority).Select(interceptor =>
(Func<Sampler, Sampler>) (next => ctx => interceptor.Invoke(ctx, next))).ToList();
Sampler sampler = ctx => true;
foreach (var next in samplers)
{
sampler = next(sampler);
}
return _sampler = sampler;
}
while (_sampler == null)
{
}
return _sampler;
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Linq;
using SkyWalking.Common;
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Tracing
{
public class SegmentContextFactory : ISegmentContextFactory
{
private readonly IEntrySegmentContextAccessor _entrySegmentContextAccessor;
private readonly ILocalSegmentContextAccessor _localSegmentContextAccessor;
private readonly IExitSegmentContextAccessor _exitSegmentContextAccessor;
private readonly IRuntimeEnvironment _runtimeEnvironment;
private readonly ISamplerChainBuilder _samplerChainBuilder;
private readonly IUniqueIdGenerator _uniqueIdGenerator;
public SegmentContextFactory(IRuntimeEnvironment runtimeEnvironment,
ISamplerChainBuilder samplerChainBuilder,
IUniqueIdGenerator uniqueIdGenerator,
IEntrySegmentContextAccessor entrySegmentContextAccessor,
ILocalSegmentContextAccessor localSegmentContextAccessor,
IExitSegmentContextAccessor exitSegmentContextAccessor)
{
_runtimeEnvironment = runtimeEnvironment;
_samplerChainBuilder = samplerChainBuilder;
_uniqueIdGenerator = uniqueIdGenerator;
_entrySegmentContextAccessor = entrySegmentContextAccessor;
_localSegmentContextAccessor = localSegmentContextAccessor;
_exitSegmentContextAccessor = exitSegmentContextAccessor;
}
public SegmentContext CreateEntrySegment(string operationName, ICarrier carrier)
{
var traceId = GetTraceId(carrier);
var segmentId = GetSegmentId();
var sampled = GetSampled(carrier, operationName);
var segmentContext = new SegmentContext(traceId, segmentId, sampled, _runtimeEnvironment.ServiceId.Value,
_runtimeEnvironment.ServiceInstanceId.Value, operationName, SpanType.Entry);
if (carrier.HasValue)
{
var segmentReference = new SegmentReference
{
Reference = Reference.CrossProcess,
EntryEndpoint = carrier.EntryEndpoint,
NetworkAddress = carrier.NetworkAddress,
ParentEndpoint = carrier.ParentEndpoint,
ParentSpanId = carrier.ParentSpanId,
ParentSegmentId = carrier.ParentSegmentId,
EntryServiceInstanceId = carrier.EntryServiceInstanceId,
ParentServiceInstanceId = carrier.ParentServiceInstanceId
};
segmentContext.References.Add(segmentReference);
}
_entrySegmentContextAccessor.Context = segmentContext;
return segmentContext;
}
public SegmentContext CreateLocalSegment(string operationName)
{
var parentSegmentContext = GetParentSegmentContext(SpanType.Local);
var traceId = GetTraceId(parentSegmentContext);
var segmentId = GetSegmentId();
var sampled = GetSampled(parentSegmentContext, operationName);
var segmentContext = new SegmentContext(traceId, segmentId, sampled, _runtimeEnvironment.ServiceId.Value,
_runtimeEnvironment.ServiceInstanceId.Value, operationName, SpanType.Local);
if (parentSegmentContext != null)
{
var parentReference = parentSegmentContext.References.FirstOrDefault();
var reference = new SegmentReference
{
Reference = Reference.CrossThread,
EntryEndpoint = parentReference?.EntryEndpoint ?? parentSegmentContext.Span.OperationName,
NetworkAddress = parentReference?.NetworkAddress ?? parentSegmentContext.Span.OperationName,
ParentEndpoint = parentSegmentContext.Span.OperationName,
ParentSpanId = parentSegmentContext.Span.SpanId,
ParentSegmentId = parentSegmentContext.SegmentId,
EntryServiceInstanceId =
parentReference?.EntryServiceInstanceId ?? parentSegmentContext.ServiceInstanceId,
ParentServiceInstanceId = parentSegmentContext.ServiceInstanceId
};
segmentContext.References.Add(reference);
}
_localSegmentContextAccessor.Context = segmentContext;
return segmentContext;
}
public SegmentContext CreateExitSegment(string operationName, StringOrIntValue networkAddress)
{
var parentSegmentContext = GetParentSegmentContext(SpanType.Exit);
var traceId = GetTraceId(parentSegmentContext);
var segmentId = GetSegmentId();
var sampled = GetSampled(parentSegmentContext, operationName, networkAddress);
var segmentContext = new SegmentContext(traceId, segmentId, sampled, _runtimeEnvironment.ServiceId.Value,
_runtimeEnvironment.ServiceInstanceId.Value, operationName, SpanType.Exit);
if (parentSegmentContext != null)
{
var parentReference = parentSegmentContext.References.FirstOrDefault();
var reference = new SegmentReference
{
Reference = Reference.CrossThread,
EntryEndpoint = parentReference?.EntryEndpoint ?? parentSegmentContext.Span.OperationName,
NetworkAddress = parentReference?.NetworkAddress ?? parentSegmentContext.Span.OperationName,
ParentEndpoint = parentSegmentContext.Span.OperationName,
ParentSpanId = parentSegmentContext.Span.SpanId,
ParentSegmentId = parentSegmentContext.SegmentId,
EntryServiceInstanceId =
parentReference?.EntryServiceInstanceId ?? parentSegmentContext.ServiceInstanceId,
ParentServiceInstanceId = parentSegmentContext.ServiceInstanceId
};
segmentContext.References.Add(reference);
}
segmentContext.Span.Peer = networkAddress;
_exitSegmentContextAccessor.Context = segmentContext;
return segmentContext;
}
public void Release(SegmentContext segmentContext)
{
segmentContext.Span.Finish();
switch (segmentContext.Span.SpanType)
{
case SpanType.Entry:
_entrySegmentContextAccessor.Context = null;
break;
case SpanType.Local:
_localSegmentContextAccessor.Context = null;
break;
case SpanType.Exit:
_exitSegmentContextAccessor.Context = null;
break;
default:
throw new ArgumentOutOfRangeException(nameof(SpanType), segmentContext.Span.SpanType, "Invalid SpanType.");
}
}
private UniqueId GetTraceId(ICarrier carrier)
{
return carrier.HasValue ? carrier.TraceId : _uniqueIdGenerator.Generate();
}
private UniqueId GetTraceId(SegmentContext parentSegmentContext)
{
return parentSegmentContext?.TraceId ?? _uniqueIdGenerator.Generate();
}
private UniqueId GetSegmentId()
{
return _uniqueIdGenerator.Generate();
}
private bool GetSampled(ICarrier carrier, string operationName)
{
if (carrier.HasValue && carrier.Sampled.HasValue)
{
return carrier.Sampled.Value;
}
SamplingContext samplingContext;
if (carrier.HasValue)
{
samplingContext = new SamplingContext(operationName, carrier.NetworkAddress, carrier.EntryEndpoint,
carrier.ParentEndpoint);
}
else
{
samplingContext = new SamplingContext(operationName, default(StringOrIntValue), default(StringOrIntValue),
default(StringOrIntValue));
}
var sampler = _samplerChainBuilder.Build();
return sampler(samplingContext);
}
private bool GetSampled(SegmentContext parentSegmentContext, string operationName,
StringOrIntValue peer = default(StringOrIntValue))
{
if (parentSegmentContext != null) return parentSegmentContext.Sampled;
var sampledContext = new SamplingContext(operationName, peer, new StringOrIntValue(operationName),
default(StringOrIntValue));
var sampler = _samplerChainBuilder.Build();
return sampler(sampledContext);
}
private SegmentContext GetParentSegmentContext(SpanType spanType)
{
switch (spanType)
{
case SpanType.Entry:
return null;
case SpanType.Local:
return _entrySegmentContextAccessor.Context;
case SpanType.Exit:
return _localSegmentContextAccessor.Context ?? _entrySegmentContextAccessor.Context;
default:
throw new ArgumentOutOfRangeException(nameof(spanType), spanType, "Invalid SpanType.");
}
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Linq;
using SkyWalking.Common;
using SkyWalking.Config;
namespace SkyWalking.Tracing
{
public class Sw3CarrierFormatter : ICarrierFormatter
{
private readonly IUniqueIdParser _uniqueIdParser;
public Sw3CarrierFormatter(IUniqueIdParser uniqueIdParser, IConfigAccessor configAccessor)
{
_uniqueIdParser = uniqueIdParser;
var config = configAccessor.Get<InstrumentConfig>();
Key = string.IsNullOrEmpty(config.Namespace)
? HeaderVersions.SW3
: $"{config.Namespace}-{HeaderVersions.SW3}";
Enable = config.HeaderVersions != null && config.HeaderVersions.Contains(HeaderVersions.SW3);
}
public string Key { get; }
public bool Enable { get; }
public ICarrier Decode(string content)
{
NullableCarrier Defer()
{
return NullableCarrier.Instance;
}
if (string.IsNullOrEmpty(content))
return Defer();
var parts = content.Split('|');
if (parts.Length < 8)
return Defer();
if (!_uniqueIdParser.TryParse(parts[0], out var segmentId))
return Defer();
if (!int.TryParse(parts[1], out var parentSpanId))
return Defer();
if (!int.TryParse(parts[2], out var parentServiceInstanceId))
return Defer();
if (!int.TryParse(parts[3], out var entryServiceInstanceId))
return Defer();
if (!_uniqueIdParser.TryParse(parts[7], out var traceId))
return Defer();
return new Carrier(traceId, segmentId, parentSpanId, parentServiceInstanceId,
entryServiceInstanceId)
{
NetworkAddress = StringOrIntValueHelpers.ParseStringOrIntValue(parts[4]),
EntryEndpoint = StringOrIntValueHelpers.ParseStringOrIntValue(parts[5]),
ParentEndpoint = StringOrIntValueHelpers.ParseStringOrIntValue(parts[6])
};
}
public string Encode(ICarrier carrier)
{
if (!carrier.HasValue)
return string.Empty;
return string.Join("|",
carrier.ParentSegmentId.ToString(),
carrier.ParentSpanId.ToString(),
carrier.ParentServiceInstanceId.ToString(),
carrier.EntryServiceInstanceId.ToString(),
ConvertStringOrIntValue(carrier.NetworkAddress),
ConvertStringOrIntValue(carrier.EntryEndpoint),
ConvertStringOrIntValue(carrier.ParentEndpoint),
carrier.TraceId.ToString());
}
private static string ConvertStringOrIntValue(StringOrIntValue value)
{
if (value.HasIntValue)
{
return value.GetIntValue().ToString();
}
return "#" + value.GetStringValue();
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Linq;
using SkyWalking.Common;
using SkyWalking.Config;
namespace SkyWalking.Tracing
{
public class Sw6CarrierFormatter : ICarrierFormatter
{
private readonly IUniqueIdParser _uniqueIdParser;
private readonly IBase64Formatter _base64Formatter;
public Sw6CarrierFormatter(IUniqueIdParser uniqueIdParser, IBase64Formatter base64Formatter,
IConfigAccessor configAccessor)
{
_uniqueIdParser = uniqueIdParser;
_base64Formatter = base64Formatter;
var config = configAccessor.Get<InstrumentConfig>();
Key = string.IsNullOrEmpty(config.Namespace)
? HeaderVersions.SW6
: $"{config.Namespace}-{HeaderVersions.SW6}";
Enable = config.HeaderVersions == null || config.HeaderVersions.Contains(HeaderVersions.SW6);
}
public string Key { get; }
public bool Enable { get; }
public ICarrier Decode(string content)
{
NullableCarrier Defer()
{
return NullableCarrier.Instance;
}
if (string.IsNullOrEmpty(content))
return Defer();
var parts = content.Split('-');
if (parts.Length < 7)
return Defer();
if (!int.TryParse(parts[0], out var sampled))
return Defer();
if (!_uniqueIdParser.TryParse(_base64Formatter.Decode(parts[1]), out var traceId))
return Defer();
if (!_uniqueIdParser.TryParse(_base64Formatter.Decode(parts[2]), out var segmentId))
return Defer();
if (!int.TryParse(parts[3], out var parentSpanId))
return Defer();
if (!int.TryParse(parts[4], out var parentServiceInstanceId))
return Defer();
if (!int.TryParse(parts[5], out var entryServiceInstanceId))
return Defer();
var carrier = new Carrier(traceId, segmentId, parentSpanId, parentServiceInstanceId,
entryServiceInstanceId)
{
NetworkAddress = StringOrIntValueHelpers.ParseStringOrIntValue(_base64Formatter.Decode(parts[6])),
Sampled = sampled != 0
};
if (parts.Length >= 9)
{
carrier.ParentEndpoint =
StringOrIntValueHelpers.ParseStringOrIntValue(_base64Formatter.Decode(parts[7]));
carrier.EntryEndpoint =
StringOrIntValueHelpers.ParseStringOrIntValue(_base64Formatter.Decode(parts[8]));
}
return carrier;
}
public string Encode(ICarrier carrier)
{
if (!carrier.HasValue)
return string.Empty;
return string.Join("-",
carrier.Sampled != null && carrier.Sampled.Value ? "1" : "0",
_base64Formatter.Encode(carrier.TraceId.ToString()),
_base64Formatter.Encode(carrier.ParentSegmentId.ToString()),
carrier.ParentSpanId.ToString(),
carrier.ParentServiceInstanceId.ToString(),
carrier.EntryServiceInstanceId.ToString(),
_base64Formatter.Encode(ConvertStringOrIntValue(carrier.NetworkAddress)),
_base64Formatter.Encode(ConvertStringOrIntValue(carrier.ParentEndpoint)),
_base64Formatter.Encode(ConvertStringOrIntValue(carrier.EntryEndpoint)));
}
private static string ConvertStringOrIntValue(StringOrIntValue value)
{
if (value.HasIntValue)
{
return value.GetIntValue().ToString();
}
return "#" + value.GetStringValue();
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections;
using System.Collections.Generic;
namespace SkyWalking.Tracing
{
public class TextCarrierHeaderCollection : ICarrierHeaderCollection
{
private readonly IDictionary<string, string> _headers;
public TextCarrierHeaderCollection(IEnumerable<KeyValuePair<string, string>> headers)
{
_headers = new Dictionary<string, string>();
foreach (var header in headers)
{
_headers[header.Key] = header.Value;
}
}
public TextCarrierHeaderCollection(IDictionary<string, string> headers)
{
_headers = headers;
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return _headers.GetEnumerator();
}
public void Add(string key, string value)
{
_headers[key] = value;
}
IEnumerator IEnumerable.GetEnumerator()
{
return _headers.GetEnumerator();
}
}
}
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,81 +16,60 @@ ...@@ -16,81 +16,60 @@
* *
*/ */
using System.Collections; using System;
using System.Collections.Generic; using SkyWalking.Common;
using SkyWalking.Tracing.Segments;
using SkyWalking.Transport;
namespace SkyWalking.Context namespace SkyWalking.Tracing
{ {
public class CarrierItem : IEnumerable<CarrierItem> public class TracingContext : ITracingContext
{ {
private readonly string _headKey; private readonly ISegmentContextFactory _segmentContextFactory;
private string _headValue; private readonly ICarrierPropagator _carrierPropagator;
private readonly CarrierItem _next; private readonly ISegmentDispatcher _segmentDispatcher;
public virtual string HeadKey => _headKey; public TracingContext(ISegmentContextFactory segmentContextFactory, ICarrierPropagator carrierPropagator,
ISegmentDispatcher segmentDispatcher)
public virtual string HeadValue
{ {
get => _headValue; _segmentContextFactory = segmentContextFactory;
set => _headValue = value; _carrierPropagator = carrierPropagator;
_segmentDispatcher = segmentDispatcher;
} }
protected CarrierItem(string headKey, string headValue, string @namespace) public SegmentContext CreateEntrySegmentContext(string operationName, ICarrierHeaderCollection carrierHeader)
: this(headKey, headValue, null, @namespace)
{ {
if (operationName == null) throw new ArgumentNullException(nameof(operationName));
var carrier = _carrierPropagator.Extract(carrierHeader);
return _segmentContextFactory.CreateEntrySegment(operationName, carrier);
} }
protected CarrierItem(string headKey, string headValue, CarrierItem next, string @namespace) public SegmentContext CreateLocalSegmentContext(string operationName)
{ {
_headKey = string.IsNullOrEmpty(@namespace) ? headKey : $"{@namespace}-{headKey}"; if (operationName == null) throw new ArgumentNullException(nameof(operationName));
_headValue = headValue; return _segmentContextFactory.CreateLocalSegment(operationName);
_next = next;
} }
public IEnumerator<CarrierItem> GetEnumerator() public SegmentContext CreateExitSegmentContext(string operationName, string networkAddress,
ICarrierHeaderCollection carrierHeader = default(ICarrierHeaderCollection))
{ {
return new Enumerator(this); var segmentContext =
_segmentContextFactory.CreateExitSegment(operationName, new StringOrIntValue(networkAddress));
if (carrierHeader != null)
_carrierPropagator.Inject(segmentContext, carrierHeader);
return segmentContext;
} }
IEnumerator IEnumerable.GetEnumerator() public void Release(SegmentContext segmentContext)
{ {
return GetEnumerator(); if (segmentContext == null)
}
private class Enumerator : IEnumerator<CarrierItem>
{
private readonly CarrierItem _head;
public CarrierItem Current { get; private set; }
object IEnumerator.Current => Current;
public Enumerator(CarrierItem head)
{
_head = head;
Current = head;
}
public void Dispose()
{
}
public bool MoveNext()
{
var next = Current._next;
if (next == null)
{
return false;
}
Current = next;
return true;
}
public void Reset()
{ {
Current = _head; return;
} }
_segmentContextFactory.Release(segmentContext);
if (segmentContext.Sampled)
_segmentDispatcher.Dispatch(segmentContext);
} }
} }
} }
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Threading;
namespace SkyWalking.Tracing
{
public class UniqueIdGenerator : IUniqueIdGenerator
{
private readonly ThreadLocal<long> sequence = new ThreadLocal<long>(() => 0);
private readonly IRuntimeEnvironment _runtimeEnvironment;
public UniqueIdGenerator(IRuntimeEnvironment runtimeEnvironment)
{
_runtimeEnvironment = runtimeEnvironment;
}
public UniqueId Generate()
{
return new UniqueId(_runtimeEnvironment.ServiceInstanceId.Value,
Thread.CurrentThread.ManagedThreadId,
DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() * 10000 + GetSequence());
}
private long GetSequence()
{
if (sequence.Value++ >= 9999)
{
sequence.Value = 0;
}
return sequence.Value;
}
}
}
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace SkyWalking.Tracing
{
public class UniqueIdParser : IUniqueIdParser
{
public bool TryParse(string text, out UniqueId uniqueId)
{
uniqueId = null;
if (text == null) return false;
var parts = text.Split("\\.".ToCharArray(), 3);
if (parts.Length < 3) return false;
if (!long.TryParse(parts[0], out var part0)) return false;
if (!long.TryParse(parts[1], out var part1)) return false;
if (!long.TryParse(parts[2], out var part2)) return false;
uniqueId = new UniqueId(part0, part1, part2);
return true;
}
}
}
\ No newline at end of file
...@@ -22,6 +22,7 @@ using System.Threading; ...@@ -22,6 +22,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Transport namespace SkyWalking.Transport
{ {
...@@ -30,30 +31,41 @@ namespace SkyWalking.Transport ...@@ -30,30 +31,41 @@ namespace SkyWalking.Transport
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly TransportConfig _config; private readonly TransportConfig _config;
private readonly ISegmentReporter _segmentReporter; private readonly ISegmentReporter _segmentReporter;
private readonly ISegmentContextMapper _segmentContextMapper;
private readonly ConcurrentQueue<SegmentRequest> _segmentQueue; private readonly ConcurrentQueue<SegmentRequest> _segmentQueue;
private readonly IRuntimeEnvironment _runtimeEnvironment;
private readonly CancellationTokenSource _cancellation; private readonly CancellationTokenSource _cancellation;
public AsyncQueueSegmentDispatcher(IConfigAccessor configAccessor, ISegmentReporter segmentReporter, public AsyncQueueSegmentDispatcher(IConfigAccessor configAccessor,
ILoggerFactory loggerFactory) ISegmentReporter segmentReporter, IRuntimeEnvironment runtimeEnvironment,
ISegmentContextMapper segmentContextMapper, ILoggerFactory loggerFactory)
{ {
_segmentReporter = segmentReporter; _segmentReporter = segmentReporter;
_segmentContextMapper = segmentContextMapper;
_runtimeEnvironment = runtimeEnvironment;
_logger = loggerFactory.CreateLogger(typeof(AsyncQueueSegmentDispatcher)); _logger = loggerFactory.CreateLogger(typeof(AsyncQueueSegmentDispatcher));
_config = configAccessor.Get<TransportConfig>(); _config = configAccessor.Get<TransportConfig>();
_segmentQueue = new ConcurrentQueue<SegmentRequest>(); _segmentQueue = new ConcurrentQueue<SegmentRequest>();
_cancellation = new CancellationTokenSource(); _cancellation = new CancellationTokenSource();
} }
public bool Dispatch(SegmentRequest segment) public bool Dispatch(SegmentContext segmentContext)
{ {
if (!_runtimeEnvironment.Initialized || segmentContext == null || !segmentContext.Sampled)
return false;
// todo performance optimization for ConcurrentQueue // todo performance optimization for ConcurrentQueue
if (_config.PendingSegmentLimit < _segmentQueue.Count || _cancellation.IsCancellationRequested) if (_config.QueueSize < _segmentQueue.Count || _cancellation.IsCancellationRequested)
{ return false;
var segment = _segmentContextMapper.Map(segmentContext);
if (segment == null)
return false; return false;
}
_segmentQueue.Enqueue(segment); _segmentQueue.Enqueue(segment);
_logger.Debug($"Dispatch trace segment. [SegmentId]={segment.Segment.SegmentId}."); _logger.Debug($"Dispatch trace segment. [SegmentId]={segmentContext.SegmentId}.");
return true; return true;
} }
...@@ -62,7 +74,7 @@ namespace SkyWalking.Transport ...@@ -62,7 +74,7 @@ namespace SkyWalking.Transport
// todo performance optimization for ConcurrentQueue // todo performance optimization for ConcurrentQueue
//var queued = _segmentQueue.Count; //var queued = _segmentQueue.Count;
//var limit = queued <= _config.PendingSegmentLimit ? queued : _config.PendingSegmentLimit; //var limit = queued <= _config.PendingSegmentLimit ? queued : _config.PendingSegmentLimit;
var limit = _config.PendingSegmentLimit; var limit = _config.BatchSize;
var index = 0; var index = 0;
var segments = new List<SegmentRequest>(limit); var segments = new List<SegmentRequest>(limit);
while (index++ < limit && _segmentQueue.TryDequeue(out var request)) while (index++ < limit && _segmentQueue.TryDequeue(out var request))
......
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections.Generic;
using SkyWalking.Tracing;
using SkyWalking.Tracing.Segments;
namespace SkyWalking.Transport
{
public class SegmentContextMapper : ISegmentContextMapper
{
public SegmentRequest Map(SegmentContext segmentContext)
{
var segmentRequest = new SegmentRequest
{
UniqueIds = new[]
{
MapUniqueId(segmentContext.TraceId)
}
};
var segmentObjectRequest = new SegmentObjectRequest
{
SegmentId = MapUniqueId(segmentContext.SegmentId),
ServiceId = segmentContext.ServiceId,
ServiceInstanceId = segmentContext.ServiceId
};
segmentRequest.Segment = segmentObjectRequest;
var span = new SpanRequest
{
SpanId = segmentContext.Span.SpanId,
ParentSpanId = segmentContext.Span.ParentSpanId,
OperationName = segmentContext.Span.OperationName,
StartTime = segmentContext.Span.StartTime,
EndTime = segmentContext.Span.EndTime,
SpanType = (int) segmentContext.Span.SpanType,
SpanLayer = (int) segmentContext.Span.SpanLayer,
IsError = segmentContext.Span.IsError,
Peer = segmentContext.Span.Peer,
Component = segmentContext.Span.Component
};
foreach (var reference in segmentContext.References)
span.References.Add(new SegmentReferenceRequest
{
ParentSegmentId = MapUniqueId(reference.ParentSegmentId),
ParentServiceInstanceId = reference.ParentServiceInstanceId,
ParentSpanId = reference.ParentSpanId,
ParentEndpointName = reference.ParentEndpoint,
EntryServiceInstanceId = reference.EntryServiceInstanceId,
EntryEndpointName = reference.EntryEndpoint,
NetworkAddress = reference.NetworkAddress,
RefType = (int) reference.Reference
});
foreach (var tag in segmentContext.Span.Tags)
span.Tags.Add(new KeyValuePair<string, string>(tag.Key, tag.Value));
foreach (var log in segmentContext.Span.Logs)
{
var logData = new LogDataRequest {Timestamp = log.Timestamp};
foreach (var data in log.Data)
logData.Data.Add(new KeyValuePair<string, string>(data.Key, data.Value));
span.Logs.Add(logData);
}
segmentObjectRequest.Spans.Add(span);
return segmentRequest;
}
private static UniqueIdRequest MapUniqueId(UniqueId uniqueId)
{
return new UniqueIdRequest
{
Part1 = uniqueId.Part1,
Part2 = uniqueId.Part2,
Part3 = uniqueId.Part3
};
}
}
}
\ No newline at end of file
using System.Runtime.InteropServices;
namespace SkyWalking.Utils
{
internal static class PlatformInformation
{
private const string OSX = "Mac OS X";
private const string LINUX = "Linux";
private const string WINDOWS = "Windows";
public static string GetOSName()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return WINDOWS;
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return LINUX;
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return OSX;
}
return "Unknown";
}
}
}
...@@ -17,120 +17,90 @@ ...@@ -17,120 +17,90 @@
*/ */
using System; using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Abstractions;
using SkyWalking.Components; using SkyWalking.Common;
using SkyWalking.Config;
using SkyWalking.Context;
using SkyWalking.Context.Tag;
using SkyWalking.Context.Trace;
using SkyWalking.Diagnostics; using SkyWalking.Diagnostics;
using SkyWalking.Tracing;
using SkyWalking.Tracing.Segments;
namespace SkyWalking.AspNetCore.Diagnostics namespace SkyWalking.AspNetCore.Diagnostics
{ {
public class HostingTracingDiagnosticProcessor : ITracingDiagnosticProcessor public class HostingTracingDiagnosticProcessor : ITracingDiagnosticProcessor
{ {
public string ListenerName { get; } = "Microsoft.AspNetCore"; public string ListenerName { get; } = "Microsoft.AspNetCore";
private readonly InstrumentationConfig _config;
private readonly IContextCarrierFactory _contextCarrierFactory;
public HostingTracingDiagnosticProcessor(IConfigAccessor configAccessor, private readonly ITracingContext _tracingContext;
IContextCarrierFactory contextCarrierFactory) private readonly IEntrySegmentContextAccessor _segmentContextAccessor;
public HostingTracingDiagnosticProcessor(IEntrySegmentContextAccessor segmentContextAccessor,
ITracingContext tracingContext)
{ {
_config = configAccessor.Get<InstrumentationConfig>(); _tracingContext = tracingContext;
_contextCarrierFactory = contextCarrierFactory; _segmentContextAccessor = segmentContextAccessor;
} }
[DiagnosticName("Microsoft.AspNetCore.Hosting.BeginRequest")] [DiagnosticName("Microsoft.AspNetCore.Hosting.BeginRequest")]
public void BeginRequest([Property] HttpContext httpContext) public void BeginRequest([Property] HttpContext httpContext)
{ {
var carrier = _contextCarrierFactory.Create(); var context = _tracingContext.CreateEntrySegmentContext(httpContext.Request.Path,
foreach (var item in carrier.Items) new HttpRequestCarrierHeaderCollection(httpContext.Request));
item.HeadValue = httpContext.Request.Headers[item.HeadKey]; context.Span.SpanLayer = SpanLayer.HTTP;
var httpRequestSpan = ContextManager.CreateEntrySpan(httpContext.Request.Path, carrier); context.Span.Component = Common.Components.ASPNETCORE;
httpRequestSpan.AsHttp(); context.Span.Peer = new StringOrIntValue(httpContext.Connection.RemoteIpAddress.ToString());
httpRequestSpan.SetComponent(ComponentsDefine.AspNetCore); context.Span.AddTag(Tags.URL, httpContext.Request.GetDisplayUrl());
Tags.Url.Set(httpRequestSpan, httpContext.Request.Path); context.Span.AddTag(Tags.PATH, httpContext.Request.Path);
Tags.HTTP.Method.Set(httpRequestSpan, httpContext.Request.Method); context.Span.AddTag(Tags.HTTP_METHOD, httpContext.Request.Method);
httpRequestSpan.Log(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), context.Span.AddLog(
new Dictionary<string, object> LogEvent.Event("AspNetCore Hosting BeginRequest"),
{ LogEvent.Message(
{"event", "AspNetCore Hosting BeginRequest"}, $"Request starting {httpContext.Request.Protocol} {httpContext.Request.Method} {httpContext.Request.GetDisplayUrl()}"));
{
"message",
$"Request starting {httpContext.Request.Protocol} {httpContext.Request.Method} {httpContext.Request.GetDisplayUrl()}"
}
});
httpContext.Items[HttpContextDiagnosticStrings.SpanKey] = httpRequestSpan;
} }
[DiagnosticName("Microsoft.AspNetCore.Hosting.EndRequest")] [DiagnosticName("Microsoft.AspNetCore.Hosting.EndRequest")]
public void EndRequest([Property] HttpContext httpContext) public void EndRequest([Property] HttpContext httpContext)
{ {
var httpRequestSpan = ContextManager.ActiveSpan; var context = _segmentContextAccessor.Context;
if (httpRequestSpan == null) if (context == null)
{ {
return; return;
} }
var statusCode = httpContext.Response.StatusCode; var statusCode = httpContext.Response.StatusCode;
if (statusCode >= 400) if (statusCode >= 400)
{ {
httpRequestSpan.ErrorOccurred(); context.Span.ErrorOccurred();
} }
Tags.StatusCode.Set(httpRequestSpan, statusCode.ToString()); context.Span.AddTag(Tags.STATUS_CODE, statusCode);
httpRequestSpan.Log(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), context.Span.AddLog(
new Dictionary<string, object> LogEvent.Event("AspNetCore Hosting EndRequest"),
{ LogEvent.Message(
{"event", "AspNetCore Hosting EndRequest"}, $"Request finished {httpContext.Response.StatusCode} {httpContext.Response.ContentType}"));
{
"message", _tracingContext.Release(context);
$"Request finished {httpContext.Response.StatusCode} {httpContext.Response.ContentType}"
}
});
ContextManager.StopSpan(httpRequestSpan);
} }
[DiagnosticName("Microsoft.AspNetCore.Diagnostics.UnhandledException")] [DiagnosticName("Microsoft.AspNetCore.Diagnostics.UnhandledException")]
public void DiagnosticUnhandledException([Property] HttpContext httpContext, [Property] Exception exception) public void DiagnosticUnhandledException([Property] HttpContext httpContext, [Property] Exception exception)
{ {
ContextManager.ActiveSpan?.ErrorOccurred()?.Log(exception); _segmentContextAccessor.Context?.Span?.ErrorOccurred(exception);
} }
[DiagnosticName("Microsoft.AspNetCore.Hosting.UnhandledException")] [DiagnosticName("Microsoft.AspNetCore.Hosting.UnhandledException")]
public void HostingUnhandledException([Property] HttpContext httpContext, [Property] Exception exception) public void HostingUnhandledException([Property] HttpContext httpContext, [Property] Exception exception)
{ {
ContextManager.ActiveSpan?.ErrorOccurred()?.Log(exception); _segmentContextAccessor.Context?.Span?.ErrorOccurred(exception);
} }
//[DiagnosticName("Microsoft.AspNetCore.Mvc.BeforeAction")] //[DiagnosticName("Microsoft.AspNetCore.Mvc.BeforeAction")]
public void BeforeAction([Property] ActionDescriptor actionDescriptor, [Property] HttpContext httpContext) public void BeforeAction([Property] ActionDescriptor actionDescriptor, [Property] HttpContext httpContext)
{ {
var span = httpContext.Items[HttpContextDiagnosticStrings.SpanKey] as ISpan;
if (span == null)
{
return;
}
var events = new Dictionary<string, object>
{{"event", "AspNetCore.Mvc Executing action method"}, {"Action method", actionDescriptor.DisplayName}};
span.Log(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), events);
} }
//[DiagnosticName("Microsoft.AspNetCore.Mvc.AfterAction")] //[DiagnosticName("Microsoft.AspNetCore.Mvc.AfterAction")]
public void AfterAction([Property] ActionDescriptor actionDescriptor, [Property] HttpContext httpContext) public void AfterAction([Property] ActionDescriptor actionDescriptor, [Property] HttpContext httpContext)
{ {
var span = httpContext.Items[HttpContextDiagnosticStrings.SpanKey] as ISpan;
if (span == null)
{
return;
}
var events = new Dictionary<string, object> {{"event", "AspNetCore.Mvc Executed action method"}};
span.Log(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), events);
} }
} }
} }
\ No newline at end of file
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
using SkyWalking.Tracing;
namespace SkyWalking.AspNetCore.Diagnostics
{
public class HttpRequestCarrierHeaderCollection : ICarrierHeaderCollection
{
private readonly IEnumerable<KeyValuePair<string, string>> _headers;
public HttpRequestCarrierHeaderCollection(HttpRequest httpRequest)
{
_headers = httpRequest.Headers.Select(x => new KeyValuePair<string, string>(x.Key, x.Value)).ToArray();
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return _headers.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _headers.GetEnumerator();
}
public void Add(string key, string value)
{
throw new System.NotImplementedException();
}
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\common.props" /> <Import Project="..\..\build\common.props" />
......
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenSkywalking licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections;
using System.Collections.Generic;
using DotNetCore.CAP.Diagnostics;
using SkyWalking.Tracing;
namespace SkyWalking.Diagnostics.CAP
{
public class CapCarrierHeaderCollection : ICarrierHeaderCollection
{
private readonly TracingHeaders _tracingHeaders;
public CapCarrierHeaderCollection(TracingHeaders tracingHeaders)
{
_tracingHeaders = tracingHeaders;
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return _tracingHeaders.GetEnumerator();
}
public void Add(string key, string value)
{
_tracingHeaders.Add(key, value);
}
IEnumerator IEnumerable.GetEnumerator()
{
return _tracingHeaders.GetEnumerator();
}
}
}
\ No newline at end of file
...@@ -19,13 +19,9 @@ ...@@ -19,13 +19,9 @@
using System; using System;
using DotNetCore.CAP.Diagnostics; using DotNetCore.CAP.Diagnostics;
using DotNetCore.CAP.Infrastructure; using DotNetCore.CAP.Infrastructure;
using SkyWalking.Components; using SkyWalking.Tracing;
using SkyWalking.Context;
using SkyWalking.Context.Tag;
using SkyWalking.Context.Trace;
using CapEvents = DotNetCore.CAP.Diagnostics.CapDiagnosticListenerExtensions; using CapEvents = DotNetCore.CAP.Diagnostics.CapDiagnosticListenerExtensions;
namespace SkyWalking.Diagnostics.CAP namespace SkyWalking.Diagnostics.CAP
{ {
/// <summary> /// <summary>
...@@ -33,9 +29,7 @@ namespace SkyWalking.Diagnostics.CAP ...@@ -33,9 +29,7 @@ namespace SkyWalking.Diagnostics.CAP
/// </summary> /// </summary>
public class CapTracingDiagnosticProcessor : ITracingDiagnosticProcessor public class CapTracingDiagnosticProcessor : ITracingDiagnosticProcessor
{ {
private readonly IContextCarrierFactory _contextCarrierFactory;
private Func<BrokerEventData, string> _brokerOperationNameResolver; private Func<BrokerEventData, string> _brokerOperationNameResolver;
public string ListenerName => CapEvents.DiagnosticListenerName; public string ListenerName => CapEvents.DiagnosticListenerName;
public Func<BrokerEventData, string> BrokerOperationNameResolver public Func<BrokerEventData, string> BrokerOperationNameResolver
...@@ -45,130 +39,101 @@ namespace SkyWalking.Diagnostics.CAP ...@@ -45,130 +39,101 @@ namespace SkyWalking.Diagnostics.CAP
return _brokerOperationNameResolver ?? return _brokerOperationNameResolver ??
(_brokerOperationNameResolver = (data) => "CAP " + data.BrokerTopicName); (_brokerOperationNameResolver = (data) => "CAP " + data.BrokerTopicName);
} }
set => _brokerOperationNameResolver = value ?? throw new ArgumentNullException(nameof(BrokerOperationNameResolver)); set => _brokerOperationNameResolver =
value ?? throw new ArgumentNullException(nameof(BrokerOperationNameResolver));
} }
public CapTracingDiagnosticProcessor(IContextCarrierFactory contextCarrierFactory) private readonly ITracingContext _tracingContext;
private readonly IEntrySegmentContextAccessor _entrySegmentContextAccessor;
private readonly IExitSegmentContextAccessor _exitSegmentContextAccessor;
public CapTracingDiagnosticProcessor(ITracingContext tracingContext,
IEntrySegmentContextAccessor entrySegmentContextAccessor,
IExitSegmentContextAccessor exitSegmentContextAccessor)
{ {
_contextCarrierFactory = contextCarrierFactory; _tracingContext = tracingContext;
_exitSegmentContextAccessor = exitSegmentContextAccessor;
_entrySegmentContextAccessor = entrySegmentContextAccessor;
} }
[DiagnosticName(CapEvents.CapBeforePublish)] [DiagnosticName(CapEvents.CapBeforePublish)]
public void CapBeforePublish([Object]BrokerPublishEventData eventData) public void CapBeforePublish([Object] BrokerPublishEventData eventData)
{ {
var operationName = BrokerOperationNameResolver(eventData); var operationName = BrokerOperationNameResolver(eventData);
var contextCarrier = _contextCarrierFactory.Create(); var context = _tracingContext.CreateExitSegmentContext(operationName, eventData.BrokerAddress,
var peer = eventData.BrokerAddress; new CapCarrierHeaderCollection(eventData.Headers));
var span = ContextManager.CreateExitSpan(operationName, contextCarrier, peer); context.Span.SpanLayer = Tracing.Segments.SpanLayer.MQ;
span.SetComponent(ComponentsDefine.CAP); context.Span.Component = Common.Components.CAP;
span.SetLayer(SpanLayer.MQ); context.Span.AddTag(Common.Tags.MQ_TOPIC, eventData.BrokerTopicName);
Tags.MqTopic.Set(span, eventData.BrokerTopicName);
foreach (var item in contextCarrier.Items)
{
eventData.Headers.Add(item.HeadKey, item.HeadValue);
}
} }
[DiagnosticName(CapEvents.CapAfterPublish)] [DiagnosticName(CapEvents.CapAfterPublish)]
public void CapAfterPublish([Object]BrokerPublishEndEventData eventData) public void CapAfterPublish([Object] BrokerPublishEndEventData eventData)
{ {
ContextManager.StopSpan(); _tracingContext.Release(_exitSegmentContextAccessor.Context);
} }
[DiagnosticName(CapEvents.CapErrorPublish)] [DiagnosticName(CapEvents.CapErrorPublish)]
public void CapErrorPublish([Object]BrokerPublishErrorEventData eventData) public void CapErrorPublish([Object] BrokerPublishErrorEventData eventData)
{ {
var capSpan = ContextManager.ActiveSpan; var context = _exitSegmentContextAccessor.Context;
if (capSpan == null) if (context != null)
{ {
return; context.Span.ErrorOccurred(eventData.Exception);
_tracingContext.Release(context);
} }
capSpan.Log(eventData.Exception);
capSpan.ErrorOccurred();
ContextManager.StopSpan(capSpan);
} }
[DiagnosticName(CapEvents.CapBeforeConsume)] [DiagnosticName(CapEvents.CapBeforeConsume)]
public void CapBeforeConsume([Object]BrokerConsumeEventData eventData) public void CapBeforeConsume([Object] BrokerConsumeEventData eventData)
{ {
var operationName = BrokerOperationNameResolver(eventData); var operationName = BrokerOperationNameResolver(eventData);
var carrier = _contextCarrierFactory.Create();
ICarrierHeaderCollection carrierHeader = null;
if (Helper.TryExtractTracingHeaders(eventData.BrokerTopicBody, out var headers, if (Helper.TryExtractTracingHeaders(eventData.BrokerTopicBody, out var headers,
out var removedHeadersJson)) out var removedHeadersJson))
{ {
eventData.Headers = headers; eventData.Headers = headers;
eventData.BrokerTopicBody = removedHeadersJson; eventData.BrokerTopicBody = removedHeadersJson;
carrierHeader = new CapCarrierHeaderCollection(headers);
foreach (var tracingHeader in headers)
{
foreach (var item in carrier.Items)
{
if (tracingHeader.Key == item.HeadKey)
{
item.HeadValue = tracingHeader.Value;
}
}
}
} }
var span = ContextManager.CreateEntrySpan(operationName, carrier);
span.SetComponent(ComponentsDefine.CAP); var context = _tracingContext.CreateEntrySegmentContext(operationName, carrierHeader);
span.SetLayer(SpanLayer.MQ); context.Span.SpanLayer = Tracing.Segments.SpanLayer.MQ;
Tags.MqTopic.Set(span, eventData.BrokerTopicName); context.Span.Component = Common.Components.CAP;
context.Span.AddTag(Common.Tags.MQ_TOPIC, eventData.BrokerTopicName);
} }
[DiagnosticName(CapEvents.CapAfterConsume)] [DiagnosticName(CapEvents.CapAfterConsume)]
public void CapAfterConsume([Object]BrokerConsumeEndEventData eventData) public void CapAfterConsume([Object] BrokerConsumeEndEventData eventData)
{ {
var capSpan = ContextManager.ActiveSpan; _tracingContext.Release(_entrySegmentContextAccessor.Context);
if (capSpan == null)
{
return;
}
ContextManager.StopSpan(capSpan);
} }
[DiagnosticName(CapEvents.CapErrorConsume)] [DiagnosticName(CapEvents.CapErrorConsume)]
public void CapErrorConsume([Object]BrokerConsumeErrorEventData eventData) public void CapErrorConsume([Object] BrokerConsumeErrorEventData eventData)
{ {
var capSpan = ContextManager.ActiveSpan; var context = _entrySegmentContextAccessor.Context;
if (capSpan == null) if (context != null)
{ {
return; context.Span.ErrorOccurred(eventData.Exception);
_tracingContext.Release(context);
} }
capSpan.Log(eventData.Exception);
capSpan.ErrorOccurred();
ContextManager.StopSpan(capSpan);
} }
[DiagnosticName(CapEvents.CapBeforeSubscriberInvoke)] [DiagnosticName(CapEvents.CapBeforeSubscriberInvoke)]
public void CapBeforeSubscriberInvoke([Object]SubscriberInvokeEventData eventData) public void CapBeforeSubscriberInvoke([Object] SubscriberInvokeEventData eventData)
{ {
var span = ContextManager.CreateLocalSpan("Subscriber invoke");
span.SetComponent(ComponentsDefine.CAP);
span.Tag("subscriber.name", eventData.MethodName);
} }
[DiagnosticName(CapEvents.CapAfterSubscriberInvoke)] [DiagnosticName(CapEvents.CapAfterSubscriberInvoke)]
public void CapAfterSubscriberInvoke([Object]SubscriberInvokeEventData eventData) public void CapAfterSubscriberInvoke([Object] SubscriberInvokeEventData eventData)
{ {
ContextManager.StopSpan();
} }
[DiagnosticName(CapEvents.CapErrorSubscriberInvoke)] [DiagnosticName(CapEvents.CapErrorSubscriberInvoke)]
public void CapErrorSubscriberInvoke([Object]SubscriberInvokeErrorEventData eventData) public void CapErrorSubscriberInvoke([Object] SubscriberInvokeErrorEventData eventData)
{ {
var capSpan = ContextManager.ActiveSpan;
if (capSpan == null)
{
return;
}
capSpan.Log(eventData.Exception);
capSpan.ErrorOccurred();
ContextManager.StopSpan(capSpan);
} }
} }
} }
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\common.props" /> <Import Project="..\..\build\common.props" />
......
...@@ -24,7 +24,7 @@ namespace SkyWalking.Diagnostics.EntityFrameworkCore ...@@ -24,7 +24,7 @@ namespace SkyWalking.Diagnostics.EntityFrameworkCore
{ {
public static DatabaseProviderBuilder AddNpgsql(this DatabaseProviderBuilder builder) public static DatabaseProviderBuilder AddNpgsql(this DatabaseProviderBuilder builder)
{ {
builder.Services.AddSingleton<IEfCoreSpanMetadataProvider, NpgsqlEFCoreSpanMetadataProvider>(); builder.Services.AddSingleton<IEntityFrameworkCoreSpanMetadataProvider, NpgsqlEntityFrameworkCoreSpanMetadataProvider>();
return builder; return builder;
} }
} }
......
...@@ -17,14 +17,12 @@ ...@@ -17,14 +17,12 @@
*/ */
using System.Data.Common; using System.Data.Common;
using Npgsql;
using SkyWalking.Components;
namespace SkyWalking.Diagnostics.EntityFrameworkCore namespace SkyWalking.Diagnostics.EntityFrameworkCore
{ {
public class NpgsqlEFCoreSpanMetadataProvider : IEfCoreSpanMetadataProvider public class NpgsqlEntityFrameworkCoreSpanMetadataProvider : IEntityFrameworkCoreSpanMetadataProvider
{ {
public IComponent Component { get; } = ComponentsDefine.Npgsql_EntityFrameworkCore_PostgreSQL; public string Component { get; } = Common.Components.NPGSQL_ENTITYFRAMEWORKCORE_POSTGRESQL.GetStringValue();
public bool Match(DbConnection connection) public bool Match(DbConnection connection)
{ {
......
...@@ -18,6 +18,6 @@ ...@@ -18,6 +18,6 @@
<ProjectReference Include="..\SkyWalking.Utilities.DependencyInjection\SkyWalking.Utilities.DependencyInjection.csproj" /> <ProjectReference Include="..\SkyWalking.Utilities.DependencyInjection\SkyWalking.Utilities.DependencyInjection.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.0.0" PrivateAssets="All"/> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.0.0" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
</Project> </Project>
\ No newline at end of file
...@@ -24,7 +24,7 @@ namespace SkyWalking.Diagnostics.EntityFrameworkCore ...@@ -24,7 +24,7 @@ namespace SkyWalking.Diagnostics.EntityFrameworkCore
{ {
public static DatabaseProviderBuilder AddPomeloMysql(this DatabaseProviderBuilder builder) public static DatabaseProviderBuilder AddPomeloMysql(this DatabaseProviderBuilder builder)
{ {
builder.Services.AddSingleton<IEfCoreSpanMetadataProvider, MySqlEFCoreSpanMetadataProvider>(); builder.Services.AddSingleton<IEntityFrameworkCoreSpanMetadataProvider, MySqlEntityFrameworkCoreSpanMetadataProvider>();
return builder; return builder;
} }
} }
......
...@@ -17,14 +17,12 @@ ...@@ -17,14 +17,12 @@
*/ */
using System.Data.Common; using System.Data.Common;
using MySql.Data.MySqlClient;
using SkyWalking.Components;
namespace SkyWalking.Diagnostics.EntityFrameworkCore namespace SkyWalking.Diagnostics.EntityFrameworkCore
{ {
public class MySqlEFCoreSpanMetadataProvider : IEfCoreSpanMetadataProvider public class MySqlEntityFrameworkCoreSpanMetadataProvider : IEntityFrameworkCoreSpanMetadataProvider
{ {
public IComponent Component { get; } = ComponentsDefine.Pomelo_EntityFrameworkCore_MySql; public string Component { get; } = Common.Components.POMELO_ENTITYFRAMEWORKCORE_MYSQL.GetStringValue();
public bool Match(DbConnection connection) public bool Match(DbConnection connection)
{ {
......
...@@ -24,7 +24,7 @@ namespace SkyWalking.Diagnostics.EntityFrameworkCore ...@@ -24,7 +24,7 @@ namespace SkyWalking.Diagnostics.EntityFrameworkCore
{ {
public static DatabaseProviderBuilder AddSqlite(this DatabaseProviderBuilder builder) public static DatabaseProviderBuilder AddSqlite(this DatabaseProviderBuilder builder)
{ {
builder.Services.AddSingleton<IEfCoreSpanMetadataProvider, SqliteEFCoreSpanMetadataProvider>(); builder.Services.AddSingleton<IEntityFrameworkCoreSpanMetadataProvider, SqliteEntityFrameworkCoreSpanMetadataProvider>();
return builder; return builder;
} }
} }
......
...@@ -18,6 +18,6 @@ ...@@ -18,6 +18,6 @@
<ProjectReference Include="..\SkyWalking.Utilities.DependencyInjection\SkyWalking.Utilities.DependencyInjection.csproj" /> <ProjectReference Include="..\SkyWalking.Utilities.DependencyInjection\SkyWalking.Utilities.DependencyInjection.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.0" PrivateAssets="All"/> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.0" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
</Project> </Project>
\ No newline at end of file
...@@ -17,14 +17,12 @@ ...@@ -17,14 +17,12 @@
*/ */
using System.Data.Common; using System.Data.Common;
using Microsoft.Data.Sqlite;
using SkyWalking.Components;
namespace SkyWalking.Diagnostics.EntityFrameworkCore namespace SkyWalking.Diagnostics.EntityFrameworkCore
{ {
public class SqliteEFCoreSpanMetadataProvider : IEfCoreSpanMetadataProvider public class SqliteEntityFrameworkCoreSpanMetadataProvider : IEntityFrameworkCoreSpanMetadataProvider
{ {
public IComponent Component { get; } = ComponentsDefine.EntityFrameworkCore_Sqlite; public string Component { get; } = Common.Components.ENTITYFRAMEWORKCORE_SQLITE.GetStringValue();
public bool Match(DbConnection connection) public bool Match(DbConnection connection)
{ {
......
...@@ -22,17 +22,14 @@ using System.Linq; ...@@ -22,17 +22,14 @@ using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Storage.Internal; using Microsoft.EntityFrameworkCore.Storage.Internal;
using SkyWalking.Context; using SkyWalking.Tracing;
using SkyWalking.Context.Tag;
using SkyWalking.Context.Trace;
namespace SkyWalking.Diagnostics.EntityFrameworkCore namespace SkyWalking.Diagnostics.EntityFrameworkCore
{ {
public class EntityFrameworkCoreTracingDiagnosticProcessor : ITracingDiagnosticProcessor public class EntityFrameworkCoreTracingDiagnosticProcessor : ITracingDiagnosticProcessor
{ {
private const string TRACE_ORM = "TRACE_ORM";
private Func<CommandEventData, string> _operationNameResolver; private Func<CommandEventData, string> _operationNameResolver;
private readonly IEfCoreSpanFactory _efCoreSpanFactory; private readonly IEntityFrameworkCoreSegmentContextFactory _contextFactory;
public string ListenerName => DbLoggerCategory.Name; public string ListenerName => DbLoggerCategory.Name;
...@@ -50,50 +47,57 @@ namespace SkyWalking.Diagnostics.EntityFrameworkCore ...@@ -50,50 +47,57 @@ namespace SkyWalking.Diagnostics.EntityFrameworkCore
return "DB " + (commandType.FirstOrDefault() ?? data.ExecuteMethod.ToString()); return "DB " + (commandType.FirstOrDefault() ?? data.ExecuteMethod.ToString());
}); });
} }
set => _operationNameResolver = value ?? throw new ArgumentNullException(nameof(OperationNameResolver)); set => _operationNameResolver = value ??
throw new ArgumentNullException(nameof(OperationNameResolver));
} }
public EntityFrameworkCoreTracingDiagnosticProcessor(IEfCoreSpanFactory spanFactory) public EntityFrameworkCoreTracingDiagnosticProcessor(
IEntityFrameworkCoreSegmentContextFactory contextFactory)
{ {
_efCoreSpanFactory = spanFactory; _contextFactory = contextFactory;
} }
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting")] [DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting")]
public void CommandExecuting([Object] CommandEventData eventData) public void CommandExecuting([Object] CommandEventData eventData)
{ {
var operationName = OperationNameResolver(eventData); var operationName = OperationNameResolver(eventData);
var span = _efCoreSpanFactory.Create(operationName, eventData); var context = _contextFactory.Create(operationName, eventData.Command);
span.SetLayer(SpanLayer.DB); context.Span.SpanLayer = Tracing.Segments.SpanLayer.DB;
Tags.DbType.Set(span, "Sql"); context.Span.AddTag(Common.Tags.DB_TYPE, "Sql");
Tags.DbInstance.Set(span, eventData.Command.Connection.Database); context.Span.AddTag(Common.Tags.DB_INSTANCE, eventData.Command.Connection.Database);
Tags.DbStatement.Set(span, eventData.Command.CommandText); context.Span.AddTag(Common.Tags.DB_STATEMENT, eventData.Command.CommandText);
Tags.DbBindVariables.Set(span, BuildParameterVariables(eventData.Command.Parameters)); context.Span.AddTag(Common.Tags.DB_BIND_VARIABLES, BuildParameterVariables(eventData.Command.Parameters));
ContextManager.ContextProperties[TRACE_ORM] = true;
} }
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted")] [DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted")]
public void CommandExecuted() public void CommandExecuted([Object] CommandExecutedEventData eventData)
{ {
ContextManager.StopSpan(); if (eventData == null)
ContextManager.ContextProperties.Remove(TRACE_ORM); {
return;
}
var context = _contextFactory.GetCurrentContext(eventData.Command);
if (context != null)
{
_contextFactory.Release(context);
}
} }
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandError")] [DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandError")]
public void CommandError([Object]CommandErrorEventData eventData) public void CommandError([Object] CommandErrorEventData eventData)
{ {
var span = ContextManager.ActiveSpan; if (eventData == null)
if (span == null)
{ {
return; return;
} }
if (eventData != null) var context = _contextFactory.GetCurrentContext(eventData.Command);
if (context != null)
{ {
span.Log(eventData.Exception); context.Span.ErrorOccurred(eventData.Exception);
_contextFactory.Release(context);
} }
span.ErrorOccurred();
ContextManager.StopSpan(span);
ContextManager.ContextProperties.Remove(TRACE_ORM);
} }
private string BuildParameterVariables(DbParameterCollection dbParameters) private string BuildParameterVariables(DbParameterCollection dbParameters)
......
...@@ -17,42 +17,68 @@ ...@@ -17,42 +17,68 @@
*/ */
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Diagnostics; using System.Data.Common;
using SkyWalking.Components; using SkyWalking.Common;
using SkyWalking.Context; using SkyWalking.Tracing;
using SkyWalking.Context.Trace; using SkyWalking.Tracing.Segments;
namespace SkyWalking.Diagnostics.EntityFrameworkCore namespace SkyWalking.Diagnostics.EntityFrameworkCore
{ {
public class EfCoreSpanFactory : IEfCoreSpanFactory public class EntityFrameworkCoreSegmentContextFactory : IEntityFrameworkCoreSegmentContextFactory
{ {
private readonly IEnumerable<IEfCoreSpanMetadataProvider> _spanMetadataProviders; private readonly IEnumerable<IEntityFrameworkCoreSpanMetadataProvider> _spanMetadataProviders;
private readonly ITracingContext _tracingContext;
private readonly ILocalSegmentContextAccessor _localSegmentContextAccessor;
private readonly IExitSegmentContextAccessor _exitSegmentContextAccessor;
public EfCoreSpanFactory(IEnumerable<IEfCoreSpanMetadataProvider> spanMetadataProviders) public EntityFrameworkCoreSegmentContextFactory(
IEnumerable<IEntityFrameworkCoreSpanMetadataProvider> spanMetadataProviders,
ITracingContext tracingContext, ILocalSegmentContextAccessor localSegmentContextAccessor,
IExitSegmentContextAccessor exitSegmentContextAccessor)
{ {
_spanMetadataProviders = spanMetadataProviders; _spanMetadataProviders = spanMetadataProviders;
_tracingContext = tracingContext;
_localSegmentContextAccessor = localSegmentContextAccessor;
_exitSegmentContextAccessor = exitSegmentContextAccessor;
} }
public ISpan Create(string operationName, CommandEventData eventData) public SegmentContext GetCurrentContext(DbCommand dbCommand)
{ {
foreach (var provider in _spanMetadataProviders) foreach (var provider in _spanMetadataProviders)
if (provider.Match(eventData.Command.Connection)) return CreateSpan(operationName, eventData, provider); if (provider.Match(dbCommand.Connection))
return _exitSegmentContextAccessor.Context;
return CreateDefaultSpan(operationName, eventData); return _localSegmentContextAccessor.Context;
} }
protected virtual ISpan CreateSpan(string operationName, CommandEventData eventData, IEfCoreSpanMetadataProvider metadataProvider) public SegmentContext Create(string operationName, DbCommand dbCommand)
{ {
var span = ContextManager.CreateExitSpan(operationName, metadataProvider.GetPeer(eventData.Command.Connection)); foreach (var provider in _spanMetadataProviders)
span.SetComponent(metadataProvider.Component); if (provider.Match(dbCommand.Connection))
return span; return CreateExitSegment(operationName, dbCommand, provider);
return CreateLocalSegment(operationName, dbCommand);
}
public void Release(SegmentContext segmentContext)
{
_tracingContext.Release(segmentContext);
}
private SegmentContext CreateExitSegment(string operationName, DbCommand dbCommand,
IEntityFrameworkCoreSpanMetadataProvider metadataProvider)
{
var context = _tracingContext.CreateExitSegmentContext(operationName,
metadataProvider.GetPeer(dbCommand.Connection));
context.Span.Component = new StringOrIntValue(metadataProvider.Component);
return context;
} }
private ISpan CreateDefaultSpan(string operationName, CommandEventData eventData) private SegmentContext CreateLocalSegment(string operationName, DbCommand dbCommand)
{ {
var span = ContextManager.CreateLocalSpan(operationName); var context = _tracingContext.CreateLocalSegmentContext(operationName);
span.SetComponent(ComponentsDefine.EntityFrameworkCore); context.Span.Component = Common.Components.ENTITYFRAMEWORKCORE;
return span; return context;
} }
} }
} }
\ No newline at end of file
...@@ -16,13 +16,17 @@ ...@@ -16,13 +16,17 @@
* *
*/ */
using Microsoft.EntityFrameworkCore.Diagnostics; using System.Data.Common;
using SkyWalking.Context.Trace; using SkyWalking.Tracing.Segments;
namespace SkyWalking.Diagnostics.EntityFrameworkCore namespace SkyWalking.Diagnostics.EntityFrameworkCore
{ {
public interface IEfCoreSpanFactory public interface IEntityFrameworkCoreSegmentContextFactory
{ {
ISpan Create(string operationName, CommandEventData eventData); SegmentContext GetCurrentContext(DbCommand dbCommand);
SegmentContext Create(string operationName, DbCommand dbCommand);
void Release(SegmentContext segmentContext);
} }
} }
\ No newline at end of file
...@@ -17,13 +17,12 @@ ...@@ -17,13 +17,12 @@
*/ */
using System.Data.Common; using System.Data.Common;
using SkyWalking.Components;
namespace SkyWalking.Diagnostics.EntityFrameworkCore namespace SkyWalking.Diagnostics.EntityFrameworkCore
{ {
public interface IEfCoreSpanMetadataProvider public interface IEntityFrameworkCoreSpanMetadataProvider
{ {
IComponent Component { get; } string Component { get; }
bool Match(DbConnection connection); bool Match(DbConnection connection);
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
<RootNamespace>SkyWalking.Diagnostics.EntityFrameworkCore</RootNamespace> <RootNamespace>SkyWalking.Diagnostics.EntityFrameworkCore</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.0" PrivateAssets="All"/> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.0.0" PrivateAssets="All"/> <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.0.0" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\SkyWalking.Abstractions\SkyWalking.Abstractions.csproj" /> <ProjectReference Include="..\SkyWalking.Abstractions\SkyWalking.Abstractions.csproj" />
......
...@@ -32,7 +32,7 @@ namespace SkyWalking.Diagnostics.EntityFrameworkCore ...@@ -32,7 +32,7 @@ namespace SkyWalking.Diagnostics.EntityFrameworkCore
} }
extensions.Services.AddSingleton<ITracingDiagnosticProcessor, EntityFrameworkCoreTracingDiagnosticProcessor>(); extensions.Services.AddSingleton<ITracingDiagnosticProcessor, EntityFrameworkCoreTracingDiagnosticProcessor>();
extensions.Services.AddSingleton<IEfCoreSpanFactory, EfCoreSpanFactory>(); extensions.Services.AddSingleton<IEntityFrameworkCoreSegmentContextFactory, EntityFrameworkCoreSegmentContextFactory>();
if (optionAction != null) if (optionAction != null)
{ {
......
...@@ -18,59 +18,68 @@ ...@@ -18,59 +18,68 @@
using System; using System;
using System.Net.Http; using System.Net.Http;
using SkyWalking.Components; using SkyWalking.Common;
using SkyWalking.Context; using SkyWalking.Tracing;
using SkyWalking.Context.Tag; using SkyWalking.Tracing.Segments;
using SkyWalking.Context.Trace;
namespace SkyWalking.Diagnostics.HttpClient namespace SkyWalking.Diagnostics.HttpClient
{ {
public class HttpClientTracingDiagnosticProcessor : ITracingDiagnosticProcessor public class HttpClientTracingDiagnosticProcessor : ITracingDiagnosticProcessor
{ {
public string ListenerName { get; } = "HttpHandlerDiagnosticListener"; public string ListenerName { get; } = "HttpHandlerDiagnosticListener";
private readonly IContextCarrierFactory _contextCarrierFactory;
public HttpClientTracingDiagnosticProcessor(IContextCarrierFactory contextCarrierFactory) //private readonly IContextCarrierFactory _contextCarrierFactory;
private readonly ITracingContext _tracingContext;
private readonly IExitSegmentContextAccessor _contextAccessor;
public HttpClientTracingDiagnosticProcessor(ITracingContext tracingContext,
IExitSegmentContextAccessor contextAccessor)
{ {
_contextCarrierFactory = contextCarrierFactory; _tracingContext = tracingContext;
_contextAccessor = contextAccessor;
} }
[DiagnosticName("System.Net.Http.Request")] [DiagnosticName("System.Net.Http.Request")]
public void HttpRequest([Property(Name = "Request")] HttpRequestMessage request) public void HttpRequest([Property(Name = "Request")] HttpRequestMessage request)
{ {
var contextCarrier = _contextCarrierFactory.Create(); var context = _tracingContext.CreateExitSegmentContext(request.RequestUri.ToString(),
var peer = $"{request.RequestUri.Host}:{request.RequestUri.Port}"; $"{request.RequestUri.Host}:{request.RequestUri.Port}",
var span = ContextManager.CreateExitSpan(request.RequestUri.ToString(), contextCarrier, peer); new HttpClientICarrierHeaderCollection(request));
Tags.Url.Set(span, request.RequestUri.ToString());
span.AsHttp(); context.Span.SpanLayer = SpanLayer.HTTP;
span.SetComponent(ComponentsDefine.HttpClient); context.Span.Component = Common.Components.HTTPCLIENT;
Tags.HTTP.Method.Set(span, request.Method.ToString()); context.Span.AddTag(Tags.URL, request.RequestUri.ToString());
foreach (var item in contextCarrier.Items) context.Span.AddTag(Tags.HTTP_METHOD, request.Method.ToString());
request.Headers.Add(item.HeadKey, item.HeadValue);
} }
[DiagnosticName("System.Net.Http.Response")] [DiagnosticName("System.Net.Http.Response")]
public void HttpResponse([Property(Name = "Response")] HttpResponseMessage response) public void HttpResponse([Property(Name = "Response")] HttpResponseMessage response)
{ {
var span = ContextManager.ActiveSpan; var context = _contextAccessor.Context;
if (span != null && response != null) if (context == null)
{
return;
}
if (response != null)
{ {
Tags.StatusCode.Set(span, response.StatusCode.ToString()); var statusCode = (int) response.StatusCode;
if (statusCode >= 400)
{
context.Span.ErrorOccurred();
}
context.Span.AddTag(Tags.STATUS_CODE, statusCode);
} }
ContextManager.StopSpan(span); _tracingContext.Release(context);
} }
[DiagnosticName("System.Net.Http.Exception")] [DiagnosticName("System.Net.Http.Exception")]
public void HttpException([Property(Name = "Request")] HttpRequestMessage request, public void HttpException([Property(Name = "Request")] HttpRequestMessage request,
[Property(Name = "Exception")] Exception ex) [Property(Name = "Exception")] Exception exception)
{ {
var span = ContextManager.ActiveSpan; _contextAccessor.Context?.Span?.ErrorOccurred(exception);
if (span != null && span.IsExit)
{
span.ErrorOccurred();
}
} }
} }
} }
\ No newline at end of file
/* /*
* Licensed to the OpenSkywalking under one or more * Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
...@@ -16,33 +16,36 @@ ...@@ -16,33 +16,36 @@
* *
*/ */
namespace SkyWalking.Context.Trace
using System.Collections;
using System.Collections.Generic;
using System.Net.Http;
using SkyWalking.Tracing;
namespace SkyWalking.Diagnostics.HttpClient
{ {
public static class SpanLayerExtensions public class HttpClientICarrierHeaderCollection : ICarrierHeaderCollection
{ {
public static void AsDB(this ISpan span) private readonly HttpRequestMessage _request;
{
span.SetLayer(SpanLayer.DB);
}
public static void AsCache(this ISpan span) public HttpClientICarrierHeaderCollection(HttpRequestMessage request)
{ {
span.SetLayer(SpanLayer.CACHE); _request = request;
} }
public static void AsRPCFramework(this ISpan span) public void Add(string key, string value)
{ {
span.SetLayer(SpanLayer.RPC_FRAMEWORK); _request.Headers.Add(key, value);
} }
public static void AsHttp(this ISpan span) public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{ {
span.SetLayer(SpanLayer.HTTP); throw new System.NotImplementedException();
} }
public static void AsMQ(this ISpan span) IEnumerator IEnumerable.GetEnumerator()
{ {
span.SetLayer(SpanLayer.MQ); return GetEnumerator();
} }
} }
} }
\ No newline at end of file
...@@ -19,16 +19,22 @@ ...@@ -19,16 +19,22 @@
using System; using System;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Linq; using System.Linq;
using SkyWalking.Components; using SkyWalking.Tracing;
using SkyWalking.Context;
using SkyWalking.Context.Tag;
using SkyWalking.Context.Trace;
namespace SkyWalking.Diagnostics.SqlClient namespace SkyWalking.Diagnostics.SqlClient
{ {
public class SqlClientTracingDiagnosticProcessor : ITracingDiagnosticProcessor public class SqlClientTracingDiagnosticProcessor : ITracingDiagnosticProcessor
{ {
private const string TRACE_ORM = "TRACE_ORM"; private readonly ITracingContext _tracingContext;
private readonly IExitSegmentContextAccessor _contextAccessor;
public SqlClientTracingDiagnosticProcessor(ITracingContext tracingContext,
IExitSegmentContextAccessor contextAccessor)
{
_tracingContext = tracingContext;
_contextAccessor = contextAccessor;
}
public string ListenerName { get; } = SqlClientDiagnosticStrings.DiagnosticListenerName; public string ListenerName { get; } = SqlClientDiagnosticStrings.DiagnosticListenerName;
private static string ResolveOperationName(SqlCommand sqlCommand) private static string ResolveOperationName(SqlCommand sqlCommand)
...@@ -36,39 +42,38 @@ namespace SkyWalking.Diagnostics.SqlClient ...@@ -36,39 +42,38 @@ namespace SkyWalking.Diagnostics.SqlClient
var commandType = sqlCommand.CommandText?.Split(' '); var commandType = sqlCommand.CommandText?.Split(' ');
return $"{SqlClientDiagnosticStrings.SqlClientPrefix}{commandType?.FirstOrDefault()}"; return $"{SqlClientDiagnosticStrings.SqlClientPrefix}{commandType?.FirstOrDefault()}";
} }
private bool IsTraceORM()
{
return ContextManager.ContextProperties != null && ContextManager.ContextProperties.ContainsKey(TRACE_ORM);
}
[DiagnosticName(SqlClientDiagnosticStrings.SqlBeforeExecuteCommand)] [DiagnosticName(SqlClientDiagnosticStrings.SqlBeforeExecuteCommand)]
public void BeforeExecuteCommand([Property(Name = "Command")] SqlCommand sqlCommand) public void BeforeExecuteCommand([Property(Name = "Command")] SqlCommand sqlCommand)
{ {
if (IsTraceORM()) { return; } var context = _tracingContext.CreateExitSegmentContext(ResolveOperationName(sqlCommand),
var peer = sqlCommand.Connection.DataSource; sqlCommand.Connection.DataSource);
var span = ContextManager.CreateExitSpan(ResolveOperationName(sqlCommand), peer); context.Span.SpanLayer = Tracing.Segments.SpanLayer.DB;
span.SetLayer(SpanLayer.DB); context.Span.Component = Common.Components.SQLCLIENT;
span.SetComponent(ComponentsDefine.SqlClient); context.Span.AddTag(Common.Tags.DB_TYPE, "sql");
Tags.DbType.Set(span, "Sql"); context.Span.AddTag(Common.Tags.DB_INSTANCE, sqlCommand.Connection.Database);
Tags.DbInstance.Set(span, sqlCommand.Connection.Database); context.Span.AddTag(Common.Tags.DB_STATEMENT, sqlCommand.CommandText);
Tags.DbStatement.Set(span, sqlCommand.CommandText);
//todo Tags.DbBindVariables
} }
[DiagnosticName(SqlClientDiagnosticStrings.SqlAfterExecuteCommand)] [DiagnosticName(SqlClientDiagnosticStrings.SqlAfterExecuteCommand)]
public void AfterExecuteCommand() public void AfterExecuteCommand()
{ {
if (IsTraceORM()) { return; } var context = _contextAccessor.Context;
ContextManager.StopSpan(); if (context != null)
{
_tracingContext.Release(context);
}
} }
[DiagnosticName(SqlClientDiagnosticStrings.SqlErrorExecuteCommand)] [DiagnosticName(SqlClientDiagnosticStrings.SqlErrorExecuteCommand)]
public void ErrorExecuteCommand([Property(Name = "Exception")] Exception ex) public void ErrorExecuteCommand([Property(Name = "Exception")] Exception ex)
{ {
if (IsTraceORM()) { return; } var context = _contextAccessor.Context;
var span = ContextManager.ActiveSpan; if (context != null)
span?.ErrorOccurred(); {
span?.Log(ex); context.Span.ErrorOccurred(ex);
ContextManager.StopSpan(span); _tracingContext.Release(context);
}
} }
} }
} }
\ No newline at end of file
...@@ -20,7 +20,7 @@ using System; ...@@ -20,7 +20,7 @@ using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace SkyWalking.Transport.Grpc namespace SkyWalking.Transport.Grpc.Common
{ {
internal class AsyncLock internal class AsyncLock
{ {
......
...@@ -20,7 +20,7 @@ using System; ...@@ -20,7 +20,7 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Logging; using SkyWalking.Logging;
namespace SkyWalking.Transport.Grpc namespace SkyWalking.Transport.Grpc.Common
{ {
internal class Call internal class Call
{ {
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* *
*/ */
namespace SkyWalking.Transport.Grpc namespace SkyWalking.Transport.Grpc.Common
{ {
internal static class ExceptionHelpers internal static class ExceptionHelpers
{ {
......
...@@ -19,9 +19,10 @@ ...@@ -19,9 +19,10 @@
using System; using System;
using System.Linq; using System.Linq;
using Google.Protobuf; using Google.Protobuf;
using SkyWalking.Common;
using SkyWalking.NetworkProtocol; using SkyWalking.NetworkProtocol;
namespace SkyWalking.Transport.Grpc namespace SkyWalking.Transport.Grpc.Common
{ {
internal static class SegmentV5Helpers internal static class SegmentV5Helpers
{ {
......
...@@ -19,9 +19,10 @@ ...@@ -19,9 +19,10 @@
using System; using System;
using System.Linq; using System.Linq;
using Google.Protobuf; using Google.Protobuf;
using SkyWalking.Common;
using SkyWalking.NetworkProtocol; using SkyWalking.NetworkProtocol;
namespace SkyWalking.Transport.Grpc namespace SkyWalking.Transport.Grpc.Common
{ {
internal static class SegmentV6Helpers internal static class SegmentV6Helpers
{ {
......
...@@ -22,6 +22,7 @@ using System.Threading.Tasks; ...@@ -22,6 +22,7 @@ using System.Threading.Tasks;
using Grpc.Core; using Grpc.Core;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.Transport.Grpc.Common;
namespace SkyWalking.Transport.Grpc namespace SkyWalking.Transport.Grpc
{ {
......
...@@ -24,6 +24,7 @@ using System.Threading.Tasks; ...@@ -24,6 +24,7 @@ using System.Threading.Tasks;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.NetworkProtocol; using SkyWalking.NetworkProtocol;
using SkyWalking.Transport.Grpc.Common;
namespace SkyWalking.Transport.Grpc.V5 namespace SkyWalking.Transport.Grpc.V5
{ {
......
...@@ -19,9 +19,11 @@ ...@@ -19,9 +19,11 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Common;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.NetworkProtocol; using SkyWalking.NetworkProtocol;
using SkyWalking.Transport.Grpc.Common;
namespace SkyWalking.Transport.Grpc.V5 namespace SkyWalking.Transport.Grpc.V5
{ {
......
...@@ -22,6 +22,7 @@ using System.Threading.Tasks; ...@@ -22,6 +22,7 @@ using System.Threading.Tasks;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.NetworkProtocol; using SkyWalking.NetworkProtocol;
using SkyWalking.Transport.Grpc.Common;
namespace SkyWalking.Transport.Grpc.V6 namespace SkyWalking.Transport.Grpc.V6
{ {
......
...@@ -24,6 +24,7 @@ using System.Threading.Tasks; ...@@ -24,6 +24,7 @@ using System.Threading.Tasks;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.NetworkProtocol; using SkyWalking.NetworkProtocol;
using SkyWalking.Transport.Grpc.Common;
namespace SkyWalking.Transport.Grpc.V6 namespace SkyWalking.Transport.Grpc.V6
{ {
......
...@@ -19,9 +19,11 @@ ...@@ -19,9 +19,11 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SkyWalking.Common;
using SkyWalking.Config; using SkyWalking.Config;
using SkyWalking.Logging; using SkyWalking.Logging;
using SkyWalking.NetworkProtocol; using SkyWalking.NetworkProtocol;
using SkyWalking.Transport.Grpc.Common;
namespace SkyWalking.Transport.Grpc.V6 namespace SkyWalking.Transport.Grpc.V6
{ {
......
...@@ -33,16 +33,17 @@ namespace SkyWalking.Utilities.Configuration ...@@ -33,16 +33,17 @@ namespace SkyWalking.Utilities.Configuration
{"SkyWalking:Namespace", string.Empty}, {"SkyWalking:Namespace", string.Empty},
{"SkyWalking:ApplicationCode", "My_Service"}, {"SkyWalking:ApplicationCode", "My_Service"},
{"SkyWalking:SpanLimitPerSegment", "300"}, {"SkyWalking:SpanLimitPerSegment", "300"},
{"SkyWalking:HeaderVersions:0", HeaderVersions.SW6},
{"SkyWalking:Sampling:SamplePer3Secs", "-1"}, {"SkyWalking:Sampling:SamplePer3Secs", "-1"},
{"SkyWalking:Logging:Level", "Information"}, {"SkyWalking:Logging:Level", "Information"},
{"SkyWalking:Logging:FilePath", defaultLogFile}, {"SkyWalking:Logging:FilePath", defaultLogFile},
{"SkyWalking:Transport:Interval", "3000"}, {"SkyWalking:Transport:Interval", "3000"},
{"SkyWalking:Transport:ProtocolVersion", ProtocolVersions.V6}, {"SkyWalking:Transport:ProtocolVersion", ProtocolVersions.V6},
{"SkyWalking:Transport:PendingSegmentLimit", "30000"}, {"SkyWalking:Transport:QueueSize", "30000"},
{"SkyWalking:Transport:PendingSegmentTimeout", "1000"}, {"SkyWalking:Transport:BatchSize", "3000"},
{"SkyWalking:Transport:gRPC:Servers", "localhost:11800"}, {"SkyWalking:Transport:gRPC:Servers", "localhost:11800"},
{"SkyWalking:Transport:gRPC:Timeout", "2000"}, {"SkyWalking:Transport:gRPC:Timeout", "10000"},
{"SkyWalking:Transport:gRPC:ReportTimeout", "300000"}, {"SkyWalking:Transport:gRPC:ReportTimeout", "600000"},
{"SkyWalking:Transport:gRPC:ConnectTimeout", "10000"} {"SkyWalking:Transport:gRPC:ConnectTimeout", "10000"}
}; };
return builder.AddInMemoryCollection(defaultConfig); return builder.AddInMemoryCollection(defaultConfig);
......
...@@ -39,7 +39,7 @@ namespace SkyWalking.Utilities.Logging ...@@ -39,7 +39,7 @@ namespace SkyWalking.Utilities.Logging
{ {
_loggingConfig = configAccessor.Get<LoggingConfig>(); _loggingConfig = configAccessor.Get<LoggingConfig>();
_loggerFactory = new MSLoggerFactory(); _loggerFactory = new MSLoggerFactory();
var instrumentationConfig = configAccessor.Get<InstrumentationConfig>(); var instrumentationConfig = configAccessor.Get<InstrumentConfig>();
var level = EventLevel(_loggingConfig.Level); var level = EventLevel(_loggingConfig.Level);
......
using System; using System;
using SkyWalking.Utils; using SkyWalking.Common;
using Xunit; using Xunit;
namespace SkyWalking.Core.Tests.Utils namespace SkyWalking.Core.Tests.Utils
......
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