Unverified Commit d049ef48 authored by 吴晟 Wu Sheng's avatar 吴晟 Wu Sheng Committed by GitHub

Merge pull request #14 from liuhaoyang/dev-0.1

Release skywalking C# agent V0.1 
parents b864df72 4e2621c7
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace SkyWalking.Sample.Backend.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] {"value1", "value2"};
}
// GET api/values/5
[HttpGet("{id}")]
public async Task<string> Get(int id, [FromServices] IHttpClientFactory httpClientFactory)
{
var httpClient = httpClientFactory.CreateClient("tracing");
return await httpClient.GetStringAsync("http://www.baidu.com");
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace SkyWalking.Sample.Backend
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseUrls("http://*:5002")
.Build();
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\SkyWalking.AspNetCore\SkyWalking.AspNetCore.csproj" />
</ItemGroup>
</Project>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SkyWalking.AspNetCore;
namespace SkyWalking.Sample.Backend
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSkyWalking(option =>
{
option.DirectServers = "localhost:11800";
option.ApplicationCode = "asp-net-core-backend";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
\ No newline at end of file
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using SkyWalking.AspNetCore;
namespace SkyWalking.Sample.Frontend.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
public async Task<IEnumerable<string>> Get([FromServices] TracingHttpClient httpClient)
{
await httpClient.HttpClient.GetAsync("http://localhost:5002/api/values");
return new string[] {"value1", "value2"};
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace SkyWalking.Sample.Frontend
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseUrls("http://*:5001")
.Build();
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\SkyWalking.AspNetCore\SkyWalking.AspNetCore.csproj" />
</ItemGroup>
</Project>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SkyWalking.AspNetCore;
namespace SkyWalking.Sample.Frontend
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSkyWalking(option =>
{
option.DirectServers = "localhost:11800";
option.ApplicationCode = "asp-net-core-frontend";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
\ No newline at end of file
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
......@@ -24,6 +24,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyWalking.Core.Tests", "te
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkyWalking.NetworkProtocol.Trace", "src\SkyWalking.NetworkProtocol.Trace\SkyWalking.NetworkProtocol.Trace.csproj", "{50BE8184-EC7A-4257-AF54-764C0E61276F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Components", "Components", "{79ED86A5-E9B9-49B2-9354-C911C079D03E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{CBFF7EE0-69D7-4D6A-9BBD-8E567FF4D810}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkyWalking.AspNetCore", "src\SkyWalking.AspNetCore\SkyWalking.AspNetCore.csproj", "{D75B68C5-6788-4871-A63F-F6EB48FB0DC5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{844CEACD-4C85-4B15-9E2B-892B01FDA4BB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkyWalking.Sample.Backend", "sample\SkyWalking.Sample.Backend\SkyWalking.Sample.Backend.csproj", "{80A67B09-83F2-477F-907F-95FFF5B8FEAF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkyWalking.Sample.Frontend", "sample\SkyWalking.Sample.Frontend\SkyWalking.Sample.Frontend.csproj", "{2B4E350E-A1E5-4B4A-A642-BCA6D3887E5A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -50,16 +62,33 @@ Global
{50BE8184-EC7A-4257-AF54-764C0E61276F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{50BE8184-EC7A-4257-AF54-764C0E61276F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{50BE8184-EC7A-4257-AF54-764C0E61276F}.Release|Any CPU.Build.0 = Release|Any CPU
{D75B68C5-6788-4871-A63F-F6EB48FB0DC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D75B68C5-6788-4871-A63F-F6EB48FB0DC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D75B68C5-6788-4871-A63F-F6EB48FB0DC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D75B68C5-6788-4871-A63F-F6EB48FB0DC5}.Release|Any CPU.Build.0 = Release|Any CPU
{80A67B09-83F2-477F-907F-95FFF5B8FEAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{80A67B09-83F2-477F-907F-95FFF5B8FEAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80A67B09-83F2-477F-907F-95FFF5B8FEAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{80A67B09-83F2-477F-907F-95FFF5B8FEAF}.Release|Any CPU.Build.0 = Release|Any CPU
{2B4E350E-A1E5-4B4A-A642-BCA6D3887E5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B4E350E-A1E5-4B4A-A642-BCA6D3887E5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B4E350E-A1E5-4B4A-A642-BCA6D3887E5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B4E350E-A1E5-4B4A-A642-BCA6D3887E5A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{54B9183A-928B-43E1-9851-10E2F1CCE61C} = {05BF0D4E-C824-4EC8-8330-36C1FC49910E}
{C3860B5F-21D0-429F-8A00-B0C0F4573DF7} = {05BF0D4E-C824-4EC8-8330-36C1FC49910E}
{FD84A10C-C962-4AEA-BA06-86F08EB048E6} = {05BF0D4E-C824-4EC8-8330-36C1FC49910E}
{3915A2C2-7174-4651-A4F1-D45CD109916A} = {613F0980-91ED-4064-8E8C-168582EF4AD7}
{50BE8184-EC7A-4257-AF54-764C0E61276F} = {05BF0D4E-C824-4EC8-8330-36C1FC49910E}
{79ED86A5-E9B9-49B2-9354-C911C079D03E} = {05BF0D4E-C824-4EC8-8330-36C1FC49910E}
{CBFF7EE0-69D7-4D6A-9BBD-8E567FF4D810} = {05BF0D4E-C824-4EC8-8330-36C1FC49910E}
{C3860B5F-21D0-429F-8A00-B0C0F4573DF7} = {CBFF7EE0-69D7-4D6A-9BBD-8E567FF4D810}
{FD84A10C-C962-4AEA-BA06-86F08EB048E6} = {CBFF7EE0-69D7-4D6A-9BBD-8E567FF4D810}
{54B9183A-928B-43E1-9851-10E2F1CCE61C} = {CBFF7EE0-69D7-4D6A-9BBD-8E567FF4D810}
{50BE8184-EC7A-4257-AF54-764C0E61276F} = {CBFF7EE0-69D7-4D6A-9BBD-8E567FF4D810}
{D75B68C5-6788-4871-A63F-F6EB48FB0DC5} = {79ED86A5-E9B9-49B2-9354-C911C079D03E}
{80A67B09-83F2-477F-907F-95FFF5B8FEAF} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB}
{2B4E350E-A1E5-4B4A-A642-BCA6D3887E5A} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {94C0DA2C-CCCB-4314-93A2-9809B5DD0583}
......
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using System.Threading;
using System.Threading.Tasks;
namespace SkyWalking.Boot
{
public interface IBootService : IDisposable
{
int Order { get; }
Task Initialize(CancellationToken token);
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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.
*
*/
namespace SkyWalking.Config
{
public static class AgentConfig
{
/// <summary>
/// Namespace isolates headers in cross propagation. The HEADER name will be 'HeaderName:Namespace'.
/// </summary>
public static string Namespace { get; set; }
/// <summary>
/// Application code is showed in sky-walking-ui
/// </summary>
public static string ApplicationCode { get; set; }
/// <summary>
/// Negative or zeor means off ,by default. Sample_N_Per_3_Secs means sampling N TraceSegment in 10 seconds tops.
/// </summary>
public static int Sample_N_Per_3_Secs = -1;
/// <summary>
/// If the operation name of the first span is included in this set, this segment should be ignored.
/// </summary>
public static string IgnoreSuffix = ".jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg";
/// <summary>
/// The max number of spans in a single segment. Through this config item, skywalking keep your application memory cost estimated.
/// </summary>
public static int SpanLimitPerSegment = 300;
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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.
*
*/
namespace SkyWalking.Config
{
public class CollectorConfig
{
/// <summary>
/// service registry check interval
/// </summary>
public static long ServiceRegisterCheckInterval { get; set; } = 3;
/// <summary>
/// Collector agent_gRPC/grpc service addresses.
/// By using this, no discovery mechanism provided. The agent only uses these addresses to uplink data.
/// Recommend to use this only when collector cluster IPs are unreachable from agent side. Such as:
/// 1. Agent and collector cluster are in different VPC in Cloud.
/// 2. Agent uplinks data to collector cluster through Internet.
/// Single collector:DirectServers="127.0.0.1:11800"
/// Collector cluster:DirectServers="10.2.45.126:11800,10.2.45.127:11800"
/// </summary>
public static string DirectServers { get; set; }
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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.
*
*/
namespace SkyWalking.Config
{
public static class DictionaryConfig
{
public static int ApplicationCodeBufferSize { get; set; } = 10 * 10000;
public static int OperationNameBufferSize { get; set; } = 1000 * 10000;
}
}
\ No newline at end of file
......@@ -17,6 +17,7 @@
*/
using System.Collections.Generic;
using System.Linq;
using SkyWalking.Dictionarys;
namespace SkyWalking.Config
......@@ -36,10 +37,15 @@ namespace SkyWalking.Config
public static class Collector
{
private static IList<string> _grpcServers;
/// <summary>
/// Collector GRPC-Service address.
/// </summary>
public static IList<string> gRPCServers = new List<string>();
public static IList<string> gRPCServers
{
get => _grpcServers ?? CollectorConfig.DirectServers.Split(',').ToList();
set => _grpcServers = value;
}
}
}
}
......@@ -19,6 +19,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using SkyWalking.Config;
namespace SkyWalking.Context
{
......@@ -57,7 +58,14 @@ namespace SkyWalking.Context
public CarrierItem(String headKey, String headValue, CarrierItem next)
{
_headKey = headKey;
if (string.IsNullOrEmpty(AgentConfig.Namespace))
{
_headKey = headKey;
}
else
{
_headKey = $"{AgentConfig.Namespace}:{headKey}";
}
_headValue = headValue;
_next = next;
}
......
......@@ -29,12 +29,18 @@ namespace SkyWalking.Context
int EntryApplicationInstanceId { get; set; }
string EntryOperationName { get; set; }
int EntryOperationId { get; set; }
int ParentApplicationInstanceId { get; set; }
string ParentOperationName { get; set; }
int ParentOperationId { get; set; }
string PeerHost { get; set; }
int PeerId { get; set; }
int SpanId { get; set; }
......
/*
* Licensed to the Apache Software Foundation (ASF) 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.
*
*/
namespace SkyWalking.Context
{
public interface IIgnoreTracerContextListener
{
void AfterFinish(ITracerContext tracerContext);
}
}
\ No newline at end of file
......@@ -16,12 +16,30 @@
*
*/
using System;
using SkyWalking.Context.Trace;
namespace SkyWalking.Context
{
public interface ITracerContext
{
void Inject(IContextCarrier carrier);
void Extract(IContextCarrier carrier);
IContextSnapshot Capture { get; }
ISpan ActiveSpan { get; }
void Continued(IContextSnapshot snapshot);
string GetReadableGlobalTraceId();
ISpan CreateEntrySpan(string operationName);
ISpan CreateLocalSpan(string operationName);
ISpan CreateExitSpan(string operationName, string remotePeer);
void StopSpan(ISpan span);
}
}
......@@ -16,13 +16,12 @@
*
*/
using System;
using System.Collections.Generic;
using System.Text;
using SkyWalking.Context.Trace;
namespace SkyWalking.Context
{
interface ITracingContextListener
public interface ITracingContextListener
{
void AfterFinished(ITraceSegment traceSegment);
}
}
......@@ -28,7 +28,7 @@ namespace SkyWalking.Context.Tag
Key = tagKey;
}
protected abstract void Set(ISpan span, T tagValue);
public abstract void Set(ISpan span, T tagValue);
/**
* @return the key of this tag.
......
......@@ -27,7 +27,7 @@ namespace SkyWalking.Context.Trace
int EntryOperationId { get; }
int EntryApplicationInstance { get; }
int EntryApplicationInstanceId { get; }
TraceSegmentReference Transform();
}
......
......@@ -27,18 +27,15 @@ namespace SkyWalking.Context.Trace
private long _timestamp = 0;
private Dictionary<string, string> _logs;
private LogDataEntity(long timestamp,Dictionary<string,string> logs)
private LogDataEntity(long timestamp, Dictionary<string, string> logs)
{
_timestamp = timestamp;
_logs = logs;
}
public IReadOnlyDictionary<string,string> Logs
public IReadOnlyDictionary<string, string> Logs
{
get
{
return new ReadOnlyDictionary<string, string>(_logs);
}
get { return new ReadOnlyDictionary<string, string>(_logs); }
}
public class Builder
......@@ -57,7 +54,7 @@ namespace SkyWalking.Context.Trace
return this;
}
public Builder Add(string key,string value)
public Builder Add(string key, string value)
{
_logs.Add(key, value);
return this;
......@@ -73,10 +70,11 @@ namespace SkyWalking.Context.Trace
{
LogMessage logMessage = new LogMessage();
logMessage.Time = _timestamp;
foreach(var log in _logs)
foreach (var log in _logs)
{
logMessage.Data.Add(new KeyWithStringValue { Key = log.Key, Value = log.Value });
logMessage.Data.Add(new KeyWithStringValue {Key = log.Key, Value = log.Value});
}
return logMessage;
}
}
......
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
namespace SkyWalking.Context
{
public static class ExceptionExtensions
{
public static string ConvertToString(Exception exception, int maxLength)
{
var message = new StringBuilder();
while (exception != null)
{
message.Append(exception.Message);
PrintStackFrame(message, exception.StackTrace, maxLength, out var overMaxLength);
if (overMaxLength)
{
break;
}
exception = exception.InnerException;
}
return message.ToString();
}
private static void PrintStackFrame(StringBuilder message, string stackTrace,
int maxLength, out bool overMaxLength)
{
message.AppendLine(stackTrace);
overMaxLength = message.Length > maxLength;
}
}
}
/*
* Licensed to the Apache Software Foundation (ASF) 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 SkyWalking.NetworkProtocol;
namespace SkyWalking.Context
{
public class KeyValuePair
{
public string Key { get; }
public string Value { get; }
public KeyValuePair(string key, string value)
{
Key = key;
Value = value;
}
public KeyWithStringValue Transform()
{
var keyWithStringValue = new KeyWithStringValue
{
Key = Key,
Value = Value
};
return keyWithStringValue;
}
}
}
......@@ -18,7 +18,7 @@
namespace SkyWalking.Context.Trace
{
public static class SpanLayereExtensions
public static class SpanLayerExtensions
{
public static void AsDB(this ISpan span)
{
......
......@@ -17,35 +17,40 @@
*/
using System;
using System.Threading;
namespace SkyWalking.Context
namespace SkyWalking.Dictionarys
{
/// <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 static class ContextManager
public abstract class PossibleFound
{
private static readonly ThreadLocal<ITracerContext> CONTEXT = new ThreadLocal<ITracerContext>();
private bool _found;
private int _value;
private static ITracerContext GetOrCreate(String operationName, bool forceSampling)
protected PossibleFound(int value)
{
if (!CONTEXT.IsValueCreated)
_found = true;
_value = value;
}
protected PossibleFound()
{
_found = false;
}
public virtual void InCondition(Action<int> foundCondition, Action notFoundCondition)
{
if (_found)
{
return null;
foundCondition?.Invoke(_value);
}
else
{
return null;
notFoundCondition?.Invoke();
}
}
public static IContextSnapshot Capture()
public virtual object InCondition(Func<int, object> foundCondition, Func<object> notFoundCondition)
{
return null;
return _found ? foundCondition?.Invoke(_value) : notFoundCondition?.Invoke();
}
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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 SkyWalking.Boot;
namespace SkyWalking.Sampling
{
public interface ISampler : IBootService
{
bool TrySampling();
void ForceSampled();
}
}
\ No newline at end of file
......@@ -3,7 +3,7 @@
<PropertyGroup>
<Description>SkyWalking Core abstractions and interfaces for apm agent.</Description>
<AssemblyTitle>SkyWalking.Abstractions</AssemblyTitle>
<TargetFrameworks>netstandard1.6;net45</TargetFrameworks>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>SkyWalking.Abstractions</AssemblyName>
<PackageId>SkyWalking.Abstractions</PackageId>
<PackageTags>SkyWalking;APM</PackageTags>
......
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DiagnosticAdapter;
using SkyWalking.Context;
using SkyWalking.Context.Tag;
using SkyWalking.Context.Trace;
using SkyWalking.NetworkProtocol.Trace;
namespace SkyWalking.AspNetCore.Diagnostics
{
public class HostingDiagnosticListener : ITracingDiagnosticListener
{
public HostingDiagnosticListener()
{
}
public string ListenerName { get; } = "Microsoft.AspNetCore";
[DiagnosticName("Microsoft.AspNetCore.Hosting.HttpRequestIn")]
public void HttpRequestIn()
{
// do nothing, just enable the diagnotic source
}
[DiagnosticName("Microsoft.AspNetCore.Hosting.HttpRequestIn.Start")]
public void HttpRequestInStart(HttpContext httpContext)
{
var carrier = new ContextCarrier();
foreach (var item in carrier.Items)
item.HeadValue = httpContext.Request.Headers[item.HeadKey];
var httpRequestSpan = ContextManager.CreateEntrySpan(httpContext.Request.Path, carrier);
httpRequestSpan.AsHttp();
httpRequestSpan.SetComponent(ComponentsDefine.AspNetCore);
Tags.Url.Set(httpRequestSpan, httpContext.Request.Path);
Tags.HTTP.Method.Set(httpRequestSpan, httpContext.Request.Method);
}
[DiagnosticName("Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop")]
public void HttpRequestInStop(HttpContext httpContext)
{
var httpRequestSpan = ContextManager.ActiveSpan;
if (httpRequestSpan == null)
{
return;
}
var statusCode = httpContext.Response.StatusCode;
if (statusCode >= 400)
{
httpRequestSpan.ErrorOccurred();
}
Tags.StatusCode.Set(httpRequestSpan, statusCode.ToString());
ContextManager.StopSpan(httpRequestSpan);
}
[DiagnosticName("Microsoft.AspNetCore.Diagnostics.HandledException")]
public void DiagnosticHandledException(HttpContext httpContext, Exception exception)
{
ContextManager.ActiveSpan.ErrorOccurred();
}
[DiagnosticName("Microsoft.AspNetCore.Diagnostics.UnhandledException")]
public void DiagnosticUnhandledException(HttpContext httpContext, Exception exception)
{
ContextManager.ActiveSpan.ErrorOccurred();
}
[DiagnosticName("Microsoft.AspNetCore.Hosting.UnhandledException")]
public void HostingUnhandledException(HttpContext httpContext, Exception exception)
{
ContextManager.ActiveSpan.ErrorOccurred();
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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.
*
*/
namespace SkyWalking.AspNetCore.Diagnostics
{
public interface ITracingDiagnosticListener
{
string ListenerName { get; }
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Http;
using SkyWalking.AspNetCore.Diagnostics;
namespace SkyWalking.AspNetCore
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddSkyWalking(this IServiceCollection services,
Action<SkyWalkingOptions> options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
return services.AddSkyWalking().Configure(options);
}
public static IServiceCollection AddSkyWalking(this IServiceCollection services,
IConfiguration configuration)
{
return services.AddSkyWalking().Configure<SkyWalkingOptions>(configuration);
}
private static IServiceCollection AddSkyWalking(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddHttpClient<TracingHttpClient>("sw-tracing");
services.AddSingleton<IHostedService, SkyWalkingHostedService>();
services.TryAddSingleton<ITracingDiagnosticListener, HostingDiagnosticListener>();
services.AddTransient<HttpMessageHandlerBuilder, TracingHttpMessageHandlerBuilder>();
return services;
}
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.1.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.1.0-preview2-final" />
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="2.1.0-preview2-final" />
<PackageReference Include="Microsoft.Extensions.Http" Version="2.1.0-preview2-final" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.1.0-preview2-final" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.1.0-preview2-final" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.1.0-preview2-final" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SkyWalking.Core\SkyWalking.Core.csproj" />
</ItemGroup>
</Project>
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using SkyWalking.AspNetCore.Diagnostics;
using SkyWalking.Boot;
using SkyWalking.Config;
using SkyWalking.Remote;
namespace SkyWalking.AspNetCore
{
public class SkyWalkingHostedService : IHostedService
{
private readonly IEnumerable<ITracingDiagnosticListener> _tracingDiagnosticListeners;
private readonly DiagnosticListener _diagnosticListener;
public SkyWalkingHostedService(IOptions<SkyWalkingOptions> options, IHostingEnvironment hostingEnvironment,
IEnumerable<ITracingDiagnosticListener> tracingDiagnosticListeners, DiagnosticListener diagnosticListener)
{
if (string.IsNullOrEmpty(options.Value.DirectServers))
{
throw new ArgumentException("DirectServers cannot be empty or null.");
}
if (string.IsNullOrEmpty(options.Value.ApplicationCode))
{
options.Value.ApplicationCode = hostingEnvironment.ApplicationName;
}
AgentConfig.ApplicationCode = options.Value.ApplicationCode;
CollectorConfig.DirectServers = options.Value.DirectServers;
_tracingDiagnosticListeners = tracingDiagnosticListeners;
_diagnosticListener = diagnosticListener;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
await GrpcChannelManager.Instance.ConnectAsync();
await ServiceManager.Instance.Initialize();
foreach (var tracingDiagnosticListener in _tracingDiagnosticListeners)
_diagnosticListener.SubscribeWithAdapter(tracingDiagnosticListener);
}
public async Task StopAsync(CancellationToken cancellationToken)
{
await GrpcChannelManager.Instance.ShutdownAsync();
ServiceManager.Instance.Dispose();
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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 Microsoft.Extensions.Options;
namespace SkyWalking.AspNetCore
{
public class SkyWalkingOptions : IOptions<SkyWalkingOptions>
{
public SkyWalkingOptions Value => this;
/// <summary>
/// Application code is showed in sky-walking-ui
/// </summary>
public string ApplicationCode
{
get;
set;
}
/// <summary>
/// Collector agent_gRPC/grpc service addresses.
/// By using this, no discovery mechanism provided. The agent only uses these addresses to uplink data.
/// Recommend to use this only when collector cluster IPs are unreachable from agent side. Such as:
/// 1. Agent and collector cluster are in different VPC in Cloud.
/// 2. Agent uplinks data to collector cluster through Internet.
/// Single collector:DirectServers="127.0.0.1:11800"
/// Collector cluster:DirectServers="10.2.45.126:11800,10.2.45.127:11800"
/// </summary>
public string DirectServers
{
get;
set;
}
}
}
\ No newline at end of file
using System.Net.Http;
namespace SkyWalking.AspNetCore
{
public class TracingHttpClient
{
public HttpClient HttpClient { get; }
public TracingHttpClient(HttpClient httpClient)
{
HttpClient = httpClient;
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using SkyWalking.Context;
using SkyWalking.Context.Tag;
using SkyWalking.Context.Trace;
using SkyWalking.NetworkProtocol.Trace;
namespace SkyWalking.AspNetCore
{
public class TracingHttpHandler : DelegatingHandler
{
public TracingHttpHandler()
{
InnerHandler = new HttpClientHandler();
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
var contextCarrier = new ContextCarrier();
var peer = $"{request.RequestUri.Host}:{request.RequestUri.Port}";
var span = ContextManager.CreateExitSpan(request.RequestUri.ToString(), contextCarrier, peer);
Tags.Url.Set(span, request.RequestUri.ToString());
span.AsHttp();
span.SetComponent(ComponentsDefine.HttpClient);
Tags.HTTP.Method.Set(span, request.Method.ToString());
foreach (var item in contextCarrier.Items)
request.Headers.Add(item.HeadKey, item.HeadValue);
var response = await base.SendAsync(request, cancellationToken);
Tags.StatusCode.Set(span, response.StatusCode.ToString());
ContextManager.StopSpan(span);
return response;
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.Extensions.Http;
namespace SkyWalking.AspNetCore
{
internal class TracingHttpMessageHandlerBuilder : HttpMessageHandlerBuilder
{
private readonly TracingHttpHandler _primaryHandler = new TracingHttpHandler();
private string _name;
public override string Name
{
get => _name;
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_name = value;
}
}
public override IList<DelegatingHandler> AdditionalHandlers { get; } = new List<DelegatingHandler>();
public override HttpMessageHandler Build()
{
if (PrimaryHandler == null)
{
throw new InvalidOperationException();
}
return CreateHandlerPipeline(PrimaryHandler, AdditionalHandlers);
}
public override HttpMessageHandler PrimaryHandler
{
get => _primaryHandler;
set
{
if (value != null)
{
_primaryHandler.InnerHandler = value;
}
}
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace SkyWalking.Boot
{
public class ServiceManager : IDisposable
{
private static readonly ServiceManager _instance = new ServiceManager();
public static ServiceManager Instance => _instance;
private readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();
private readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
private ServiceManager()
{
}
private Type[] FindServiceTypes()
{
return typeof(ServiceManager).Assembly.GetTypes().Where(x =>
x.IsClass && !x.IsAbstract && typeof(IBootService).IsAssignableFrom(x))
.ToArray();
}
public object GetService(Type serviceType)
{
_services.TryGetValue(serviceType, out var instance);
return instance;
}
public T GetService<T>()
{
return (T) GetService(typeof(T));
}
public async Task Initialize()
{
var types = FindServiceTypes();
foreach (var service in types.Select(Activator.CreateInstance).OfType<IBootService>().OrderBy(x => x.Order))
{
await service.Initialize(_tokenSource.Token);
_services.Add(service.GetType(), service);
}
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void Dispose()
{
_tokenSource.Cancel();
foreach (var item in _services.Values)
{
var service = item as IBootService;
service?.Dispose();
}
_tokenSource.Dispose();
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using System.Threading;
using System.Threading.Tasks;
namespace SkyWalking.Boot
{
public abstract class TimerService : IBootService
{
protected abstract TimeSpan Interval { get; }
private Task _task;
public virtual void Dispose()
{
}
public virtual int Order { get; } = 2;
public async Task Initialize(CancellationToken token)
{
await Initializing(token);
_task = Task.Factory.StartNew(async () =>
{
while (true)
{
await Execute(token);
await Task.Delay(Interval, token);
}
},
token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
protected virtual Task Initializing(CancellationToken token)
{
return Task.CompletedTask;
}
protected abstract Task Execute(CancellationToken token);
}
}
\ No newline at end of file
using System.Collections.Generic;
/*
* Licensed to the Apache Software Foundation (ASF) 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.Collections.Generic;
using System.Linq;
using SkyWalking.Context.Ids;
using SkyWalking.Dictionarys;
......@@ -29,64 +47,85 @@ namespace SkyWalking.Context
/// </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 string _parentOperationName;
private int _parentOperationId;
private DistributedTraceId _primaryDistributedTraceId;
public DistributedTraceId DistributedTraceId
{
get { return _primaryDistributedTraceId; }
}
public DistributedTraceId DistributedTraceId => _primaryDistributedTraceId;
public int EntryApplicationInstanceId
{
get { return _entryApplicationInstanceId; }
set { _entryApplicationInstanceId = value; }
get => _entryApplicationInstanceId;
set => _entryApplicationInstanceId = value;
}
public string EntryOperationName
{
get { return _entryOperationName; }
set { _entryOperationName = "#" + value; }
get => _entryOperationName;
set => _entryOperationName = "#" + value;
}
public int EntryOperationId
{
get => _entryOperationId;
set => _entryOperationId = value;
}
public int ParentApplicationInstanceId
{
get { return _parentApplicationInstanceId; }
set { _parentApplicationInstanceId = value; }
get => _parentApplicationInstanceId;
set => _parentApplicationInstanceId = value;
}
public string ParentOperationName
{
get { return _parentOPerationName; }
set { _parentOPerationName = "#" + value; }
get => _parentOperationName;
set => _parentOperationName = "#" + value;
}
public int ParentOperationId
{
get => _parentOperationId;
set => _parentOperationId = value;
}
public string PeerHost
{
get { return _peerHost; }
set { _peerHost = value; }
get => _peerHost;
set => _peerHost = "#" + value;
}
public int PeerId
{
get => _peerId;
set => _peerId = value;
}
public int SpanId
{
get { return _spanId; }
set { _spanId = value; }
get => _spanId;
set => _spanId = value;
}
public ID TraceSegmentId
{
get { return _traceSegmentId; }
set { _traceSegmentId = value; }
get => _traceSegmentId;
set => _traceSegmentId = value;
}
public bool IsValid
......@@ -98,8 +137,9 @@ namespace SkyWalking.Context
&& _spanId > -1
&& _parentApplicationInstanceId != DictionaryUtil.NullValue
&& _entryApplicationInstanceId != DictionaryUtil.NullValue
&& string.IsNullOrEmpty(_parentOPerationName)
&& string.IsNullOrEmpty(_entryOperationName)
&& !string.IsNullOrEmpty(_peerHost)
&& !string.IsNullOrEmpty(_parentOperationName)
&& !string.IsNullOrEmpty(_entryOperationName)
&& _primaryDistributedTraceId != null;
}
}
......@@ -115,7 +155,7 @@ namespace SkyWalking.Context
_entryApplicationInstanceId = int.Parse(parts[3]);
_peerHost = parts[4];
_entryOperationName = parts[5];
_parentOPerationName = parts[6];
_parentOperationName = parts[6];
_primaryDistributedTraceId = new PropagatedTraceId(parts[7]);
}
......
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using System.Threading;
using System.Threading.Tasks;
using SkyWalking.Boot;
using SkyWalking.Config;
using SkyWalking.Context.Trace;
using SkyWalking.Dictionarys;
using SkyWalking.Sampling;
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, IBootService, IIgnoreTracerContextListener
{
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 (!DictionaryUtil.IsNull(RemoteDownstreamConfig.Agent.ApplicationId) &&
!DictionaryUtil.IsNull(RemoteDownstreamConfig.Agent.ApplicationInstanceId))
{
var suffixIdx = operationName.LastIndexOf('.');
if (suffixIdx > -1 && AgentConfig.IgnoreSuffix.Contains(operationName.Substring(suffixIdx)))
{
_context.Value = new IgnoredTracerContext();
}
else
{
var sampler = ServiceManager.Instance.GetService<SamplingService>();
if (forceSampling || sampler.TrySampling())
{
_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 ISpan CreateEntrySpan(string operationName, IContextCarrier carrier)
{
var samplingService = ServiceManager.Instance.GetService<SamplingService>();
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 void StopSpan(ISpan span)
{
Context?.StopSpan(span);
}
public void AfterFinished(ITraceSegment traceSegment)
{
_context.Value = null;
}
public void Dispose()
{
}
public int Order { get; } = 1;
public Task Initialize(CancellationToken token)
{
TracingContext.ListenerManager.Add(this);
IgnoredTracerContext.ListenerManager.Add(this);
return Task.CompletedTask;
}
public void AfterFinish(ITracerContext tracerContext)
{
_context.Value = null;
}
}
}
......@@ -28,20 +28,20 @@ namespace SkyWalking.Context
/// <summary>
/// Trace Segment Id of the parent trace segment
/// </summary>
private ID _traceSegmentId;
private readonly ID _traceSegmentId;
/// <summary>
/// span id of the parent span , in parent trace segment
/// </summary>
private int _spanId = -1;
private readonly int _spanId = -1;
private string _entryOperationName;
private string _parentOperationName;
private DistributedTraceId _primaryDistributedTraceId;
private readonly DistributedTraceId _primaryDistributedTraceId;
private int _entryApplicationInstanceId = DictionaryUtil.NullValue;
public ContextSnapshot(ID traceSegmentId, int spanId, List<DistributedTraceId> distributedTraceIds)
public ContextSnapshot(ID traceSegmentId, int spanId, IEnumerable<DistributedTraceId> distributedTraceIds)
{
_traceSegmentId = traceSegmentId;
_spanId = spanId;
......@@ -51,63 +51,45 @@ namespace SkyWalking.Context
public string EntryOperationName
{
get { return _entryOperationName; }
set { _entryOperationName = "#" + value; }
get => _entryOperationName;
set => _entryOperationName = "#" + value;
}
public string ParentOperationName
{
get { return _parentOperationName; }
set { _parentOperationName = "#" + value; }
get => _parentOperationName;
set => _parentOperationName = "#" + value;
}
public DistributedTraceId DistributedTraceId
{
get { return _primaryDistributedTraceId; }
}
public DistributedTraceId DistributedTraceId => _primaryDistributedTraceId;
public int EntryApplicationInstanceId
{
get { return _entryApplicationInstanceId; }
set { _entryApplicationInstanceId = value; }
get => _entryApplicationInstanceId;
set => _entryApplicationInstanceId = value;
}
public int SpanId
{
get { return _spanId; }
}
public int SpanId => _spanId;
public bool IsFromCurrent
{
get { return _traceSegmentId.Equals(ContextManager.Capture().TraceSegmentId); }
}
public bool IsFromCurrent => _traceSegmentId.Equals(ContextManager.Capture.TraceSegmentId);
public bool IsValid
{
get
{
return _traceSegmentId != null
&& _spanId > -1
&& _entryApplicationInstanceId != DictionaryUtil.NullValue
&& _primaryDistributedTraceId != null
&& string.IsNullOrEmpty(_entryOperationName)
&& string.IsNullOrEmpty(_parentOperationName);
}
}
public bool IsValid => _traceSegmentId != null
&& _spanId > -1
&& _entryApplicationInstanceId != DictionaryUtil.NullValue
&& _primaryDistributedTraceId != null
&& string.IsNullOrEmpty(_entryOperationName)
&& string.IsNullOrEmpty(_parentOperationName);
public ID TraceSegmentId
{
get { return _traceSegmentId; }
}
public ID TraceSegmentId => _traceSegmentId;
public int EntryOperationId
{
set { _entryOperationName = value + ""; }
set => _entryOperationName = value + "";
}
public int ParentOperationId
{
set { _parentOperationName = value + ""; }
set => _parentOperationName = value + "";
}
}
}
\ No newline at end of file
......@@ -25,7 +25,7 @@ namespace SkyWalking.Context.Ids
{
public static class GlobalIdGenerator
{
private static ThreadLocal<IDContext> threadIdSequence = new ThreadLocal<IDContext>(() => new IDContext(DateTime.Now.GetTimeMillis(), 0));
private static readonly ThreadLocal<IDContext> threadIdSequence = new ThreadLocal<IDContext>(() => new IDContext(DateTime.Now.GetTimeMillis(), 0));
public static ID Generate()
{
......@@ -37,7 +37,7 @@ namespace SkyWalking.Context.Ids
IDContext context = threadIdSequence.Value;
return new ID(
RemoteDownstreamConfig.Agent.ApplicationId,
RemoteDownstreamConfig.Agent.ApplicationInstanceId,
Thread.CurrentThread.ManagedThreadId,
context.NextSeq()
);
......@@ -51,7 +51,7 @@ namespace SkyWalking.Context.Ids
// Just for considering time-shift-back only.
private long _runRandomTimestamp;
private int _lastRandomValue;
private Random _random;
private readonly Random _random;
public IDContext(long lastTimestamp, short threadSeq)
{
......
/*
* Licensed to the Apache Software Foundation (ASF) 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.Collections.Generic;
using System.Runtime.CompilerServices;
using SkyWalking.Context.Trace;
namespace SkyWalking.Context
{
public class IgnoredTracerContext : ITracerContext
{
private static readonly NoopSpan noopSpan = new NoopSpan();
private int _stackDepth;
public void Inject(IContextCarrier carrier)
{
}
public void Extract(IContextCarrier carrier)
{
}
public IContextSnapshot Capture { get; }
public ISpan ActiveSpan { get; }
public void Continued(IContextSnapshot snapshot)
{
}
public string GetReadableGlobalTraceId()
{
return string.Empty;
}
public ISpan CreateEntrySpan(string operationName)
{
_stackDepth++;
return noopSpan;
}
public ISpan CreateLocalSpan(string operationName)
{
_stackDepth++;
return noopSpan;
}
public ISpan CreateExitSpan(string operationName, string remotePeer)
{
_stackDepth++;
return noopSpan;
}
public void StopSpan(ISpan span)
{
_stackDepth--;
if (_stackDepth == 0) {
ListenerManager.NotifyFinish(this);
}
}
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
......@@ -23,7 +23,7 @@ namespace SkyWalking.Context
public class SW3CarrierItem : CarrierItem
{
public const String HEADER_NAME = "sw3";
private IContextCarrier _carrier;
private readonly IContextCarrier _carrier;
public SW3CarrierItem(IContextCarrier carrier, CarrierItem next)
: base(HEADER_NAME, carrier.Serialize(), next)
......
......@@ -26,7 +26,7 @@ namespace SkyWalking.Context.Tag
{
}
protected override void Set(ISpan span, string tagValue)
public override void Set(ISpan span, string tagValue)
{
span.Tag(Key, tagValue);
}
......
......@@ -24,46 +24,46 @@ namespace SkyWalking.Context.Tag
/// </summary>
public static class Tags
{
public static StringTag URL = new StringTag("url");
public static readonly StringTag Url = new StringTag("url");
/**
* STATUS_CODE records the http status code of the response.
*/
public static StringTag STATUS_CODE = new StringTag("status_code");
public static readonly StringTag StatusCode = new StringTag("status_code");
/**
* DB_TYPE records database type, such as sql, redis, cassandra and so on.
*/
public static StringTag DB_TYPE = new StringTag("db.type");
public static readonly StringTag DbType = new StringTag("db.type");
/**
* DB_INSTANCE records database instance name.
*/
public static StringTag DB_INSTANCE = new StringTag("db.instance");
public static readonly StringTag DbInstance = new StringTag("db.instance");
/**
* DB_STATEMENT records the sql statement of the database access.
*/
public static StringTag DB_STATEMENT = new StringTag("db.statement");
public static readonly StringTag DbStatement = new StringTag("db.statement");
/**
* DB_BIND_VARIABLES records the bind variables of sql statement.
*/
public static StringTag DB_BIND_VARIABLES = new StringTag("db.bind_vars");
public static readonly StringTag DbBindVariables = new StringTag("db.bind_vars");
/**
* MQ_BROKER records the broker address of message-middleware
*/
public static StringTag MQ_BROKER = new StringTag("mq.broker");
public static readonly StringTag MqBorker = new StringTag("mq.broker");
/**
* MQ_TOPIC records the topic name of message-middleware
*/
public static StringTag MQ_TOPIC = new StringTag("mq.topic");
public static readonly StringTag MqTopic = new StringTag("mq.topic");
public static class HTTP
{
public static readonly StringTag METHOD = new StringTag("http.method");
public static readonly StringTag Method = new StringTag("http.method");
}
}
}
\ No newline at end of file
......@@ -27,16 +27,34 @@ namespace SkyWalking.Context.Trace
{
public class ExitSpan : StackBasedTracingSpan, IWithPeerInfo
{
private string _peer;
private int _peerId;
private readonly string _peer;
private readonly int _peerId;
protected ExitSpan(int spanId, int parentSpanId, string operationName,string peer) : base(spanId, parentSpanId, operationName)
public ExitSpan(int spanId, int parentSpanId, String operationName, String peer)
: base(spanId, parentSpanId, operationName)
{
_peer = peer;
_peerId = DictionaryUtil.NullValue;
}
protected ExitSpan(int spanId, int parentSpanId, int operationId,int peerId) : base(spanId, parentSpanId, operationId)
public ExitSpan(int spanId, int parentSpanId, int operationId, int peerId)
: base(spanId, parentSpanId, operationId)
{
_peer = null;
_peerId = peerId;
}
public ExitSpan(int spanId, int parentSpanId, int operationId, String peer)
: base(spanId, parentSpanId, operationId)
{
_peer = peer;
_peerId = DictionaryUtil.NullValue;
}
public ExitSpan(int spanId, int parentSpanId, String operationName, int peerId)
: base(spanId, parentSpanId, operationName)
{
_peer = null;
_peerId = peerId;
}
......@@ -54,6 +72,7 @@ namespace SkyWalking.Context.Trace
{
base.Start();
}
return base.Start();
}
......@@ -63,6 +82,7 @@ namespace SkyWalking.Context.Trace
{
base.Tag(key, value);
}
return this;
}
......@@ -72,6 +92,7 @@ namespace SkyWalking.Context.Trace
{
return base.SetLayer(layer);
}
return this;
}
......@@ -81,6 +102,7 @@ namespace SkyWalking.Context.Trace
{
return base.SetComponent(component);
}
return this;
}
......@@ -90,15 +112,13 @@ namespace SkyWalking.Context.Trace
{
return base.SetComponent(componentName);
}
return this;
}
public override string OperationName
{
get
{
return base.OperationName;
}
get { return base.OperationName; }
set
{
if (_stackDepth == 1)
......@@ -110,10 +130,7 @@ namespace SkyWalking.Context.Trace
public override int OperationId
{
get
{
return base.OperationId;
}
get { return base.OperationId; }
set
{
if (_stackDepth == 1)
......@@ -125,7 +142,7 @@ namespace SkyWalking.Context.Trace
public override SpanObject Transform()
{
var spanObject= base.Transform();
var spanObject = base.Transform();
if (_peerId != DictionaryUtil.NullValue)
{
......
......@@ -21,11 +21,11 @@ namespace SkyWalking.Context.Trace
{
public class LocalSpan : StackBasedTracingSpan
{
protected LocalSpan(int spanId, int parentSpanId, string operationName) : base(spanId, parentSpanId, operationName)
public LocalSpan(int spanId, int parentSpanId, string operationName) : base(spanId, parentSpanId, operationName)
{
}
protected LocalSpan(int spanId, int parentSpanId, int operationId) : base(spanId, parentSpanId, operationId)
public LocalSpan(int spanId, int parentSpanId, int operationId) : base(spanId, parentSpanId, operationId)
{
}
......
/*
* Licensed to the Apache Software Foundation (ASF) 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.Collections.Generic;
using System.Linq;
using Google.Protobuf;
using SkyWalking.Config;
using SkyWalking.Context.Ids;
using SkyWalking.NetworkProtocol;
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 = false;
public int ApplicationId => RemoteDownstreamConfig.Agent.ApplicationId;
public int ApplicationInstanceId => RemoteDownstreamConfig.Agent.ApplicationInstanceId;
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 UpstreamSegment Transform()
{
var upstreamSegment = new UpstreamSegment();
upstreamSegment.GlobalTraceIds.AddRange(_relatedGlobalTraces.GetRelatedGlobalTraces()
.Select(x => x.ToUniqueId()));
var traceSegment = new TraceSegmentObject {TraceSegmentId = TraceSegmentId.Transform()};
traceSegment.Spans.AddRange(_spans.Select(x => x.Transform()));
traceSegment.ApplicationId = ApplicationId;
traceSegment.ApplicationInstanceId = ApplicationInstanceId;
traceSegment.IsSizeLimited = _isSizeLimited;
upstreamSegment.Segment = traceSegment.ToByteString();
return upstreamSegment;
}
public override string ToString()
{
return "TraceSegment{"
+
$"traceSegmentId='{TraceSegmentId}', refs={_refs}, spans={_spans}, relatedGlobalTraces={_relatedGlobalTraces}"
+ "}";
}
}
}
\ No newline at end of file
......@@ -146,7 +146,7 @@ namespace SkyWalking.Context.Trace
public int EntryOperationId => _entryOperationId;
public int EntryApplicationInstance => _entryApplicationInstanceId;
public int EntryApplicationInstanceId => _entryApplicationInstanceId;
public TraceSegmentReference Transform()
{
......
This diff is collapsed.
/*
* Licensed to the Apache Software Foundation (ASF) 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.
*
*/
namespace SkyWalking.Dictionarys
{
public class DictionaryManager
{
public static NetworkAddressDictionary NetworkAddress => NetworkAddressDictionary.Instance;
public static OperationNameDictionary OperationName => OperationNameDictionary.Instance;
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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 SkyWalking.Dictionarys;
namespace SkyWalking.Dictionarys
{
public class Found : PossibleFound
{
public Found(int value)
: base(value)
{
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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.Collections.Concurrent;
using SkyWalking.Config;
using SkyWalking.Dictionarys;
using SkyWalking.NetworkProtocol;
namespace SkyWalking.Dictionarys
{
public class NetworkAddressDictionary
{
private static readonly NetworkAddressDictionary _instance = new NetworkAddressDictionary();
public static NetworkAddressDictionary Instance => _instance;
private NetworkAddressDictionary()
{
}
private readonly ConcurrentDictionary<string, int> _applicationDic = new ConcurrentDictionary<string, int>();
private readonly ConcurrentDictionary<string, object> _unRegisterApps =
new ConcurrentDictionary<string, object>();
public PossibleFound Find(string networkAddress)
{
if (_applicationDic.TryGetValue(networkAddress, out var id))
{
return new Found(id);
}
if (_applicationDic.Count + _unRegisterApps.Count < DictionaryConfig.ApplicationCodeBufferSize)
{
_unRegisterApps.TryAdd(networkAddress, null);
}
return NotFound.Instance;
}
public void SyncRemote(NetworkAddressRegisterService.NetworkAddressRegisterServiceClient serviceClient)
{
if (_unRegisterApps.Count <= 0) return;
var networkAddress = new NetworkAddresses();
networkAddress.Addresses.Add(_unRegisterApps.Keys);
var mapping = serviceClient.batchRegister(networkAddress);
if (mapping.AddressIds.Count <= 0) return;
foreach (var id in mapping.AddressIds)
{
_unRegisterApps.TryRemove(id.Key, out _);
_applicationDic.TryAdd(id.Key, id.Value);
}
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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 SkyWalking.Dictionarys;
namespace SkyWalking.Dictionarys
{
public class NotFound : PossibleFound
{
public NotFound()
: base()
{
}
public static readonly PossibleFound Instance = new NotFound();
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Xml.Schema;
using SkyWalking.Config;
using SkyWalking.Dictionarys;
using SkyWalking.NetworkProtocol;
namespace SkyWalking.Dictionarys
{
public class OperationNameDictionary
{
private static readonly OperationNameDictionary _instance=new OperationNameDictionary();
public static OperationNameDictionary Instance => _instance;
private OperationNameDictionary()
{
}
private readonly ConcurrentDictionary<OperationNameKey,int> _operationNameDic=new ConcurrentDictionary<OperationNameKey, int>();
private readonly ConcurrentDictionary<OperationNameKey,object> _unRegisterOpNames=new ConcurrentDictionary<OperationNameKey, object>();
public PossibleFound FindOrPrepareForRegister(int applicationId, string operationName, bool isEntry,
bool isExit)
{
return internalFind(applicationId, operationName, isEntry, isExit, true);
}
public PossibleFound FindOnly(int applicationId, string operationName)
{
return internalFind(applicationId, operationName, false, false, false);
}
private PossibleFound internalFind(int applicationId, string operationName, bool isEntry, bool isExit,
bool registerWhenNotFound)
{
if (string.IsNullOrEmpty(operationName))
{
return NotFound.Instance;
}
var operationNameKey = new OperationNameKey(applicationId, operationName, isEntry, isExit);
if (_operationNameDic.TryGetValue(operationNameKey, out var id))
{
return new Found(id);
}
else
{
if (registerWhenNotFound && _operationNameDic.Count + _unRegisterOpNames.Count <
DictionaryConfig.OperationNameBufferSize)
{
_unRegisterOpNames.TryAdd(operationNameKey, null);
}
return NotFound.Instance;
}
}
public void SyncRemote(ServiceNameDiscoveryService.ServiceNameDiscoveryServiceClient serviceClient)
{
if (_unRegisterOpNames.Count > 0)
{
var serviceNameCollection = new ServiceNameCollection();
foreach (var opName in _unRegisterOpNames)
{
var serviceName = new ServiceNameElement();
serviceName.ApplicationId = opName.Key.ApplicationId;
serviceName.ServiceName = opName.Key.OperationName;
serviceName.SrcSpanType = opName.Key.SpanType;
serviceNameCollection.Elements.Add(serviceName);
}
var mapping = serviceClient.discovery(serviceNameCollection);
foreach (var item in mapping.Elements)
{
var element = item.Element;
var key = new OperationNameKey(element.ApplicationId, element.ServiceName,
SpanType.Entry == element.SrcSpanType, SpanType.Exit == element.SrcSpanType);
_unRegisterOpNames.TryRemove(key, out _);
_operationNameDic.TryAdd(key, item.ServiceId);
}
}
}
}
public class OperationNameKey : IEquatable<OperationNameKey>
{
private readonly int _applicationId;
private readonly string _operationName;
private readonly bool _isEntry;
private readonly bool _isExit;
public OperationNameKey(int applicationId, string operationName, bool isEntry, bool isExit)
{
_applicationId = applicationId;
_operationName = operationName;
_isEntry = isEntry;
_isExit = isExit;
}
public int ApplicationId => _applicationId;
public string OperationName => _operationName;
public bool Equals(OperationNameKey other)
{
if (other == null)
{
return false;
}
var isMatch = _applicationId == other._applicationId || _operationName == other._operationName;
return isMatch && _isEntry == other._isEntry && _isExit == other._isExit;
}
public override bool Equals(object obj)
{
var other = obj as OperationNameKey;
return Equals(other);
}
public override int GetHashCode()
{
var result = _applicationId;
result = 31 * result + _operationName.GetHashCode();
return result;
}
public SpanType SpanType
{
get
{
if (_isEntry)
{
return SpanType.Entry;
}
else if(_isExit)
{
return SpanType.Exit;
}
else
{
return SpanType.Local;
}
}
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using System.Diagnostics;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using SkyWalking.Boot;
using SkyWalking.Config;
using SkyWalking.Context;
using SkyWalking.Dictionarys;
using SkyWalking.NetworkProtocol;
namespace SkyWalking.Remote
{
public class GrpcApplicationService : TimerService
{
public override int Order { get; } = -1;
protected override async Task Initializing(CancellationToken token)
{
var application = new Application {ApplicationCode = AgentConfig.ApplicationCode};
var applicationRegisterService =
new ApplicationRegisterService.ApplicationRegisterServiceClient(GrpcChannelManager.Instance.Channel);
var applicationId = default(int?);
while (!applicationId.HasValue || DictionaryUtil.IsNull(applicationId.Value))
{
var applicationMapping = await applicationRegisterService.applicationCodeRegisterAsync(application);
applicationId = applicationMapping?.Application?.Value;
}
RemoteDownstreamConfig.Agent.ApplicationId = applicationId.Value;
var instanceDiscoveryService =
new InstanceDiscoveryService.InstanceDiscoveryServiceClient(GrpcChannelManager.Instance.Channel);
var agentUUID = Guid.NewGuid().ToString().Replace("-", "");
var registerTime = DateTime.UtcNow.GetTimeMillis();
var hostName = Dns.GetHostName();
var osInfo = new OSInfo
{
Hostname = hostName,
OsName = Environment.OSVersion.ToString(),
ProcessNo = Process.GetCurrentProcess().Id
};
// todo fix Device not configured
//var ipv4s = Dns.GetHostAddresses(hostName);
//foreach (var ipAddress in ipv4s.Where(x => x.AddressFamily == AddressFamily.InterNetwork))
// osInfo.Ipv4S.Add(ipAddress.ToString());
var applicationInstance = new ApplicationInstance
{
ApplicationId = applicationId.Value,
AgentUUID = agentUUID,
RegisterTime = registerTime,
Osinfo = osInfo
};
var applicationInstanceId = 0;
while (DictionaryUtil.IsNull(applicationInstanceId))
{
var applicationInstanceMapping = await instanceDiscoveryService.registerInstanceAsync(applicationInstance);
applicationInstanceId = applicationInstanceMapping.ApplicationInstanceId;
}
RemoteDownstreamConfig.Agent.ApplicationInstanceId = applicationInstanceId;
}
protected override TimeSpan Interval { get; } = TimeSpan.FromMinutes(1);
protected override async Task Execute(CancellationToken token)
{
var instanceDiscoveryService =
new InstanceDiscoveryService.InstanceDiscoveryServiceClient(GrpcChannelManager.Instance.Channel);
var heartbeat = new ApplicationInstanceHeartbeat
{
ApplicationInstanceId = RemoteDownstreamConfig.Agent.ApplicationInstanceId,
HeartbeatTime = DateTime.UtcNow.GetTimeMillis()
};
await instanceDiscoveryService.heartbeatAsync(heartbeat);
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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.Linq;
using System.Threading.Tasks;
using Grpc.Core;
using SkyWalking.Boot;
using SkyWalking.Config;
namespace SkyWalking.Remote
{
public class GrpcChannelManager
{
private static readonly GrpcChannelManager _client = new GrpcChannelManager();
public static GrpcChannelManager Instance => _client;
private Channel _channel;
public Channel Channel => _channel;
private GrpcChannelManager()
{
_channel = new Channel(RemoteDownstreamConfig.Collector.gRPCServers.First(), ChannelCredentials.Insecure);
}
public Task ConnectAsync()
{
return _channel.ConnectAsync();
}
public Task ShutdownAsync()
{
return _channel.ShutdownAsync();
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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;
using System.Threading;
using System.Threading.Tasks;
using SkyWalking.Boot;
namespace SkyWalking.Remote
{
public class GrpcRuntimeService : TimerService
{
protected override TimeSpan Interval { get; } = TimeSpan.FromSeconds(120);
protected override Task Execute(CancellationToken token)
{
// todo
return Task.CompletedTask;
}
}
}
\ No newline at end of file
using System.Threading;
using System.Threading.Tasks;
using SkyWalking.Boot;
using SkyWalking.Context;
using SkyWalking.Context.Trace;
using SkyWalking.NetworkProtocol;
namespace SkyWalking.Remote
{
public class GrpcTraceSegmentService : IBootService, ITracingContextListener
{
public void Dispose()
{
TracingContext.ListenerManager.Remove(this);
}
public int Order { get; } = 1;
public Task Initialize(CancellationToken token)
{
TracingContext.ListenerManager.Add(this);
return Task.CompletedTask;
}
public async void AfterFinished(ITraceSegment traceSegment)
{
var segment = traceSegment.Transform();
var traceSegmentService =
new TraceSegmentService.TraceSegmentServiceClient(GrpcChannelManager.Instance.Channel);
using (var asyncClientStreamingCall = traceSegmentService.collect())
{
await asyncClientStreamingCall.RequestStream.WriteAsync(segment);
await asyncClientStreamingCall.RequestStream.CompleteAsync();
}
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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.Threading;
using System.Threading.Tasks;
namespace SkyWalking.Sampling
{
public class SamplingService : ISampler
{
public bool TrySampling()
{
return true;
}
public void ForceSampled()
{
}
public void Dispose()
{
}
public int Order { get; } = 1;
public Task Initialize(CancellationToken token)
{
return Task.CompletedTask;
}
}
}
\ No newline at end of file
......@@ -3,7 +3,7 @@
<PropertyGroup>
<Description>SkyWalking core components.</Description>
<AssemblyTitle>SkyWalking.Core</AssemblyTitle>
<TargetFrameworks>netstandard1.6;net45</TargetFrameworks>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>SkyWalking.Core</AssemblyName>
<PackageId>SkyWalking.Core</PackageId>
<PackageTags>SkyWalking;APM</PackageTags>
......
/*
* Licensed to the Apache Software Foundation (ASF) 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.Threading;
namespace SkyWalking.Utils
{
public class AtomicInteger
{
private int _value;
public int Value => _value;
public AtomicInteger()
: this(0)
{
}
public AtomicInteger(int defaultValue)
{
_value = defaultValue;
}
public int Increment()
{
Interlocked.Increment(ref _value);
return _value;
}
public int Decrement()
{
Interlocked.Decrement(ref _value);
return _value;
}
public int Add(int value)
{
AddInternal(value);
return _value;
}
private void AddInternal(int value)
{
Interlocked.Add(ref _value, value);
}
public override bool Equals(object obj)
{
switch (obj)
{
case AtomicInteger atomicInteger:
return atomicInteger._value == _value;
case int value:
return value == _value;
default:
return false;
}
}
public override int GetHashCode()
{
return _value.GetHashCode();
}
public static AtomicInteger operator +(AtomicInteger atomicInteger, int value)
{
atomicInteger.AddInternal(value);
return atomicInteger;
}
public static AtomicInteger operator +(int value, AtomicInteger atomicInteger)
{
atomicInteger.AddInternal(value);
return atomicInteger;
}
public static AtomicInteger operator -(AtomicInteger atomicInteger, int value)
{
atomicInteger.AddInternal(-value);
return atomicInteger;
}
public static AtomicInteger operator -(int value, AtomicInteger atomicInteger)
{
atomicInteger.AddInternal(-value);
return atomicInteger;
}
public static implicit operator AtomicInteger(int value)
{
return new AtomicInteger(value);
}
public static implicit operator int(AtomicInteger atomicInteger)
{
return atomicInteger._value;
}
public static bool operator ==(AtomicInteger atomicInteger, int value)
{
return atomicInteger._value == value;
}
public static bool operator !=(AtomicInteger atomicInteger, int value)
{
return !(atomicInteger == value);
}
public static bool operator ==(int value, AtomicInteger atomicInteger)
{
return atomicInteger._value == value;
}
public static bool operator !=(int value, AtomicInteger atomicInteger)
{
return !(value == atomicInteger);
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) 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.Collections.Generic;
namespace SkyWalking.Utils
{
public static class StackExtensions
{
public static bool TryPeek<T>(this Stack<T> stack, out T value)
{
if (stack == null || stack.Count == 0)
{
value = default(T);
return false;
}
value = stack.Peek();
return true;
}
public static bool TryPop<T>(this Stack<T> stack, out T value)
{
if (stack == null || stack.Count == 0)
{
value = default(T);
return false;
}
value = stack.Pop();
return true;
}
}
}
\ No newline at end of file
......@@ -17,12 +17,17 @@
*/
using System.Collections.Generic;
using System.Runtime.InteropServices.ComTypes;
namespace SkyWalking.NetworkProtocol.Trace
{
public class ComponentsDefine
{
public static readonly OfficialComponent AspNetCore = new OfficialComponent(1, "AspNetCore");
public static readonly OfficialComponent HttpClient = new OfficialComponent(2, "HttpClient");
public static readonly OfficialComponent AspNetCore = new OfficialComponent(30, "AspNetCore");
public static readonly OfficialComponent EntityFrameworkCore = new OfficialComponent(31, "EntityFrameworkCore");
private static readonly ComponentsDefine _instance = new ComponentsDefine();
......@@ -39,6 +44,8 @@ namespace SkyWalking.NetworkProtocol.Trace
private ComponentsDefine()
{
_components = new Dictionary<int, string>();
AddComponent(AspNetCore);
AddComponent(EntityFrameworkCore);
}
private void AddComponent(OfficialComponent component)
......
......@@ -5,7 +5,7 @@
<PropertyGroup>
<Description>SkyWalking trace protocol.</Description>
<AssemblyTitle>SkyWalking.NetworkProtocol.Trace</AssemblyTitle>
<TargetFrameworks>netstandard1.6;net45</TargetFrameworks>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>SkyWalking.NetworkProtocol.Trace</AssemblyName>
<PackageId>SkyWalking.NetworkProtocol.Trace</PackageId>
<PackageTags>SkyWalking</PackageTags>
......
......@@ -5,7 +5,7 @@
<PropertyGroup>
<Description>SkyWalking gRPC protocol and generated codes.</Description>
<AssemblyTitle>SkyWalking.NetworkProtocol</AssemblyTitle>
<TargetFrameworks>netstandard1.6;net45</TargetFrameworks>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>SkyWalking.NetworkProtocol</AssemblyName>
<PackageId>SkyWalking.NetworkProtocol</PackageId>
<PackageTags>SkyWalking</PackageTags>
......
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
</Project>
<ItemGroup>
<ProjectReference Include="..\..\src\SkyWalking.Abstractions\SkyWalking.Abstractions.csproj" />
<ProjectReference Include="..\..\src\SkyWalking.Core\SkyWalking.Core.csproj" />
</ItemGroup>
</Project>
\ No newline at end of file
using Xunit;
namespace SkyWalking.Core.Tests
{
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
}
using System;
using SkyWalking.Utils;
using Xunit;
namespace SkyWalking.Core.Tests.Utils
{
public class AtomicIntegerTests
{
[Fact]
public void Add_Test()
{
var atomicInteger = new AtomicInteger();
var result = atomicInteger.Add(2);
Assert.Equal(2, result);
}
[Fact]
public void Increment_Test()
{
var atomicInteger = new AtomicInteger(5);
var result = atomicInteger.Increment();
Assert.Equal(6, result);
}
[Fact]
public void Decrement_Test()
{
var atomicInteger = new AtomicInteger(5);
var result = atomicInteger.Decrement();
Assert.Equal(4, result);
}
[Fact]
public void Operator_Add_Test()
{
var atomicInteger = new AtomicInteger(5);
var result = atomicInteger + 2;
Assert.Equal<int>(7, result);
}
[Fact]
public void Operator_Sub_Test()
{
var atomicInteger = new AtomicInteger(5);
var result = atomicInteger - 2;
Assert.Equal<int>(3, result);
}
[Fact]
public void Equals_Test()
{
AtomicInteger atomicInteger = 5;
Assert.True(atomicInteger.Equals(5));
}
[Fact]
public void Operator_Equals_Test()
{
AtomicInteger atomicInteger = 5;
Assert.True(atomicInteger == 5);
Assert.False(atomicInteger != 5);
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment