提交 d8f684c4 编写于 作者: S ShaoHans 提交者: Lemon

add grpc skywalking (#236)

* 追踪grpc服务调用

* update
上级 5d685bcc
......@@ -19,7 +19,7 @@
"QueueSize": 30000,
"BatchSize": 3000,
"gRPC": {
"Servers": "localhost:11800",
"Servers": "172.17.168.234:11800",
"Timeout": 10000,
"ConnectTimeout": 10000,
"ReportTimeout": 600000
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SkyApm.Sample.Backend.Services;
namespace SkyApm.Sample.Backend.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class GrpcController : ControllerBase
{
private readonly GreeterGrpcService _greeter;
public GrpcController(GreeterGrpcService greeter)
{
_greeter = greeter;
}
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new List<string> { "value1", "value2" };
}
[HttpGet("greeter")]
public async Task<IActionResult> SayHelloAsync(string name)
{
var reply = await _greeter.SayHelloAsync(name);
return Ok($"from backend grpc message{reply}");
}
}
}
\ No newline at end of file
......@@ -18,7 +18,6 @@
},
"SkyWalking.Sample.Backend": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "SkyAPM.Agent.AspNetCore"
......
using Grpc.Core;
using Grpc.Core.Interceptors;
using GrpcGreeter;
using SkyApm.Diagnostics.Grpc.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SkyApm.Sample.Backend.Services
{
public class GreeterGrpcService
{
private readonly Greeter.GreeterClient _client;
public GreeterGrpcService(ClientDiagnosticInterceptor interceptor)
{
_client = new Greeter.GreeterClient(GetChannel(interceptor));
}
private CallInvoker GetChannel(ClientDiagnosticInterceptor interceptor)
{
var channel = new Channel("localhost:12345", ChannelCredentials.Insecure);
var invoker = channel.Intercept(interceptor);
return invoker;
}
public string SayHello(string name)
{
var reply = _client.SayHello(new HelloRequest { Name = name });
return reply.Message;
}
public async Task<string> SayHelloAsync(string name)
{
var reply = await _client.SayHelloAsync(new HelloRequest { Name = name });
return reply.Message;
}
public string SayHelloWithException(string name)
{
var reply = _client.SayHelloWithException(new HelloRequest { Name = name });
return reply.Message;
}
public async Task<string> SayHelloWithExceptionAsync(string name)
{
var reply = await _client.SayHelloWithExceptionAsync(new HelloRequest { Name = name });
return reply.Message;
}
}
}
......@@ -8,13 +8,14 @@
<ItemGroup>
<ProjectReference Include="..\..\src\SkyApm.Agent.AspNetCore\SkyApm.Agent.AspNetCore.csproj" />
<ProjectReference Include="..\..\src\SkyApm.Diagnostics.EntityFrameworkCore.Sqlite\SkyApm.Diagnostics.EntityFrameworkCore.Sqlite.csproj" />
<ProjectReference Include="..\grpc\SkyApm.Sample.GrpcProto\SkyApm.Sample.GrpcProto.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite">
<Version>2.1.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.9" />
</ItemGroup>
<ItemGroup>
<Content Update="appsettings.json">
......
......@@ -8,6 +8,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SkyApm.Sample.Backend.Models;
using SkyApm.Sample.Backend.Sampling;
using SkyApm.Sample.Backend.Services;
using SkyApm.Tracing;
namespace SkyApm.Sample.Backend
......@@ -31,6 +32,9 @@ namespace SkyApm.Sample.Backend
services.AddEntityFrameworkSqlite().AddDbContext<SampleDbContext>(c => c.UseSqlite(sqliteConnection));
services.AddSingleton<ISamplingInterceptor, CustomSamplingInterceptor>();
// DI grpc service
services.AddSingleton<GreeterGrpcService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
......
......@@ -19,7 +19,7 @@
"QueueSize": 30000,
"BatchSize": 3000,
"gRPC": {
"Servers": "localhost:11800",
"Servers": "172.17.168.234:11800",
"Timeout": 100000,
"ConnectTimeout": 100000,
"ReportTimeout": 600000
......
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using SkyApm.Sample.Backend.Services;
namespace SkyApm.Sample.Frontend.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly GreeterGrpcService _greeter;
public ValuesController(GreeterGrpcService greeter)
{
_greeter = greeter;
}
// GET api/values
[HttpGet]
public async Task<IEnumerable<string>> Get()
......@@ -25,5 +34,28 @@ namespace SkyApm.Sample.Frontend.Controllers
client.GetAsync("http://localhost:5002/api/delay/200"));
return await client.GetStringAsync("http://localhost:5002/api/delay/100");
}
[HttpGet("greeter")]
public async Task<IActionResult> SayHelloAsync(string name)
{
var content = new StringBuilder();
var message = await _greeter.SayHelloAsync(name);
content.AppendLine($"from frontend grpc message:{message}");
var response = await new HttpClient().GetStringAsync("http://localhost:5002/api/values");
content.AppendLine($"from frontend httpclient message:{response}");
response = await new HttpClient().GetStringAsync($"http://localhost:5002/api/grpc/greeter?name={name}");
content.AppendLine(response);
return Ok(content);
}
[HttpGet("greeter/exception")]
public async Task<IActionResult> SayHelloWithExceptionAsync(string name)
{
var message = await _greeter.SayHelloWithExceptionAsync(name);
return Ok(message);
}
}
}
\ No newline at end of file
......@@ -18,7 +18,6 @@
},
"SkyWalking.Sample.Frontend": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "SkyAPM.Agent.AspNetCore"
......
using Grpc.Core;
using Grpc.Core.Interceptors;
using GrpcGreeter;
using SkyApm.Diagnostics.Grpc.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SkyApm.Sample.Backend.Services
{
public class GreeterGrpcService
{
private readonly Greeter.GreeterClient _client;
public GreeterGrpcService(ClientDiagnosticInterceptor interceptor)
{
_client = new Greeter.GreeterClient(GetChannel(interceptor));
}
private CallInvoker GetChannel(ClientDiagnosticInterceptor interceptor)
{
var channel = new Channel("localhost:12345", ChannelCredentials.Insecure);
var invoker = channel.Intercept(interceptor);
return invoker;
}
public string SayHello(string name)
{
var reply = _client.SayHello(new HelloRequest { Name = name });
return reply.Message;
}
public async Task<string> SayHelloAsync(string name)
{
var reply = await _client.SayHelloAsync(new HelloRequest { Name = name });
return reply.Message;
}
public string SayHelloWithException(string name)
{
var reply = _client.SayHelloWithException(new HelloRequest { Name = name });
return reply.Message;
}
public async Task<string> SayHelloWithExceptionAsync(string name)
{
var reply = await _client.SayHelloWithExceptionAsync(new HelloRequest { Name = name });
return reply.Message;
}
}
}
......@@ -22,6 +22,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\SkyApm.Agent.AspNetCore\SkyApm.Agent.AspNetCore.csproj" />
<ProjectReference Include="..\grpc\SkyApm.Sample.GrpcProto\SkyApm.Sample.GrpcProto.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="logs" />
......
......@@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SkyApm.Sample.Backend.Services;
namespace SkyApm.Sample.Frontend
{
......@@ -18,6 +19,9 @@ namespace SkyApm.Sample.Frontend
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// DI grpc service
services.AddSingleton<GreeterGrpcService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
......
......@@ -19,9 +19,9 @@
"QueueSize": 30000,
"BatchSize": 3000,
"gRPC": {
"Servers": "localhost:11800",
"Timeout": 10000,
"ConnectTimeout": 10000,
"Servers": "172.17.168.234:11800",
"Timeout": 100000,
"ConnectTimeout": 100000,
"ReportTimeout": 600000
}
}
......
......@@ -19,7 +19,7 @@
"QueueSize": 30000,
"BatchSize": 3000,
"gRPC": {
"Servers": "localhost:11800",
"Servers": "172.17.168.234:11800",
"Timeout": 100000,
"ConnectTimeout": 100000,
"ReportTimeout": 600000
......
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: hello.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace GrpcGreeter {
/// <summary>Holder for reflection information generated from hello.proto</summary>
public static partial class HelloReflection {
#region Descriptor
/// <summary>File descriptor for hello.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static HelloReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CgtoZWxsby5wcm90bxIFR3JlZXQiHAoMSGVsbG9SZXF1ZXN0EgwKBG5hbWUY",
"ASABKAkiHQoKSGVsbG9SZXBseRIPCgdtZXNzYWdlGAEgASgJMn4KB0dyZWV0",
"ZXISMgoIU2F5SGVsbG8SEy5HcmVldC5IZWxsb1JlcXVlc3QaES5HcmVldC5I",
"ZWxsb1JlcGx5Ej8KFVNheUhlbGxvV2l0aEV4Y2VwdGlvbhITLkdyZWV0Lkhl",
"bGxvUmVxdWVzdBoRLkdyZWV0LkhlbGxvUmVwbHlCDqoCC0dycGNHcmVldGVy",
"YgZwcm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::GrpcGreeter.HelloRequest), global::GrpcGreeter.HelloRequest.Parser, new[]{ "Name" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::GrpcGreeter.HelloReply), global::GrpcGreeter.HelloReply.Parser, new[]{ "Message" }, null, null, null)
}));
}
#endregion
}
#region Messages
/// <summary>
/// The request message containing the user's name.
/// </summary>
public sealed partial class HelloRequest : pb::IMessage<HelloRequest> {
private static readonly pb::MessageParser<HelloRequest> _parser = new pb::MessageParser<HelloRequest>(() => new HelloRequest());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<HelloRequest> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::GrpcGreeter.HelloReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloRequest() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloRequest(HelloRequest other) : this() {
name_ = other.name_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloRequest Clone() {
return new HelloRequest(this);
}
/// <summary>Field number for the "name" field.</summary>
public const int NameFieldNumber = 1;
private string name_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Name {
get { return name_; }
set {
name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as HelloRequest);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(HelloRequest other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Name != other.Name) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (Name.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(HelloRequest other) {
if (other == null) {
return;
}
if (other.Name.Length != 0) {
Name = other.Name;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Name = input.ReadString();
break;
}
}
}
}
}
/// <summary>
/// The response message containing the greetings.
/// </summary>
public sealed partial class HelloReply : pb::IMessage<HelloReply> {
private static readonly pb::MessageParser<HelloReply> _parser = new pb::MessageParser<HelloReply>(() => new HelloReply());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<HelloReply> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::GrpcGreeter.HelloReflection.Descriptor.MessageTypes[1]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloReply() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloReply(HelloReply other) : this() {
message_ = other.message_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloReply Clone() {
return new HelloReply(this);
}
/// <summary>Field number for the "message" field.</summary>
public const int MessageFieldNumber = 1;
private string message_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Message {
get { return message_; }
set {
message_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as HelloReply);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(HelloReply other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Message != other.Message) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Message.Length != 0) hash ^= Message.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (Message.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Message);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
if (Message.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(HelloReply other) {
if (other == null) {
return;
}
if (other.Message.Length != 0) {
Message = other.Message;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Message = input.ReadString();
break;
}
}
}
}
}
#endregion
}
#endregion Designer generated code
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: hello.proto
// </auto-generated>
#pragma warning disable 0414, 1591
#region Designer generated code
using grpc = global::Grpc.Core;
namespace GrpcGreeter {
/// <summary>
/// The greeting service definition.
/// </summary>
public static partial class Greeter
{
static readonly string __ServiceName = "Greet.Greeter";
static readonly grpc::Marshaller<global::GrpcGreeter.HelloRequest> __Marshaller_Greet_HelloRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::GrpcGreeter.HelloRequest.Parser.ParseFrom);
static readonly grpc::Marshaller<global::GrpcGreeter.HelloReply> __Marshaller_Greet_HelloReply = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::GrpcGreeter.HelloReply.Parser.ParseFrom);
static readonly grpc::Method<global::GrpcGreeter.HelloRequest, global::GrpcGreeter.HelloReply> __Method_SayHello = new grpc::Method<global::GrpcGreeter.HelloRequest, global::GrpcGreeter.HelloReply>(
grpc::MethodType.Unary,
__ServiceName,
"SayHello",
__Marshaller_Greet_HelloRequest,
__Marshaller_Greet_HelloReply);
static readonly grpc::Method<global::GrpcGreeter.HelloRequest, global::GrpcGreeter.HelloReply> __Method_SayHelloWithException = new grpc::Method<global::GrpcGreeter.HelloRequest, global::GrpcGreeter.HelloReply>(
grpc::MethodType.Unary,
__ServiceName,
"SayHelloWithException",
__Marshaller_Greet_HelloRequest,
__Marshaller_Greet_HelloReply);
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::GrpcGreeter.HelloReflection.Descriptor.Services[0]; }
}
/// <summary>Base class for server-side implementations of Greeter</summary>
[grpc::BindServiceMethod(typeof(Greeter), "BindService")]
public abstract partial class GreeterBase
{
/// <summary>
/// Sends a greeting
/// </summary>
/// <param name="request">The request received from the client.</param>
/// <param name="context">The context of the server-side call handler being invoked.</param>
/// <returns>The response to send back to the client (wrapped by a task).</returns>
public virtual global::System.Threading.Tasks.Task<global::GrpcGreeter.HelloReply> SayHello(global::GrpcGreeter.HelloRequest request, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
}
public virtual global::System.Threading.Tasks.Task<global::GrpcGreeter.HelloReply> SayHelloWithException(global::GrpcGreeter.HelloRequest request, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
}
}
/// <summary>Client for Greeter</summary>
public partial class GreeterClient : grpc::ClientBase<GreeterClient>
{
/// <summary>Creates a new client for Greeter</summary>
/// <param name="channel">The channel to use to make remote calls.</param>
public GreeterClient(grpc::ChannelBase channel) : base(channel)
{
}
/// <summary>Creates a new client for Greeter that uses a custom <c>CallInvoker</c>.</summary>
/// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
public GreeterClient(grpc::CallInvoker callInvoker) : base(callInvoker)
{
}
/// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected GreeterClient() : base()
{
}
/// <summary>Protected constructor to allow creation of configured clients.</summary>
/// <param name="configuration">The client configuration.</param>
protected GreeterClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
/// <summary>
/// Sends a greeting
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The response received from the server.</returns>
public virtual global::GrpcGreeter.HelloReply SayHello(global::GrpcGreeter.HelloRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return SayHello(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// Sends a greeting
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="options">The options for the call.</param>
/// <returns>The response received from the server.</returns>
public virtual global::GrpcGreeter.HelloReply SayHello(global::GrpcGreeter.HelloRequest request, grpc::CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_SayHello, null, options, request);
}
/// <summary>
/// Sends a greeting
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncUnaryCall<global::GrpcGreeter.HelloReply> SayHelloAsync(global::GrpcGreeter.HelloRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return SayHelloAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// Sends a greeting
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="options">The options for the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncUnaryCall<global::GrpcGreeter.HelloReply> SayHelloAsync(global::GrpcGreeter.HelloRequest request, grpc::CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_SayHello, null, options, request);
}
public virtual global::GrpcGreeter.HelloReply SayHelloWithException(global::GrpcGreeter.HelloRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return SayHelloWithException(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
public virtual global::GrpcGreeter.HelloReply SayHelloWithException(global::GrpcGreeter.HelloRequest request, grpc::CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_SayHelloWithException, null, options, request);
}
public virtual grpc::AsyncUnaryCall<global::GrpcGreeter.HelloReply> SayHelloWithExceptionAsync(global::GrpcGreeter.HelloRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return SayHelloWithExceptionAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
public virtual grpc::AsyncUnaryCall<global::GrpcGreeter.HelloReply> SayHelloWithExceptionAsync(global::GrpcGreeter.HelloRequest request, grpc::CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_SayHelloWithException, null, options, request);
}
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
protected override GreeterClient NewInstance(ClientBaseConfiguration configuration)
{
return new GreeterClient(configuration);
}
}
/// <summary>Creates service definition that can be registered with a server</summary>
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
public static grpc::ServerServiceDefinition BindService(GreeterBase serviceImpl)
{
return grpc::ServerServiceDefinition.CreateBuilder()
.AddMethod(__Method_SayHello, serviceImpl.SayHello)
.AddMethod(__Method_SayHelloWithException, serviceImpl.SayHelloWithException).Build();
}
/// <summary>Register service method with a service binder with or without implementation. Useful when customizing the service binding logic.
/// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
/// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
public static void BindService(grpc::ServiceBinderBase serviceBinder, GreeterBase serviceImpl)
{
serviceBinder.AddMethod(__Method_SayHello, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::GrpcGreeter.HelloRequest, global::GrpcGreeter.HelloReply>(serviceImpl.SayHello));
serviceBinder.AddMethod(__Method_SayHelloWithException, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::GrpcGreeter.HelloRequest, global::GrpcGreeter.HelloReply>(serviceImpl.SayHelloWithException));
}
}
}
#endregion
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<None Remove="grpc_csharp_plugin.exe" />
<None Remove="protoc.exe" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.9.1" />
<PackageReference Include="Grpc" Version="2.23.0" />
<PackageReference Include="Grpc.Tools" Version="2.23.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
protoc.exe --proto_path protos --csharp_out=. --grpc_out=. --plugin=protoc-gen-grpc=grpc_csharp_plugin.exe hello.proto
\ No newline at end of file
using Grpc.Core;
using GrpcGreeter;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace SkyApm.Sample.GrpcServer
{
public class GreeterImpl : Greeter.GreeterBase
{
// Server side handler of the SayHello RPC
public override async Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
await Task.Delay(150);
var httpClient = new HttpClient();
var result = await httpClient.GetAsync("http://www.baidu.com");
Console.WriteLine(result.Content.Headers);
return new HelloReply { Message = "Hello " + request.Name };
}
public override Task<HelloReply> SayHelloWithException(HelloRequest request, ServerCallContext context)
{
throw new Exception("grpc server throw exception !!!");
}
}
}
using Grpc.Core;
using GrpcGreeter;
using Microsoft.Extensions.Hosting;
using SkyApm.Agent.GeneralHost;
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace SkyApm.Sample.GrpcServer
{
class Program
{
public static async Task Main(string[] args)
{
await CreateHostBuilder(args).Build().RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
return new HostBuilder()
.UseEnvironment(environmentName)
.AddSkyAPM()
.ConfigureServices((hostContext, services) =>
{
var startUp = new Startup(hostContext.Configuration);
var provider = startUp.ConfigureServices(services);
startUp.Use(provider);
});
}
}
}
{
"profiles": {
"SkyApm.Sample.GrpcServer": {
"commandName": "Project",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<ItemGroup>
<None Remove="skyapm.json" />
</ItemGroup>
<ItemGroup>
<Content Include="skyapm.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Grpc" Version="2.23.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\SkyApm.Agent.GeneralHost\SkyApm.Agent.GeneralHost.csproj" />
<ProjectReference Include="..\SkyApm.Sample.GrpcProto\SkyApm.Sample.GrpcProto.csproj" />
</ItemGroup>
</Project>
using Grpc.Core;
using Grpc.Core.Interceptors;
using GrpcGreeter;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SkyApm.Diagnostics.Grpc.Server;
using System;
namespace SkyApm.Sample.GrpcServer
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddLogging();
return services.BuildServiceProvider();
}
public void Use(IServiceProvider provider)
{
var interceptor = provider.GetService<ServerDiagnosticInterceptor>();
var definition = Greeter.BindService(new GreeterImpl());
if (interceptor != null)
{
definition = definition.Intercept(interceptor);
}
int port = 12345;
Server server = new Server
{
Services = { definition },
Ports = { new ServerPort("localhost", port, ServerCredentials.Insecure) },
};
server.Start();
Console.WriteLine("Greeter server listening on port " + port);
//Console.WriteLine("Press any key to stop the server...");
//Console.ReadKey();
//server.ShutdownAsync().Wait();
}
}
}
{
"SkyWalking": {
"ServiceName": "grpc-greeter-server",
"Namespace": "",
"HeaderVersions": [
"sw6"
],
"Sampling": {
"SamplePer3Secs": -1,
"Percentage": -1.0
},
"Logging": {
"Level": "Information",
"FilePath": "logs/skyapm-{Date}.log"
},
"Transport": {
"Interval": 3000,
"ProtocolVersion": "v6",
"QueueSize": 30000,
"BatchSize": 3000,
"gRPC": {
"Servers": "172.17.168.234:11800",
"Timeout": 100000,
"ConnectTimeout": 100000,
"ReportTimeout": 600000
}
}
}
}
\ No newline at end of file
......@@ -92,7 +92,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Benchmark", "benchma
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmark", "benchmark", "{2B7F59E8-147F-4399-9804-E7EAEF2DCB22}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkyApm.Core.Tests", "test\SkyApm.Core.Tests\SkyApm.Core.Tests.csproj", "{5E654407-E22F-4696-A33F-C4B372F547BD}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Core.Tests", "test\SkyApm.Core.Tests\SkyApm.Core.Tests.csproj", "{5E654407-E22F-4696-A33F-C4B372F547BD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkyApm.Diagnostics.Grpc", "src\SkyApm.Diagnostics.Grpc\SkyApm.Diagnostics.Grpc.csproj", "{8C389735-61CE-405C-972F-3790DF1E823E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "grpc", "grpc", "{53E9CEBA-2D11-41FD-AA60-0151A5442CC4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Sample.GrpcProto", "sample\grpc\SkyApm.Sample.GrpcProto\SkyApm.Sample.GrpcProto.csproj", "{5576D9C5-8856-44AD-86AD-FE73A22751EF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkyApm.Sample.GrpcServer", "sample\grpc\SkyApm.Sample.GrpcServer\SkyApm.Sample.GrpcServer.csproj", "{0EB6D474-A915-4075-B142-FE07321F3AA9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
......@@ -204,6 +212,18 @@ Global
{5E654407-E22F-4696-A33F-C4B372F547BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E654407-E22F-4696-A33F-C4B372F547BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E654407-E22F-4696-A33F-C4B372F547BD}.Release|Any CPU.Build.0 = Release|Any CPU
{8C389735-61CE-405C-972F-3790DF1E823E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8C389735-61CE-405C-972F-3790DF1E823E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C389735-61CE-405C-972F-3790DF1E823E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C389735-61CE-405C-972F-3790DF1E823E}.Release|Any CPU.Build.0 = Release|Any CPU
{5576D9C5-8856-44AD-86AD-FE73A22751EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5576D9C5-8856-44AD-86AD-FE73A22751EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5576D9C5-8856-44AD-86AD-FE73A22751EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5576D9C5-8856-44AD-86AD-FE73A22751EF}.Release|Any CPU.Build.0 = Release|Any CPU
{0EB6D474-A915-4075-B142-FE07321F3AA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0EB6D474-A915-4075-B142-FE07321F3AA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0EB6D474-A915-4075-B142-FE07321F3AA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0EB6D474-A915-4075-B142-FE07321F3AA9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......@@ -243,6 +263,10 @@ Global
{477D705E-576B-46C8-8F1E-9A86EDAE9D86} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB}
{33581FDE-ABAF-4C27-A40A-1A2743309399} = {2B7F59E8-147F-4399-9804-E7EAEF2DCB22}
{5E654407-E22F-4696-A33F-C4B372F547BD} = {613F0980-91ED-4064-8E8C-168582EF4AD7}
{8C389735-61CE-405C-972F-3790DF1E823E} = {B5E677CF-2920-4B0A-A056-E73F6B2CF2BC}
{53E9CEBA-2D11-41FD-AA60-0151A5442CC4} = {844CEACD-4C85-4B15-9E2B-892B01FDA4BB}
{5576D9C5-8856-44AD-86AD-FE73A22751EF} = {53E9CEBA-2D11-41FD-AA60-0151A5442CC4}
{0EB6D474-A915-4075-B142-FE07321F3AA9} = {53E9CEBA-2D11-41FD-AA60-0151A5442CC4}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {94C0DA2C-CCCB-4314-93A2-9809B5DD0583}
......
......@@ -39,5 +39,7 @@ namespace SkyApm.Common
public static readonly StringOrIntValue ASPNET = new StringOrIntValue("AspNet");
public static readonly StringOrIntValue SMART_SQL = new StringOrIntValue("SmartSql");
public static readonly StringOrIntValue GRPC = new StringOrIntValue("GRPC");
}
}
\ No newline at end of file
......@@ -38,5 +38,9 @@ namespace SkyApm.Common
public static readonly string DB_BIND_VARIABLES = "db.bind_vars";
public static readonly string MQ_TOPIC = "mq.topic";
public static readonly string GRPC_METHOD_NAME = "grpc.method";
public static readonly string GRPC_STATUS = "grpc.status";
}
}
\ No newline at end of file
......@@ -37,6 +37,7 @@ using SkyApm.Diagnostics.HttpClient;
using SkyApm.Diagnostics.SqlClient;
using SkyApm.Utilities.DependencyInjection;
using SkyApm.Diagnostics.SmartSql;
using SkyApm.Diagnostics.Grpc;
namespace SkyApm.Agent.AspNetCore
{
......@@ -63,7 +64,7 @@ namespace SkyApm.Agent.AspNetCore
services.AddSingleton<IEnvironmentProvider, HostingEnvironmentProvider>();
services.AddSingleton<IExecutionService, CLRStatsService>();
services.AddTracing().AddSampling().AddGrpcTransport().AddLogging();
services.AddSkyApmExtensions().AddAspNetCoreHosting().AddHttpClient().AddSqlClient()
services.AddSkyApmExtensions().AddAspNetCoreHosting().AddHttpClient().AddSqlClient().AddGrpc()
.AddEntityFrameworkCore(c => c.AddPomeloMysql().AddNpgsql().AddSqlite());
return services;
}
......
......@@ -22,6 +22,7 @@
<ProjectReference Include="..\SkyApm.Diagnostics.EntityFrameworkCore.Sqlite\SkyApm.Diagnostics.EntityFrameworkCore.Sqlite.csproj" />
<ProjectReference Include="..\SkyApm.Diagnostics.EntityFrameworkCore\SkyApm.Diagnostics.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\SkyApm.Core\SkyApm.Core.csproj" />
<ProjectReference Include="..\SkyApm.Diagnostics.Grpc\SkyApm.Diagnostics.Grpc.csproj" />
<ProjectReference Include="..\SkyApm.Diagnostics.HttpClient\SkyApm.Diagnostics.HttpClient.csproj" />
<ProjectReference Include="..\SkyApm.Diagnostics.SmartSql\SkyApm.Diagnostics.SmartSql.csproj" />
<ProjectReference Include="..\SkyApm.Diagnostics.SqlClient\SkyApm.Diagnostics.SqlClient.csproj" />
......
......@@ -21,6 +21,7 @@ using Microsoft.Extensions.Hosting;
using SkyApm.Config;
using SkyApm.Diagnostics;
using SkyApm.Diagnostics.EntityFrameworkCore;
using SkyApm.Diagnostics.Grpc;
using SkyApm.Diagnostics.HttpClient;
using SkyApm.Diagnostics.SqlClient;
using SkyApm.Logging;
......@@ -60,7 +61,7 @@ namespace SkyApm.Agent.GeneralHost
services.AddSingleton<IHostedService, InstrumentationHostedService>();
services.AddSingleton<IEnvironmentProvider, HostingEnvironmentProvider>();
services.AddTracing().AddSampling().AddGrpcTransport().AddLogging();
services.AddSkyApmExtensions().AddHttpClient().AddSqlClient()
services.AddSkyApmExtensions().AddHttpClient().AddSqlClient().AddGrpc()
.AddEntityFrameworkCore(c => c.AddPomeloMysql().AddNpgsql().AddSqlite());
return services;
}
......
......@@ -21,6 +21,7 @@
<ProjectReference Include="..\SkyApm.Diagnostics.EntityFrameworkCore.Sqlite\SkyApm.Diagnostics.EntityFrameworkCore.Sqlite.csproj" />
<ProjectReference Include="..\SkyApm.Diagnostics.EntityFrameworkCore\SkyApm.Diagnostics.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\SkyApm.Core\SkyApm.Core.csproj" />
<ProjectReference Include="..\SkyApm.Diagnostics.Grpc\SkyApm.Diagnostics.Grpc.csproj" />
<ProjectReference Include="..\SkyApm.Diagnostics.HttpClient\SkyApm.Diagnostics.HttpClient.csproj" />
<ProjectReference Include="..\SkyApm.Diagnostics.SqlClient\SkyApm.Diagnostics.SqlClient.csproj" />
<ProjectReference Include="..\SkyApm.Transport.Grpc\SkyApm.Transport.Grpc.csproj" />
......
using Grpc.Core;
using Grpc.Core.Interceptors;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace SkyApm.Diagnostics.Grpc.Client
{
public class ClientDiagnosticInterceptor : Interceptor
{
private readonly ClientDiagnosticProcessor _processor;
public ClientDiagnosticInterceptor(ClientDiagnosticProcessor processor)
{
_processor = processor;
}
public override TResponse BlockingUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, BlockingUnaryCallContinuation<TRequest, TResponse> continuation)
{
var metadata = _processor.BeginRequest(context);
try
{
var options = context.Options.WithHeaders(metadata);
context = new ClientInterceptorContext<TRequest, TResponse>(context.Method, context.Host, options);
var response = continuation(request, context);
_processor.EndRequest();
return response;
}
catch (Exception ex)
{
_processor.DiagnosticUnhandledException(ex);
throw ex;
}
}
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
{
var metadata = _processor.BeginRequest(context);
try
{
var options = context.Options.WithHeaders(metadata);
context = new ClientInterceptorContext<TRequest, TResponse>(context.Method, context.Host, options);
var response = continuation(request, context);
var responseAsync = response.ResponseAsync.ContinueWith<TResponse>(r =>
{
_processor.EndRequest();
return r.Result;
});
return new AsyncUnaryCall<TResponse>(responseAsync, response.ResponseHeadersAsync, response.GetStatus, response.GetTrailers, response.Dispose);
}
catch (Exception ex)
{
_processor.DiagnosticUnhandledException(ex);
throw ex;
}
}
}
}
using Grpc.Core;
using Grpc.Core.Interceptors;
using SkyApm.Common;
using SkyApm.Tracing;
using SkyApm.Tracing.Segments;
using System;
namespace SkyApm.Diagnostics.Grpc.Client
{
public class ClientDiagnosticProcessor
{
private readonly ITracingContext _tracingContext;
private readonly IExitSegmentContextAccessor _segmentContextAccessor;
public ClientDiagnosticProcessor(IExitSegmentContextAccessor segmentContextAccessor,
ITracingContext tracingContext)
{
_tracingContext = tracingContext;
_segmentContextAccessor = segmentContextAccessor;
}
public Metadata BeginRequest<TRequest, TResponse>(ClientInterceptorContext<TRequest, TResponse> grpcContext)
where TRequest : class
where TResponse : class
{
var host = grpcContext.Host;
var carrierHeader = new GrpcCarrierHeaderCollection(grpcContext.Options.Headers);
var context = _tracingContext.CreateExitSegmentContext(grpcContext.Method.FullName, host, carrierHeader);
context.Span.SpanLayer = SpanLayer.RPC_FRAMEWORK;
context.Span.Component = Components.GRPC;
context.Span.Peer = new StringOrIntValue(host);
context.Span.AddTag(Tags.GRPC_METHOD_NAME, grpcContext.Method.FullName);
context.Span.AddLog(
LogEvent.Event("Grpc Client BeginRequest"),
LogEvent.Message($"Request starting {grpcContext.Method.Type} {grpcContext.Method.FullName}"));
var metadata = new Metadata();
foreach (var item in carrierHeader)
{
metadata.Add(item.Key, item.Value);
}
return metadata;
}
public void EndRequest()
{
var context = _segmentContextAccessor.Context;
if (context == null)
{
return;
}
context.Span.AddLog(
LogEvent.Event("Grpc Client EndRequest"),
LogEvent.Message($"Request finished "));
_tracingContext.Release(context);
}
public void DiagnosticUnhandledException(Exception exception)
{
var context = _segmentContextAccessor.Context;
if (context != null)
{
context.Span?.ErrorOccurred(exception);
_tracingContext.Release(context);
}
}
}
}
using Grpc.Core;
using SkyApm.Tracing;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SkyApm.Diagnostics.Grpc
{
public class GrpcCarrierHeaderCollection : ICarrierHeaderCollection
{
private readonly Metadata _metadata;
public GrpcCarrierHeaderCollection(Metadata metadata)
{
_metadata = metadata ?? new Metadata();
}
public void Add(string key, string value)
{
_metadata.Add(new Metadata.Entry(key, value));
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return _metadata.Select(m => new KeyValuePair<string, string>(m.Key, m.Value)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _metadata.GetEnumerator();
}
}
}
using Grpc.Core;
using Grpc.Core.Interceptors;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace SkyApm.Diagnostics.Grpc.Server
{
public class ServerDiagnosticInterceptor : Interceptor
{
private readonly ServerDiagnosticProcessor _processor;
public ServerDiagnosticInterceptor(ServerDiagnosticProcessor processor)
{
_processor = processor;
}
public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
{
_processor.BeginRequest(context);
try
{
var response = await continuation(request, context);
_processor.EndRequest(context);
return response;
}
catch (Exception ex)
{
_processor.DiagnosticUnhandledException(ex);
throw ex;
}
}
}
}
using Grpc.Core;
using SkyApm.Common;
using SkyApm.Tracing;
using SkyApm.Tracing.Segments;
using System;
namespace SkyApm.Diagnostics.Grpc.Server
{
public class ServerDiagnosticProcessor
{
private readonly ITracingContext _tracingContext;
private readonly IEntrySegmentContextAccessor _segmentContextAccessor;
public ServerDiagnosticProcessor(IEntrySegmentContextAccessor segmentContextAccessor,
ITracingContext tracingContext)
{
_tracingContext = tracingContext;
_segmentContextAccessor = segmentContextAccessor;
}
public void BeginRequest(ServerCallContext grpcContext)
{
var context = _tracingContext.CreateEntrySegmentContext(grpcContext.Method,
new GrpcCarrierHeaderCollection(grpcContext.RequestHeaders));
context.Span.SpanLayer = SpanLayer.RPC_FRAMEWORK;
context.Span.Component = Components.GRPC;
context.Span.Peer = new StringOrIntValue(grpcContext.Peer);
context.Span.AddTag(Tags.GRPC_METHOD_NAME, grpcContext.Method);
context.Span.AddLog(
LogEvent.Event("Grpc Server BeginRequest"),
LogEvent.Message($"Request starting {grpcContext.Method}"));
}
public void EndRequest(ServerCallContext grpcContext)
{
var context = _segmentContextAccessor.Context;
if (context == null)
{
return;
}
var statusCode = grpcContext.Status.StatusCode;
if (statusCode != StatusCode.OK)
{
context.Span.ErrorOccurred();
}
context.Span.AddTag(Tags.GRPC_STATUS, statusCode.ToString());
context.Span.AddLog(
LogEvent.Event("Grpc Server EndRequest"),
LogEvent.Message($"Request finished {statusCode} "));
_tracingContext.Release(context);
}
public void DiagnosticUnhandledException(Exception exception)
{
var context = _segmentContextAccessor.Context;
if (context != null)
{
context.Span?.ErrorOccurred(exception);
_tracingContext.Release(context);
}
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Grpc" Version="2.23.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SkyApm.Abstractions\SkyApm.Abstractions.csproj" />
<ProjectReference Include="..\SkyApm.Utilities.DependencyInjection\SkyApm.Utilities.DependencyInjection.csproj" />
</ItemGroup>
</Project>
using Microsoft.Extensions.DependencyInjection;
using SkyApm.Diagnostics.Grpc.Client;
using SkyApm.Diagnostics.Grpc.Server;
using SkyApm.Utilities.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;
namespace SkyApm.Diagnostics.Grpc
{
public static class SkyWalkingBuilderExtensions
{
public static SkyApmExtensions AddGrpc(this SkyApmExtensions extensions)
{
extensions.Services.AddSingleton<ClientDiagnosticProcessor>();
extensions.Services.AddSingleton<ClientDiagnosticInterceptor>();
extensions.Services.AddSingleton<ServerDiagnosticProcessor>();
extensions.Services.AddSingleton<ServerDiagnosticInterceptor>();
return extensions;
}
}
}
......@@ -16,7 +16,7 @@
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.6.1" />
<PackageReference Include="Grpc" Version="1.17.0" />
<PackageReference Include="Grpc" Version="2.23.0" />
<PackageReference Include="Grpc.Tools" Version="1.17.0" PrivateAssets="All" />
</ItemGroup>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册