gRPC client and server examples (#1224)
* Add dotnet new template ASP.NET Core gRPC service * Add Examples.GrpcService project to solution * Submit to StyleCop's demands * Add Open Telemetry * Remove unused usings * Add Grpc.Net.Client example to example Console project * Remove comments from original template * Fix file header * Add exception handling when gRPC service has not been started * Apply suggestions from code review Co-authored-by: Reiley Yang <reyang@microsoft.com> Co-authored-by: Reiley Yang <reyang@microsoft.com> Co-authored-by: Cijo Thomas <cithomas@microsoft.com>
This commit is contained in:
parent
623ad06d61
commit
d57a931b21
|
|
@ -189,6 +189,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "extending-the-sdk", "docs\t
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "correlation", "docs\logs\correlation\correlation.csproj", "{B26BE278-C9DA-4067-A0EE-6A4227B3DC87}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.GrpcService", "examples\GrpcService\Examples.GrpcService.csproj", "{DB942F5A-D571-4DEA-B1A7-B6BE0E24E6ED}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -363,6 +365,10 @@ Global
|
|||
{B26BE278-C9DA-4067-A0EE-6A4227B3DC87}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B26BE278-C9DA-4067-A0EE-6A4227B3DC87}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B26BE278-C9DA-4067-A0EE-6A4227B3DC87}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DB942F5A-D571-4DEA-B1A7-B6BE0E24E6ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DB942F5A-D571-4DEA-B1A7-B6BE0E24E6ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DB942F5A-D571-4DEA-B1A7-B6BE0E24E6ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DB942F5A-D571-4DEA-B1A7-B6BE0E24E6ED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -390,6 +396,7 @@ Global
|
|||
{CB401DF1-FF5C-4055-886E-1183E832B2D6} = {7CB2F02E-03FA-4FFF-89A5-C51F107623FD}
|
||||
{FCDCF532-A163-40DA-80B7-7530AA1182C4} = {5B7FB835-3FFF-4BC2-99C5-A5B5FAE3C818}
|
||||
{B26BE278-C9DA-4067-A0EE-6A4227B3DC87} = {3862190B-E2C5-418E-AFDC-DB281FB5C705}
|
||||
{DB942F5A-D571-4DEA-B1A7-B6BE0E24E6ED} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,23 @@
|
|||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Protobuf Include="..\GrpcService\Protos\greet.proto" GrpcServices="Client" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.3.0" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.13.0" />
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.27.0" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.25.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.1.58" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.GrpcNetClient\OpenTelemetry.Instrumentation.GrpcNetClient.csproj" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.Http\OpenTelemetry.Instrumentation.Http.csproj" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.StackExchangeRedis\OpenTelemetry.Instrumentation.StackExchangeRedis.csproj" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj" />
|
||||
|
|
|
|||
|
|
@ -40,11 +40,12 @@ namespace Examples.Console
|
|||
/// <param name="args">Arguments from command line.</param>
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Parser.Default.ParseArguments<JaegerOptions, ZipkinOptions, PrometheusOptions, HttpClientOptions, RedisOptions, ZPagesOptions, ConsoleOptions, OpenTelemetryShimOptions, OpenTracingShimOptions, OtlpOptions>(args)
|
||||
Parser.Default.ParseArguments<JaegerOptions, ZipkinOptions, PrometheusOptions, GrpcNetClientOptions, HttpClientOptions, RedisOptions, ZPagesOptions, ConsoleOptions, OpenTelemetryShimOptions, OpenTracingShimOptions, OtlpOptions>(args)
|
||||
.MapResult(
|
||||
(JaegerOptions options) => TestJaegerExporter.Run(options.Host, options.Port),
|
||||
(ZipkinOptions options) => TestZipkinExporter.Run(options.Uri),
|
||||
(PrometheusOptions options) => TestPrometheusExporter.RunAsync(options.Port, options.PushIntervalInSecs, options.DurationInMins),
|
||||
(GrpcNetClientOptions options) => TestGrpcNetClient.Run(),
|
||||
(HttpClientOptions options) => TestHttpClient.Run(),
|
||||
(RedisOptions options) => TestRedis.Run(options.Uri),
|
||||
(ZPagesOptions options) => TestZPagesExporter.Run(),
|
||||
|
|
@ -90,6 +91,11 @@ namespace Examples.Console
|
|||
public int DurationInMins { get; set; }
|
||||
}
|
||||
|
||||
[Verb("grpc", HelpText = "Specify the options required to test Grpc.Net.Client")]
|
||||
internal class GrpcNetClientOptions
|
||||
{
|
||||
}
|
||||
|
||||
[Verb("httpclient", HelpText = "Specify the options required to test HttpClient")]
|
||||
internal class HttpClientOptions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
// <copyright file="TestGrpcNetClient.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Diagnostics;
|
||||
using Examples.GrpcService;
|
||||
using Grpc.Core;
|
||||
using Grpc.Net.Client;
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace Examples.Console
|
||||
{
|
||||
internal class TestGrpcNetClient
|
||||
{
|
||||
internal static object Run()
|
||||
{
|
||||
using var openTelemetry = Sdk.CreateTracerProviderBuilder()
|
||||
.AddGrpcClientInstrumentation()
|
||||
.AddSource("grpc-net-client-test")
|
||||
.AddConsoleExporter()
|
||||
.Build();
|
||||
|
||||
var source = new ActivitySource("grpc-net-client-test");
|
||||
using (var parent = source.StartActivity("Main", ActivityKind.Server))
|
||||
{
|
||||
using var channel = GrpcChannel.ForAddress("https://localhost:5001");
|
||||
var client = new Greeter.GreeterClient(channel);
|
||||
|
||||
try
|
||||
{
|
||||
var reply = client.SayHelloAsync(new HelloRequest { Name = "GreeterClient" }).GetAwaiter().GetResult();
|
||||
System.Console.WriteLine($"Message received: {reply.Message}");
|
||||
}
|
||||
catch (RpcException)
|
||||
{
|
||||
System.Console.Error.WriteLine($"To run this Grpc.Net.Client example, first start the Examples.GrpcService project.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.27.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Zipkin\OpenTelemetry.Exporter.Zipkin.csproj" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.Hosting\OpenTelemetry.Extensions.Hosting.csproj" />
|
||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.AspNetCore\OpenTelemetry.Instrumentation.AspNetCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// <copyright file="Program.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
// </copyright>
|
||||
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Examples.GrpcService
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
// Additional configuration is required to successfully run gRPC on macOS.
|
||||
// For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "Examples.GrpcService";
|
||||
|
||||
package greet;
|
||||
|
||||
// The greeting service definition.
|
||||
service Greeter {
|
||||
// Sends a greeting
|
||||
rpc SayHello (HelloRequest) returns (HelloReply);
|
||||
}
|
||||
|
||||
// The request message containing the user's name.
|
||||
message HelloRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
// The response message containing the greetings.
|
||||
message HelloReply {
|
||||
string message = 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// <copyright file="GreeterService.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
// </copyright>
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Grpc.Core;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Examples.GrpcService
|
||||
{
|
||||
public class GreeterService : Greeter.GreeterBase
|
||||
{
|
||||
private readonly ILogger<GreeterService> logger;
|
||||
|
||||
public GreeterService(ILogger<GreeterService> logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
|
||||
{
|
||||
return Task.FromResult(new HelloReply
|
||||
{
|
||||
Message = "Hello " + request.Name,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
// <copyright file="Startup.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed 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.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace Examples.GrpcService
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
this.Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddGrpc();
|
||||
|
||||
// Switch between Jaeger/Zipkin by setting UseExporter in appsettings.json.
|
||||
var exporter = this.Configuration.GetValue<string>("UseExporter").ToLowerInvariant();
|
||||
switch (exporter)
|
||||
{
|
||||
case "jaeger":
|
||||
services.AddOpenTelemetryTracing((builder) => builder
|
||||
.AddAspNetCoreInstrumentation()
|
||||
.AddJaegerExporter(jaegerOptions =>
|
||||
{
|
||||
jaegerOptions.ServiceName = this.Configuration.GetValue<string>("Jaeger:ServiceName");
|
||||
jaegerOptions.AgentHost = this.Configuration.GetValue<string>("Jaeger:Host");
|
||||
jaegerOptions.AgentPort = this.Configuration.GetValue<int>("Jaeger:Port");
|
||||
}));
|
||||
break;
|
||||
case "zipkin":
|
||||
services.AddOpenTelemetryTracing((builder) => builder
|
||||
.AddAspNetCoreInstrumentation()
|
||||
.AddZipkinExporter(zipkinOptions =>
|
||||
{
|
||||
zipkinOptions.ServiceName = this.Configuration.GetValue<string>("Zipkin:ServiceName");
|
||||
zipkinOptions.Endpoint = new Uri(this.Configuration.GetValue<string>("Zipkin:Endpoint"));
|
||||
}));
|
||||
break;
|
||||
default:
|
||||
services.AddOpenTelemetryTracing((builder) => builder
|
||||
.AddAspNetCoreInstrumentation()
|
||||
.AddConsoleExporter());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapGrpcService<GreeterService>();
|
||||
|
||||
endpoints.MapGet("/", async context =>
|
||||
{
|
||||
await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Grpc": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Kestrel": {
|
||||
"EndpointDefaults": {
|
||||
"Protocols": "Http2"
|
||||
}
|
||||
},
|
||||
"UseExporter": "console",
|
||||
"Jaeger": {
|
||||
"ServiceName": "jaeger-test",
|
||||
"Host": "localhost",
|
||||
"Port": 6831
|
||||
},
|
||||
"Zipkin": {
|
||||
"ServiceName": "zipkin-test",
|
||||
"Endpoint": "http://localhost:9411/api/v2/spans"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue