From c3080dedc5c2e170a60aa10ace8e34b5444c0a6c Mon Sep 17 00:00:00 2001 From: Mayuki Sawatari Date: Wed, 25 Oct 2023 11:26:22 +0900 Subject: [PATCH 1/2] Remove MagicOnion.Server.OpenTelemetry --- MagicOnion.Experimental.sln | 102 ----- MagicOnion.Experimental.sln.startup.json | 62 --- samples/ChatApp.Telemetry/.dockerignore | 32 -- samples/ChatApp.Telemetry/.gitattributes | 5 - samples/ChatApp.Telemetry/ChatApp.Server.sln | 31 -- .../ChatApp.Server/BackendActivitySources.cs | 13 - .../ChatApp.Server/ChatApp.Server.csproj | 39 -- .../ChatApp.Server/ChatHub.cs | 153 -------- .../ChatApp.Server/ChatService.cs | 80 ---- .../ChatApp.Server/Dockerfile | 25 -- .../ExceptionFilterAttribute.cs | 49 --- .../ChatApp.Server/Program.cs | 21 - .../Properties/launchSettings.json | 10 - .../ChatApp.Server/Startup.cs | 165 -------- .../appsettings.Development.json | 15 - .../ChatApp.Server/appsettings.json | 34 -- .../ChatApp.Shared/ChatApp.Shared.csproj | 26 -- .../MicroServer.Shared/IMessageService.cs | 10 - .../MicroServer.Shared.csproj | 11 - .../ChatApp.Telemetry/MicroServer/Dockerfile | 25 -- .../MicroServer/ExceptionFilterAttribute.cs | 50 --- .../MicroServer/MessageService.cs | 17 - .../MicroServer/MicroServer.csproj | 37 -- .../ChatApp.Telemetry/MicroServer/Program.cs | 27 -- .../Properties/launchSettings.json | 12 - .../MicroServer/Protos/greet.proto | 21 - .../MicroServer/Services/GreeterService.cs | 26 -- .../ChatApp.Telemetry/MicroServer/Startup.cs | 96 ----- .../MicroServer/appsettings.Development.json | 15 - .../MicroServer/appsettings.json | 34 -- samples/ChatApp.Telemetry/Nuget.config | 13 - samples/ChatApp.Telemetry/README.md | 177 --------- .../docker-compose.telemetry.yaml | 79 ---- samples/ChatApp.Telemetry/docker-compose.yaml | 15 - samples/ChatApp.Telemetry/docker/.gitignore | 2 - .../docker/alertmanager/config.yml | 10 - .../docker/grafana/Dockerfile | 3 - .../provisioning/dashboards/provider.yaml | 12 - .../provisioning/datasources/datasource.yaml | 7 - .../docker/grafana/download_dashboards.sh | 9 - .../docker/prometheus/config/alert.rules | 44 --- .../docker/prometheus/config/prometheus.yml | 48 --- samples/ChatApp.Telemetry/docker_build.bat | 5 - samples/ChatApp.Telemetry/docker_push.bat | 11 - samples/ChatApp.Telemetry/docker_run.bat | 2 - samples/ChatApp.Telemetry/docker_stop.bat | 1 - .../ChatApp.Telemetry/k8s/app/deployment.yaml | 37 -- .../k8s/app/kustomization.yaml | 8 - .../k8s/common/kustomization.yaml | 6 - .../ChatApp.Telemetry/k8s/grafana/values.yaml | 41 -- .../k8s/namespace/kustomization.yaml | 2 - .../k8s/namespace/namespace.yaml | 4 - .../k8s/prometheus/values.yaml | 11 - .../k8s/service/kustomization.yaml | 2 - .../k8s/service/service.yaml | 24 -- .../Internal/MagicOnionInstrumentation.cs | 23 -- .../Internal/MagicOnionTelemetryConstants.cs | 11 - .../Internal/OpenTelemetryHelper.cs | 22 -- .../Internal/PropagatorExtensions.cs | 51 --- .../Internal/SemanticConventions.cs | 31 -- .../MagicOnion.Server.OpenTelemetry.csproj | 40 -- .../MagicOnionActivitySources.cs | 25 -- .../MagicOnionOpenTelemetryClientFilter.cs | 90 ----- .../MagicOnionOpenTelemetryOption.cs | 26 -- ...nionOpenTelemetryTracerFilterAttributes.cs | 205 ---------- .../MagicOnionServerBuilderExtensions.cs | 70 ---- src/MagicOnion.Server.OpenTelemetry/README.md | 363 ------------------ .../RpcScope.cs | 134 ------- .../ServiceContextTelemetryExtensions.cs | 57 --- .../TracerProviderBuilderExtensions.cs | 19 - 70 files changed, 2983 deletions(-) delete mode 100644 MagicOnion.Experimental.sln delete mode 100644 MagicOnion.Experimental.sln.startup.json delete mode 100644 samples/ChatApp.Telemetry/.dockerignore delete mode 100644 samples/ChatApp.Telemetry/.gitattributes delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server.sln delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server/BackendActivitySources.cs delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server/ChatApp.Server.csproj delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server/ChatHub.cs delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server/ChatService.cs delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server/Dockerfile delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server/ExceptionFilterAttribute.cs delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server/Program.cs delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server/Properties/launchSettings.json delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server/Startup.cs delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server/appsettings.Development.json delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Server/appsettings.json delete mode 100644 samples/ChatApp.Telemetry/ChatApp.Shared/ChatApp.Shared.csproj delete mode 100644 samples/ChatApp.Telemetry/MicroServer.Shared/IMessageService.cs delete mode 100644 samples/ChatApp.Telemetry/MicroServer.Shared/MicroServer.Shared.csproj delete mode 100644 samples/ChatApp.Telemetry/MicroServer/Dockerfile delete mode 100644 samples/ChatApp.Telemetry/MicroServer/ExceptionFilterAttribute.cs delete mode 100644 samples/ChatApp.Telemetry/MicroServer/MessageService.cs delete mode 100644 samples/ChatApp.Telemetry/MicroServer/MicroServer.csproj delete mode 100644 samples/ChatApp.Telemetry/MicroServer/Program.cs delete mode 100644 samples/ChatApp.Telemetry/MicroServer/Properties/launchSettings.json delete mode 100644 samples/ChatApp.Telemetry/MicroServer/Protos/greet.proto delete mode 100644 samples/ChatApp.Telemetry/MicroServer/Services/GreeterService.cs delete mode 100644 samples/ChatApp.Telemetry/MicroServer/Startup.cs delete mode 100644 samples/ChatApp.Telemetry/MicroServer/appsettings.Development.json delete mode 100644 samples/ChatApp.Telemetry/MicroServer/appsettings.json delete mode 100644 samples/ChatApp.Telemetry/Nuget.config delete mode 100644 samples/ChatApp.Telemetry/README.md delete mode 100644 samples/ChatApp.Telemetry/docker-compose.telemetry.yaml delete mode 100644 samples/ChatApp.Telemetry/docker-compose.yaml delete mode 100644 samples/ChatApp.Telemetry/docker/.gitignore delete mode 100644 samples/ChatApp.Telemetry/docker/alertmanager/config.yml delete mode 100644 samples/ChatApp.Telemetry/docker/grafana/Dockerfile delete mode 100644 samples/ChatApp.Telemetry/docker/grafana/conf/provisioning/dashboards/provider.yaml delete mode 100644 samples/ChatApp.Telemetry/docker/grafana/conf/provisioning/datasources/datasource.yaml delete mode 100644 samples/ChatApp.Telemetry/docker/grafana/download_dashboards.sh delete mode 100644 samples/ChatApp.Telemetry/docker/prometheus/config/alert.rules delete mode 100644 samples/ChatApp.Telemetry/docker/prometheus/config/prometheus.yml delete mode 100644 samples/ChatApp.Telemetry/docker_build.bat delete mode 100644 samples/ChatApp.Telemetry/docker_push.bat delete mode 100644 samples/ChatApp.Telemetry/docker_run.bat delete mode 100644 samples/ChatApp.Telemetry/docker_stop.bat delete mode 100644 samples/ChatApp.Telemetry/k8s/app/deployment.yaml delete mode 100644 samples/ChatApp.Telemetry/k8s/app/kustomization.yaml delete mode 100644 samples/ChatApp.Telemetry/k8s/common/kustomization.yaml delete mode 100644 samples/ChatApp.Telemetry/k8s/grafana/values.yaml delete mode 100644 samples/ChatApp.Telemetry/k8s/namespace/kustomization.yaml delete mode 100644 samples/ChatApp.Telemetry/k8s/namespace/namespace.yaml delete mode 100644 samples/ChatApp.Telemetry/k8s/prometheus/values.yaml delete mode 100644 samples/ChatApp.Telemetry/k8s/service/kustomization.yaml delete mode 100644 samples/ChatApp.Telemetry/k8s/service/service.yaml delete mode 100644 src/MagicOnion.Server.OpenTelemetry/Internal/MagicOnionInstrumentation.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/Internal/MagicOnionTelemetryConstants.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/Internal/OpenTelemetryHelper.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/Internal/PropagatorExtensions.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/Internal/SemanticConventions.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/MagicOnion.Server.OpenTelemetry.csproj delete mode 100644 src/MagicOnion.Server.OpenTelemetry/MagicOnionActivitySources.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryClientFilter.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryOption.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryTracerFilterAttributes.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/MagicOnionServerBuilderExtensions.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/README.md delete mode 100644 src/MagicOnion.Server.OpenTelemetry/RpcScope.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/ServiceContextTelemetryExtensions.cs delete mode 100644 src/MagicOnion.Server.OpenTelemetry/TracerProviderBuilderExtensions.cs diff --git a/MagicOnion.Experimental.sln b/MagicOnion.Experimental.sln deleted file mode 100644 index 018b74d75..000000000 --- a/MagicOnion.Experimental.sln +++ /dev/null @@ -1,102 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28729.10 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1987061F-8970-4018-8D58-6932961C9EB4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{7ACC27E8-8FBE-4807-B91F-B89AF3CFF7E0}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{5A3F5158-7B17-4586-9885-9E60C1393185}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{15598FE3-201F-4255-9ADA-622B52D2A6ED}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - .gitignore = .gitignore - .circleci\config.yml = .circleci\config.yml - LICENSE = LICENSE - README.md = README.md - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{42EBB7E4-52D7-4E57-80AD-79FDD4900E13}" - ProjectSection(SolutionItems) = preProject - Directory.Build.props = Directory.Build.props - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ChatApp.Telemetry", "ChatApp.Telemetry", "{134A64BF-3792-44EC-BD32-DD076A6B5643}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatApp.Server", "samples\ChatApp.Telemetry\ChatApp.Server\ChatApp.Server.csproj", "{B72BEFE9-AB6C-4340-BB0D-C6E300E1C442}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatApp.Shared", "samples\ChatApp.Telemetry\ChatApp.Shared\ChatApp.Shared.csproj", "{A54E6CE7-6053-4186-94BF-EAF57432256B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MagicOnion.Server.OpenTelemetry", "src\MagicOnion.Server.OpenTelemetry\MagicOnion.Server.OpenTelemetry.csproj", "{BD3A9267-EE7C-4D3A-B877-1772DCAD7358}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "references", "references", "{546FFD98-9FA5-48CA-8847-16AF82C3DED0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MagicOnion.Server", "src\MagicOnion.Server\MagicOnion.Server.csproj", "{E6A78679-C7E1-4507-A727-8CD2C0B2C5CB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MagicOnion.Abstractions", "src\MagicOnion.Abstractions\MagicOnion.Abstractions.csproj", "{32101781-544B-44AB-8131-31909B438DC9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicroServer", "samples\ChatApp.Telemetry\MicroServer\MicroServer.csproj", "{2A6D2D7C-82BE-4CB2-B8C3-2D65BEAAF957}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MagicOnion.Client", "src\MagicOnion.Client\MagicOnion.Client.csproj", "{8CDFC77C-7E42-4D42-8168-5E799EC7AB21}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicroServer.Shared", "samples\ChatApp.Telemetry\MicroServer.Shared\MicroServer.Shared.csproj", "{B29DEE64-4D65-4CDB-A83E-1C231165BE1E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B72BEFE9-AB6C-4340-BB0D-C6E300E1C442}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B72BEFE9-AB6C-4340-BB0D-C6E300E1C442}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B72BEFE9-AB6C-4340-BB0D-C6E300E1C442}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B72BEFE9-AB6C-4340-BB0D-C6E300E1C442}.Release|Any CPU.Build.0 = Release|Any CPU - {A54E6CE7-6053-4186-94BF-EAF57432256B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A54E6CE7-6053-4186-94BF-EAF57432256B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A54E6CE7-6053-4186-94BF-EAF57432256B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A54E6CE7-6053-4186-94BF-EAF57432256B}.Release|Any CPU.Build.0 = Release|Any CPU - {BD3A9267-EE7C-4D3A-B877-1772DCAD7358}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BD3A9267-EE7C-4D3A-B877-1772DCAD7358}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BD3A9267-EE7C-4D3A-B877-1772DCAD7358}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BD3A9267-EE7C-4D3A-B877-1772DCAD7358}.Release|Any CPU.Build.0 = Release|Any CPU - {E6A78679-C7E1-4507-A727-8CD2C0B2C5CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E6A78679-C7E1-4507-A727-8CD2C0B2C5CB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E6A78679-C7E1-4507-A727-8CD2C0B2C5CB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E6A78679-C7E1-4507-A727-8CD2C0B2C5CB}.Release|Any CPU.Build.0 = Release|Any CPU - {32101781-544B-44AB-8131-31909B438DC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {32101781-544B-44AB-8131-31909B438DC9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {32101781-544B-44AB-8131-31909B438DC9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {32101781-544B-44AB-8131-31909B438DC9}.Release|Any CPU.Build.0 = Release|Any CPU - {2A6D2D7C-82BE-4CB2-B8C3-2D65BEAAF957}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2A6D2D7C-82BE-4CB2-B8C3-2D65BEAAF957}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A6D2D7C-82BE-4CB2-B8C3-2D65BEAAF957}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2A6D2D7C-82BE-4CB2-B8C3-2D65BEAAF957}.Release|Any CPU.Build.0 = Release|Any CPU - {8CDFC77C-7E42-4D42-8168-5E799EC7AB21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8CDFC77C-7E42-4D42-8168-5E799EC7AB21}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8CDFC77C-7E42-4D42-8168-5E799EC7AB21}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8CDFC77C-7E42-4D42-8168-5E799EC7AB21}.Release|Any CPU.Build.0 = Release|Any CPU - {B29DEE64-4D65-4CDB-A83E-1C231165BE1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B29DEE64-4D65-4CDB-A83E-1C231165BE1E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B29DEE64-4D65-4CDB-A83E-1C231165BE1E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B29DEE64-4D65-4CDB-A83E-1C231165BE1E}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {134A64BF-3792-44EC-BD32-DD076A6B5643} = {5A3F5158-7B17-4586-9885-9E60C1393185} - {B72BEFE9-AB6C-4340-BB0D-C6E300E1C442} = {134A64BF-3792-44EC-BD32-DD076A6B5643} - {A54E6CE7-6053-4186-94BF-EAF57432256B} = {134A64BF-3792-44EC-BD32-DD076A6B5643} - {BD3A9267-EE7C-4D3A-B877-1772DCAD7358} = {1987061F-8970-4018-8D58-6932961C9EB4} - {E6A78679-C7E1-4507-A727-8CD2C0B2C5CB} = {546FFD98-9FA5-48CA-8847-16AF82C3DED0} - {32101781-544B-44AB-8131-31909B438DC9} = {546FFD98-9FA5-48CA-8847-16AF82C3DED0} - {2A6D2D7C-82BE-4CB2-B8C3-2D65BEAAF957} = {134A64BF-3792-44EC-BD32-DD076A6B5643} - {8CDFC77C-7E42-4D42-8168-5E799EC7AB21} = {546FFD98-9FA5-48CA-8847-16AF82C3DED0} - {B29DEE64-4D65-4CDB-A83E-1C231165BE1E} = {134A64BF-3792-44EC-BD32-DD076A6B5643} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {D5B2E7E3-B727-40A1-BE68-7BAC9B9DE2FE} - EndGlobalSection -EndGlobal diff --git a/MagicOnion.Experimental.sln.startup.json b/MagicOnion.Experimental.sln.startup.json deleted file mode 100644 index d5de1da7d..000000000 --- a/MagicOnion.Experimental.sln.startup.json +++ /dev/null @@ -1,62 +0,0 @@ -/* - This is a configuration file for the SwitchStartupProject Visual Studio Extension - See https://heptapod.host/thirteen/switchstartupproject/blob/branch/current/Configuration.md -*/ -{ - /* Configuration File Version */ - "Version": 3, - - /* Create an item in the dropdown list for each project in the solution? */ - "ListAllProjects": true, - - /* - Dictionary of named configurations with one or multiple startup projects - and optional parameters like command line arguments and working directory. - Example: - - "MultiProjectConfigurations": { - "A + B (Ext)": { - "Projects": { - "MyProjectA": {}, - "MyProjectB": { - "CommandLineArguments": "1234", - "WorkingDirectory": "%USERPROFILE%\\test", - "StartExternalProgram": "c:\\myprogram.exe" - } - } - }, - "A + B": { - "Projects": { - "MyProjectA": {}, - "MyProjectB": { - "CommandLineArguments": "", - "WorkingDirectory": "", - "StartProject": true - } - } - }, - "D (Debug x86)": { - "Projects": { - "MyProjectD": {} - }, - "SolutionConfiguration": "Debug", - "SolutionPlatform": "x86", - }, - "D (Release x64)": { - "Projects": { - "MyProjectD": {} - }, - "SolutionConfiguration": "Release", - "SolutionPlatform": "x64", - } - } - */ - "MultiProjectConfigurations": { - "ChatApp.Server + MicroServer": { - "Projects": { - "ChatApp.Server": {}, - "MicroServer": {} - } - } - } -} diff --git a/samples/ChatApp.Telemetry/.dockerignore b/samples/ChatApp.Telemetry/.dockerignore deleted file mode 100644 index 3eb2d74b6..000000000 --- a/samples/ChatApp.Telemetry/.dockerignore +++ /dev/null @@ -1,32 +0,0 @@ -.git/ -.vs/ -bin/ -obj/ -**/.dockerignore -**/.env -**/.git -**/.gitignore -**/.gitattributes -**/.vs -**/.vscode -**/*.*proj.user -**/azds.yaml -**/charts -**/bin -**/obj -**/Dockerfile -**/Dockerfile.develop -**/docker-compose.yml -**/docker-compose.*.yml -**/*.dbmdl -**/*.jfm -**/secrets.dev.yaml -**/values.dev.yaml -**/.toolstarget - -docs/ -samples/ChatApp/ -samples/ChatApp.Telemetry/ChatApp.Unity/Temp/ -samples/ChatApp.Telemetry/ChatApp.Unity/Library/ -sandbox/ -tests/ \ No newline at end of file diff --git a/samples/ChatApp.Telemetry/.gitattributes b/samples/ChatApp.Telemetry/.gitattributes deleted file mode 100644 index d8afd5f40..000000000 --- a/samples/ChatApp.Telemetry/.gitattributes +++ /dev/null @@ -1,5 +0,0 @@ -*.sh text eol=lf -*.yml text eol=lf -*.yaml text eol=lf -*.config text eol=lf -*.rules text eol=lf diff --git a/samples/ChatApp.Telemetry/ChatApp.Server.sln b/samples/ChatApp.Telemetry/ChatApp.Server.sln deleted file mode 100644 index 7b58bde21..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29509.3 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatApp.Server", "ChatApp.Server\ChatApp.Server.csproj", "{053476FC-B8B2-4A14-AED2-3733DFD5DFC3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatApp.Shared", "ChatApp.Shared\ChatApp.Shared.csproj", "{C71FCFFD-1FB9-4FD8-9DC3-6A60B2F3D848}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {053476FC-B8B2-4A14-AED2-3733DFD5DFC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {053476FC-B8B2-4A14-AED2-3733DFD5DFC3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {053476FC-B8B2-4A14-AED2-3733DFD5DFC3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {053476FC-B8B2-4A14-AED2-3733DFD5DFC3}.Release|Any CPU.Build.0 = Release|Any CPU - {C71FCFFD-1FB9-4FD8-9DC3-6A60B2F3D848}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C71FCFFD-1FB9-4FD8-9DC3-6A60B2F3D848}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C71FCFFD-1FB9-4FD8-9DC3-6A60B2F3D848}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C71FCFFD-1FB9-4FD8-9DC3-6A60B2F3D848}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {30D3EFC0-A5F4-4446-B14E-1C2C1740AA87} - EndGlobalSection -EndGlobal diff --git a/samples/ChatApp.Telemetry/ChatApp.Server/BackendActivitySources.cs b/samples/ChatApp.Telemetry/ChatApp.Server/BackendActivitySources.cs deleted file mode 100644 index 927e46669..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server/BackendActivitySources.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Diagnostics; - -namespace ChatApp.Server -{ - public static class BackendActivitySources - { - public static readonly string[] ExtraActivitySourceNames = new[] { "Chatapp.Server.S2S", "MySQL", "Redis" }; - - public static readonly ActivitySource S2sActivitySource = new ActivitySource("Chatapp.Server.S2S"); - public static readonly ActivitySource MySQLActivitySource = new ActivitySource("MySQL"); - public static readonly ActivitySource RedisActivitySource = new ActivitySource("Redis"); - } -} diff --git a/samples/ChatApp.Telemetry/ChatApp.Server/ChatApp.Server.csproj b/samples/ChatApp.Telemetry/ChatApp.Server/ChatApp.Server.csproj deleted file mode 100644 index be965cea2..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server/ChatApp.Server.csproj +++ /dev/null @@ -1,39 +0,0 @@ - - - - Exe - net5.0 - latest - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - diff --git a/samples/ChatApp.Telemetry/ChatApp.Server/ChatHub.cs b/samples/ChatApp.Telemetry/ChatApp.Server/ChatHub.cs deleted file mode 100644 index 99d3618d4..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server/ChatHub.cs +++ /dev/null @@ -1,153 +0,0 @@ -using ChatApp.Shared.Hubs; -using ChatApp.Shared.MessagePackObjects; -using MagicOnion.Server.Hubs; -using MagicOnion.Server.OpenTelemetry; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading.Tasks; - -namespace ChatApp.Server -{ - /// - /// Chat server processing. - /// One class instance for one connection. - /// - public class ChatHub : StreamingHubBase, IChatHub - { - private IGroup room; - private string myName; - private readonly ActivitySource mysqlActivity = BackendActivitySources.MySQLActivitySource; - private readonly ActivitySource redisActivity = BackendActivitySources.RedisActivitySource; - private readonly MagicOnionOpenTelemetryOptions options; - - public ChatHub(MagicOnionOpenTelemetryOptions options) - { - this.options = options; - } - - public async Task JoinAsync(JoinRequest request) - { - room = await this.Group.AddAsync(request.RoomName); - myName = request.UserName; - Broadcast(this.room).OnJoin(request.UserName); - - // dummy external operation db. - var random = new Random(); - using (var activity = mysqlActivity.StartActivity("room/insert", ActivityKind.Internal)) - { - // this is sample. use orm or any safe way. - activity?.SetTag("service.name", options.ServiceName); - activity?.SetTag("table", "rooms"); - activity?.SetTag("query", $"INSERT INTO rooms VALUES (0, '@room', '@username', '1');"); - activity?.SetTag("parameter.room", request.RoomName); - activity?.SetTag("parameter.username", request.UserName); - await Task.Delay(TimeSpan.FromMilliseconds(random.Next(2, 20))); - } - using (var activity = redisActivity.StartActivity($"member/status", ActivityKind.Internal)) - { - activity?.SetTag("service.name", options.ServiceName); - activity?.SetTag("command", "set"); - activity?.SetTag("parameter.key", this.myName); - activity?.SetTag("parameter.value", "1"); - await Task.Delay(TimeSpan.FromMilliseconds(random.Next(1, 5))); - } - - // add this time only tag - var scope = this.Context.GetTraceScope(nameof(IChatHub) + "/" + nameof(JoinAsync)); - scope?.SetTags(new Dictionary { { "my_key", Context.ContextId.ToString() } }); - } - - public async Task LeaveAsync() - { - await this.room.RemoveAsync(this.Context); - this.Broadcast(this.room).OnLeave(this.myName); - - // dummy external operation. - var random = new Random(); - using (var activity = mysqlActivity.StartActivity("room/update", ActivityKind.Internal)) - { - // this is sample. use orm or any safe way. - activity?.SetTag("service.name", options.ServiceName); - activity?.SetTag("table", "rooms"); - activity?.SetTag("query", $"UPDATE rooms SET status=0 WHERE id='room' AND name='@username';"); - activity?.SetTag("parameter.room", this.room.GroupName); - activity?.SetTag("parameter.username", this.myName); - await Task.Delay(TimeSpan.FromMilliseconds(random.Next(2, 20))); - } - - using (var activity = redisActivity.StartActivity($"member/status", ActivityKind.Internal)) - { - activity?.SetTag("service.name", options.ServiceName); - activity?.SetTag("command", "set"); - activity?.SetTag("parameter.key", this.myName); - activity?.SetTag("parameter.value", "0"); - await Task.Delay(TimeSpan.FromMilliseconds(random.Next(1, 5))); - } - } - - public async Task SendMessageAsync(string message) - { - var response = new MessageResponse { UserName = this.myName, Message = message }; - this.Broadcast(this.room).OnSendMessage(response); - - // dummy external operation. - var random = new Random(); - using (var activity = redisActivity.StartActivity($"chat_latest_message", ActivityKind.Internal)) - { - activity?.SetTag("service.name", options.ServiceName); - activity?.SetTag("command", "set"); - activity?.SetTag("parameter.key", room.GroupName); - activity?.SetTag("parameter.value", $"{myName}={message}"); - await Task.Delay(TimeSpan.FromMilliseconds(random.Next(1, 5))); - } - - await Task.CompletedTask; - } - - public async Task GenerateException(string message) - { - var ex = new Exception(message); - - // dummy external operation. - var random = new Random(); - using (var activity = mysqlActivity.StartActivity("errors/insert", ActivityKind.Internal)) - { - // this is sample. use orm or any safe way. - activity?.SetTag("service.name", options.ServiceName); - activity?.SetTag("table", "errors"); - activity?.SetTag("query", $"INSERT INTO rooms VALUES ('{ex.Message}', '{ex.StackTrace}');"); - await Task.Delay(TimeSpan.FromMilliseconds(random.Next(2, 20))); - } - throw ex; - } - - // It is not called because it is a method as a sample of arguments. - public Task SampleMethod(List sampleList, Dictionary sampleDictionary) - { - throw new System.NotImplementedException(); - } - - protected override ValueTask OnConnecting() - { - // use hub trace context to set your span on same level. Otherwise parent will automatically set. - var scope = this.Context.GetTraceScope(); - scope?.SetTags(new Dictionary { { "magiconion.connect_status", "connected" } }); - - // handle connection if needed. - Console.WriteLine($"client connected {this.Context.ContextId}"); - return CompletedTask; - } - - protected override ValueTask OnDisconnected() - { - // use hub trace context to set your span on same level. Otherwise parent will automatically set. - var scope = this.Context.GetTraceScope(); - scope?.SetTags(new Dictionary { { "magiconion.connect_status", "disconnected" } }); - - // handle disconnection if needed. - // on disconnecting, if automatically removed this connection from group. - return CompletedTask; - } - } -} diff --git a/samples/ChatApp.Telemetry/ChatApp.Server/ChatService.cs b/samples/ChatApp.Telemetry/ChatApp.Server/ChatService.cs deleted file mode 100644 index 367f6fe10..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server/ChatService.cs +++ /dev/null @@ -1,80 +0,0 @@ -using ChatApp.Shared.Services; -using MagicOnion; -using MagicOnion.Server; -using MessagePack; -using System; -using System.Diagnostics; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Grpc.Net.Client; -using MagicOnion.Client; -using MicroServer.Shared; -using MagicOnion.Server.OpenTelemetry; - -namespace ChatApp.Server -{ - public class ChatService : ServiceBase, IChatService - { - private readonly ActivitySource mysqlActivity = BackendActivitySources.MySQLActivitySource; - private readonly ActivitySource s2sActivity = BackendActivitySources.S2sActivitySource; - private readonly MagicOnionOpenTelemetryOptions options; - private readonly ILogger logger; - - public ChatService(MagicOnionOpenTelemetryOptions options, ILogger logger) - { - this.options = options; - this.logger = logger; - } - - public async UnaryResult GenerateException(string message) - { - var ex = new System.NotImplementedException(); - // dummy external operation. - using (var activity = this.mysqlActivity.StartActivity("errors/insert", ActivityKind.Internal)) - { - // this is sample. use orm or any safe way. - activity?.SetTag("service.name", options.ServiceName); - activity?.SetTag("table", "errors"); - activity?.SetTag("query", $"INSERT INTO rooms VALUES ('{ex.Message}', '{ex.StackTrace}');"); - await Task.Delay(TimeSpan.FromMilliseconds(2)); - } - throw ex; - } - - public async UnaryResult SendReportAsync(string message) - { - logger.LogDebug($"{message}"); - - // dummy external operation. - using (var activity = this.mysqlActivity.StartActivity("report/insert", ActivityKind.Internal)) - { - // this is sample. use orm or any safe way. - activity?.SetTag("service.name", options.ServiceName); - activity?.SetTag("table", "report"); - activity?.SetTag("query", $"INSERT INTO report VALUES ('foo', 'bar');"); - await Task.Delay(TimeSpan.FromMilliseconds(2)); - } - - // Server to Server operation - var channel = GrpcChannel.ForAddress(Environment.GetEnvironmentVariable("Server2ServerEndpoint", EnvironmentVariableTarget.Process) ?? "http://localhost:4999"); - var client = MagicOnionClient.Create(channel, new[] - { - // propagate trace context from ChatApp.Server to MicroServer - new MagicOnionOpenTelemetryClientFilter(s2sActivity, options), - }); - await client.SendAsync("hello"); - - // dummy external operation. - using (var activity = this.mysqlActivity.StartActivity("report/get", ActivityKind.Internal)) - { - // this is sample. use orm or any safe way. - activity?.SetTag("service.name", options.ServiceName); - activity?.SetTag("table", "report"); - activity?.SetTag("query", $"INSERT INTO report VALUES ('foo', 'bar');"); - await Task.Delay(TimeSpan.FromMilliseconds(1)); - } - - return Nil.Default; - } - } -} diff --git a/samples/ChatApp.Telemetry/ChatApp.Server/Dockerfile b/samples/ChatApp.Telemetry/ChatApp.Server/Dockerfile deleted file mode 100644 index aa36ba31a..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base -EXPOSE 12345 -WORKDIR /app - -FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build -WORKDIR /src -COPY ["samples/ChatApp.Telemetry/ChatApp.Server/ChatApp.Server.csproj", "samples/ChatApp.Telemetry/ChatApp.Server/"] -COPY ["samples/ChatApp.Telemetry/ChatApp.Shared/ChatApp.Shared.csproj", "samples/ChatApp.Telemetry/ChatApp.Shared/"] -COPY ["src/MagicOnion/MagicOnion.csproj", "src/MagicOnion/"] -COPY ["src/MagicOnion.Abstractions/MagicOnion.Abstractions.csproj", "src/MagicOnion.Abstractions/"] -COPY ["src/MagicOnion.Server/MagicOnion.Server.csproj", "src/MagicOnion.Server/"] -COPY ["src/MagicOnion.Server.OpenTelemetry/MagicOnion.Server.OpenTelemetry.csproj", "src/MagicOnion.Server.OpenTelemetry/"] -COPY ["src/MagicOnion.Shared/MagicOnion.Shared.csproj", "src/MagicOnion.Shared/"] -RUN dotnet restore "samples/ChatApp.Telemetry/ChatApp.Server/ChatApp.Server.csproj" -COPY . . -WORKDIR "/src/samples/ChatApp.Telemetry/ChatApp.Server" -RUN dotnet build "ChatApp.Server.csproj" -c Debug -o /app - -FROM build AS publish -RUN dotnet publish "ChatApp.Server.csproj" -c Debug -o /app - -FROM base AS final -WORKDIR /app -COPY --from=publish /app . -ENTRYPOINT ["dotnet", "ChatApp.Server.dll"] \ No newline at end of file diff --git a/samples/ChatApp.Telemetry/ChatApp.Server/ExceptionFilterAttribute.cs b/samples/ChatApp.Telemetry/ChatApp.Server/ExceptionFilterAttribute.cs deleted file mode 100644 index 4d9ebe1ba..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server/ExceptionFilterAttribute.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Threading.Tasks; - -namespace MagicOnion.Server.OpenTelemetry -{ - /// - /// Application Exception Filter to set gRPC Status as app wants - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] - public class ExceptionFilterFactoryAttribute : Attribute, IMagicOnionFilterFactory - { - public int Order { get; set; } - - MagicOnionFilterAttribute IMagicOnionFilterFactory.CreateInstance(IServiceProvider serviceProvider) - { - return new ExceptionFilterAttribute(); - } - } - - internal class ExceptionFilterAttribute : MagicOnionFilterAttribute - { - public override async ValueTask Invoke(ServiceContext context, Func next) - { - try - { - await next(context); - } - catch (Exception ex) - { - SetStatusCode(context, ConvertToGrpcStatus(ex), ex.Message); - throw; - } - } - - /// - /// Your Exception -> gRPC Status Converter - /// - /// - /// - private Grpc.Core.StatusCode ConvertToGrpcStatus(Exception ex) - { - return ex switch - { - NotImplementedException => Grpc.Core.StatusCode.Unimplemented, - _ => Grpc.Core.StatusCode.Internal, - }; - } - } -} \ No newline at end of file diff --git a/samples/ChatApp.Telemetry/ChatApp.Server/Program.cs b/samples/ChatApp.Telemetry/ChatApp.Server/Program.cs deleted file mode 100644 index ef8615591..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server/Program.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.Extensions.Hosting; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Core; - -namespace ChatApp.Server -{ - class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); - } -} diff --git a/samples/ChatApp.Telemetry/ChatApp.Server/Properties/launchSettings.json b/samples/ChatApp.Telemetry/ChatApp.Server/Properties/launchSettings.json deleted file mode 100644 index 1dacf7e7d..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server/Properties/launchSettings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "profiles": { - "ChatApp.Server.Telemetry": { - "commandName": "Project", - "environmentVariables": { - "DOTNET_ENVIRONMENT": "Development" - } - } - } -} \ No newline at end of file diff --git a/samples/ChatApp.Telemetry/ChatApp.Server/Startup.cs b/samples/ChatApp.Telemetry/ChatApp.Server/Startup.cs deleted file mode 100644 index 56b55eea7..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server/Startup.cs +++ /dev/null @@ -1,165 +0,0 @@ -using MagicOnion.Server; -using MagicOnion.Server.OpenTelemetry; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Hosting; -using OpenTelemetry; -using OpenTelemetry.Resources; -using OpenTelemetry.Trace; - -namespace ChatApp.Server -{ - 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) - { - // OpenTelemetry Require set of Listener + Instrumentation. - // - Listener will add via services.AddMagicOnion().UseOpenTelemetry() - // - Instrumentation will add via TraceProviderBuilder.AddMagicOnionInstrumentation() - services.AddGrpc(); // MagicOnion depends on ASP.NET Core gRPC service. - services.AddMagicOnion(options => - { - options.GlobalFilters.Add(new MagicOnionOpenTelemetryTracerFilterFactoryAttribute()); - options.GlobalStreamingHubFilters.Add(new MagicOnionOpenTelemetryStreamingTracerFilterFactoryAttribute()); - - // Exception Filter enable Telemetry to know which gRPC Error happen. - options.GlobalFilters.Add(new ExceptionFilterFactoryAttribute()); - }) - .AddOpenTelemetry(); // Listen OpenTelemetry Activity - - // Configure OpenTelemetry as usual. - services.AddOpenTelemetryTracing(configure => - { - var exporter = this.Configuration.GetValue("UseExporter").ToLowerInvariant(); - switch (exporter) - { - // Switch between Jaeger/Zipkin by setting UseExporter in appsettings.json. - case "jaeger": - var jo = new OpenTelemetry.Exporter.JaegerExporterOptions(); - Configuration.GetSection("Jaeger").Bind(jo); - configure - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("ChatApp.Server")) - .AddAspNetCoreInstrumentation() - .AddMagicOnionInstrumentation() // enable MagicOnion instrumentation - .AddJaegerExporter(); - services.Configure(Configuration.GetSection("Jaeger")); - break; - case "zipkin": - var zo = new OpenTelemetry.Exporter.ZipkinExporterOptions(); - Configuration.GetSection("Zipkin").Bind(zo); - configure - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("ChatApp.Server")) - .AddAspNetCoreInstrumentation() - .AddMagicOnionInstrumentation() // enable MagicOnion instrumentation - .AddZipkinExporter(); - services.Configure(this.Configuration.GetSection("Zipkin")); - break; - default: - // ConsoleExporter will show current tracer activity - configure - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("ChatApp.Server")) - .AddAspNetCoreInstrumentation() - .AddMagicOnionInstrumentation() // enable MagicOnion instrumentation - .AddConsoleExporter(); - services.Configure(this.Configuration.GetSection("AspNetCoreInstrumentation")); - services.Configure(options => - { - options.Filter = (req) => req.Request?.Host != null; - }); - break; - } - }); - - // additional Tracer for user's own service. - // This means we cannot use AddOpenTelemetryTracing(), but require Sdk.CreateTracerProviderBuilder() instead. - services.AddAdditionalTracer(Configuration); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Home/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - //app.UseHttpsRedirection(); - - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapMagicOnionService(); - - 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"); - }); - }); - } - } - - public static class ServiceCollectionExtentions - { - // If you want use multiple trace service, Do not use AddOpenTelemetryTracing, but use multiple Sdk.CreateTracerProviderBuilder() instead. - // ref: https://github.com/open-telemetry/opentelemetry-dotnet/issues/2040 - public static void AddAdditionalTracer(this IServiceCollection services, IConfiguration configuration) - { - var exporter = configuration.GetValue("UseExporter").ToLowerInvariant(); - foreach (var service in BackendActivitySources.ExtraActivitySourceNames) - { - switch (exporter) - { - case "jaeger": - var jo = new OpenTelemetry.Exporter.JaegerExporterOptions(); - configuration.GetSection("Jaeger").Bind(jo); - Sdk.CreateTracerProviderBuilder() - .AddSource(service) - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(service)) - .AddJaegerExporter(o => - { - o.AgentHost = jo.AgentHost; - o.AgentPort = jo.AgentPort; - }) - .Build(); - break; - case "zipkin": - var zo = new OpenTelemetry.Exporter.ZipkinExporterOptions(); - configuration.GetSection("Zipkin").Bind(zo); - Sdk.CreateTracerProviderBuilder() - .AddSource(service) - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(service)) - .AddZipkinExporter(o => o.Endpoint = zo.Endpoint) - .Build(); - break; - default: - // ConsoleExporter will show current tracer activity - Sdk.CreateTracerProviderBuilder() - .AddSource(service) - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(service)) - .AddConsoleExporter() - .Build(); - break; - } - } - } - } -} diff --git a/samples/ChatApp.Telemetry/ChatApp.Server/appsettings.Development.json b/samples/ChatApp.Telemetry/ChatApp.Server/appsettings.Development.json deleted file mode 100644 index 17855f5d6..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server/appsettings.Development.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Debug", - "System": "Information", - "Grpc": "Information", - "Microsoft": "Information" - } - }, - "MagicOnion": { - "Service": { - "IsReturnExceptionStackTraceInErrorDetail": true - } - } -} diff --git a/samples/ChatApp.Telemetry/ChatApp.Server/appsettings.json b/samples/ChatApp.Telemetry/ChatApp.Server/appsettings.json deleted file mode 100644 index e8bf9f3b3..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Server/appsettings.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Trace", - "System": "Information", - "Microsoft": "Information" - } - }, - "Kestrel": { - "EndpointDefaults": { - "Protocols": "Http2" - } - }, - "MagicOnion": { - "OpenTelemetry": { - "ServiceName": "ChatApp.Server", - // "ExposeRpcScope": false, - "TracingTags": { - "foo": "bar" - } - } - }, - "UseExporter": "jaeger", // select "console", "zipkin", "jaeger" - "Jaeger": { - "AgentHost": "localhost", - "AgentPort": 6831 - }, - "Zipkin": { - "Endpoint": "http://localhost:9411/api/v2/spans" - }, - "AspNetCoreInstrumentation": { - "RecordException": "true" - } -} diff --git a/samples/ChatApp.Telemetry/ChatApp.Shared/ChatApp.Shared.csproj b/samples/ChatApp.Telemetry/ChatApp.Shared/ChatApp.Shared.csproj deleted file mode 100644 index f2ec62696..000000000 --- a/samples/ChatApp.Telemetry/ChatApp.Shared/ChatApp.Shared.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - netstandard2.0 - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/ChatApp.Telemetry/MicroServer.Shared/IMessageService.cs b/samples/ChatApp.Telemetry/MicroServer.Shared/IMessageService.cs deleted file mode 100644 index 8d9da00cd..000000000 --- a/samples/ChatApp.Telemetry/MicroServer.Shared/IMessageService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MagicOnion; -using MessagePack; - -namespace MicroServer.Shared -{ - public interface IMessageService : IService - { - UnaryResult SendAsync(string message); - } -} diff --git a/samples/ChatApp.Telemetry/MicroServer.Shared/MicroServer.Shared.csproj b/samples/ChatApp.Telemetry/MicroServer.Shared/MicroServer.Shared.csproj deleted file mode 100644 index e761f6e77..000000000 --- a/samples/ChatApp.Telemetry/MicroServer.Shared/MicroServer.Shared.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - netstandard2.1 - - - - - - - diff --git a/samples/ChatApp.Telemetry/MicroServer/Dockerfile b/samples/ChatApp.Telemetry/MicroServer/Dockerfile deleted file mode 100644 index c79c2399f..000000000 --- a/samples/ChatApp.Telemetry/MicroServer/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base -EXPOSE 12345 -WORKDIR /app - -FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build -WORKDIR /src -COPY ["samples/ChatApp.Telemetry/MicroServer/MicroServer.csproj", "samples/ChatApp.Telemetry/MicroServer/"] -COPY ["samples/ChatApp.Telemetry/ChatApp.Shared/ChatApp.Shared.csproj", "samples/ChatApp.Telemetry/ChatApp.Shared/"] -COPY ["src/MagicOnion/MagicOnion.csproj", "src/MagicOnion/"] -COPY ["src/MagicOnion.Abstractions/MagicOnion.Abstractions.csproj", "src/MagicOnion.Abstractions/"] -COPY ["src/MagicOnion.Server/MagicOnion.Server.csproj", "src/MagicOnion.Server/"] -COPY ["src/MagicOnion.Server.OpenTelemetry/MagicOnion.Server.OpenTelemetry.csproj", "src/MagicOnion.Server.OpenTelemetry/"] -COPY ["src/MagicOnion.Shared/MagicOnion.Shared.csproj", "src/MagicOnion.Shared/"] -RUN dotnet restore "samples/ChatApp.Telemetry/MicroServer/MicroServer.csproj" -COPY . . -WORKDIR "/src/samples/ChatApp.Telemetry/MicroServer" -RUN dotnet build "MicroServer.csproj" -c Debug -o /app - -FROM build AS publish -RUN dotnet publish "MicroServer.csproj" -c Debug -o /app - -FROM base AS final -WORKDIR /app -COPY --from=publish /app . -ENTRYPOINT ["dotnet", "MicroServer.dll"] \ No newline at end of file diff --git a/samples/ChatApp.Telemetry/MicroServer/ExceptionFilterAttribute.cs b/samples/ChatApp.Telemetry/MicroServer/ExceptionFilterAttribute.cs deleted file mode 100644 index f052c0144..000000000 --- a/samples/ChatApp.Telemetry/MicroServer/ExceptionFilterAttribute.cs +++ /dev/null @@ -1,50 +0,0 @@ -using MagicOnion.Server; -using System; -using System.Threading.Tasks; - -namespace MicroServer -{ - /// - /// Application Exception Filter to set gRPC Status as app wants - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] - public class ExceptionFilterFactoryAttribute : Attribute, IMagicOnionFilterFactory - { - public int Order { get; set; } - - MagicOnionFilterAttribute IMagicOnionFilterFactory.CreateInstance(IServiceProvider serviceProvider) - { - return new ExceptionFilterAttribute(); - } - } - - internal class ExceptionFilterAttribute : MagicOnionFilterAttribute - { - public override async ValueTask Invoke(ServiceContext context, Func next) - { - try - { - await next(context); - } - catch (Exception ex) - { - SetStatusCode(context, ConvertToGrpcStatus(ex), ex.Message); - throw; - } - } - - /// - /// Your Exception -> gRPC Status Converter - /// - /// - /// - private Grpc.Core.StatusCode ConvertToGrpcStatus(Exception ex) - { - return ex switch - { - NotImplementedException => Grpc.Core.StatusCode.Unimplemented, - _ => Grpc.Core.StatusCode.Internal, - }; - } - } -} \ No newline at end of file diff --git a/samples/ChatApp.Telemetry/MicroServer/MessageService.cs b/samples/ChatApp.Telemetry/MicroServer/MessageService.cs deleted file mode 100644 index 4a1a12c93..000000000 --- a/samples/ChatApp.Telemetry/MicroServer/MessageService.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MagicOnion; -using MagicOnion.Server; -using MicroServer.Shared; -using System; -using System.Threading.Tasks; - -namespace MicroServer -{ - public class MessageService : ServiceBase, IMessageService - { - public async UnaryResult SendAsync(string message) - { - await Task.Delay(TimeSpan.FromMilliseconds(20)); - return $"echo {message}"; - } - } -} diff --git a/samples/ChatApp.Telemetry/MicroServer/MicroServer.csproj b/samples/ChatApp.Telemetry/MicroServer/MicroServer.csproj deleted file mode 100644 index a4403ddb0..000000000 --- a/samples/ChatApp.Telemetry/MicroServer/MicroServer.csproj +++ /dev/null @@ -1,37 +0,0 @@ - - - - net5.0 - latest - - - - - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - PreserveNewest - - - - diff --git a/samples/ChatApp.Telemetry/MicroServer/Program.cs b/samples/ChatApp.Telemetry/MicroServer/Program.cs deleted file mode 100644 index 5edca02b0..000000000 --- a/samples/ChatApp.Telemetry/MicroServer/Program.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -namespace MicroServer -{ - 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(); - }); - } -} diff --git a/samples/ChatApp.Telemetry/MicroServer/Properties/launchSettings.json b/samples/ChatApp.Telemetry/MicroServer/Properties/launchSettings.json deleted file mode 100644 index bffeccb43..000000000 --- a/samples/ChatApp.Telemetry/MicroServer/Properties/launchSettings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "profiles": { - "MicroServer": { - "commandName": "Project", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "dotnetRunMessages": "true", - "applicationUrl": "http://localhost:4999" - } - } -} \ No newline at end of file diff --git a/samples/ChatApp.Telemetry/MicroServer/Protos/greet.proto b/samples/ChatApp.Telemetry/MicroServer/Protos/greet.proto deleted file mode 100644 index 300323ff4..000000000 --- a/samples/ChatApp.Telemetry/MicroServer/Protos/greet.proto +++ /dev/null @@ -1,21 +0,0 @@ -syntax = "proto3"; - -option csharp_namespace = "MicroServer"; - -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; -} diff --git a/samples/ChatApp.Telemetry/MicroServer/Services/GreeterService.cs b/samples/ChatApp.Telemetry/MicroServer/Services/GreeterService.cs deleted file mode 100644 index 8cb54bac7..000000000 --- a/samples/ChatApp.Telemetry/MicroServer/Services/GreeterService.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Grpc.Core; -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace MicroServer -{ - public class GreeterService : Greeter.GreeterBase - { - private readonly ILogger _logger; - public GreeterService(ILogger logger) - { - _logger = logger; - } - - public override Task SayHello(HelloRequest request, ServerCallContext context) - { - return Task.FromResult(new HelloReply - { - Message = "Hello " + request.Name - }); - } - } -} diff --git a/samples/ChatApp.Telemetry/MicroServer/Startup.cs b/samples/ChatApp.Telemetry/MicroServer/Startup.cs deleted file mode 100644 index 62787aa24..000000000 --- a/samples/ChatApp.Telemetry/MicroServer/Startup.cs +++ /dev/null @@ -1,96 +0,0 @@ -using MagicOnion.Server; -using MagicOnion.Server.OpenTelemetry; -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.Resources; -using OpenTelemetry.Trace; - -namespace MicroServer -{ - 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. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services.AddGrpc(); - services.AddMagicOnion(options => - { - options.GlobalFilters.Add(new MagicOnionOpenTelemetryTracerFilterFactoryAttribute()); - options.GlobalStreamingHubFilters.Add(new MagicOnionOpenTelemetryStreamingTracerFilterFactoryAttribute()); - - options.GlobalFilters.Add(new ExceptionFilterFactoryAttribute()); - }) - .AddOpenTelemetry(); - - services.AddOpenTelemetryTracing(configure => - { - var exporter = this.Configuration.GetValue("UseExporter").ToLowerInvariant(); - switch (exporter) - { - case "jaeger": - configure - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MicroServer")) - .AddAspNetCoreInstrumentation() - .AddMagicOnionInstrumentation() - .AddJaegerExporter(); - services.Configure(Configuration.GetSection("Jaeger")); - break; - case "zipkin": - configure - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MicroServer")) - .AddAspNetCoreInstrumentation() - .AddMagicOnionInstrumentation() - .AddZipkinExporter(); - services.Configure(this.Configuration.GetSection("Zipkin")); - break; - default: - configure - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MicroServer")) - .AddAspNetCoreInstrumentation() - .AddMagicOnionInstrumentation() - .AddConsoleExporter(); - services.Configure(this.Configuration.GetSection("AspNetCoreInstrumentation")); - services.Configure(options => - { - options.Filter = (req) => req.Request?.Host != null; - }); - break; - } - }); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapMagicOnionService(); - endpoints.MapGrpcService(); - - 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"); - }); - }); - } - } -} diff --git a/samples/ChatApp.Telemetry/MicroServer/appsettings.Development.json b/samples/ChatApp.Telemetry/MicroServer/appsettings.Development.json deleted file mode 100644 index 17855f5d6..000000000 --- a/samples/ChatApp.Telemetry/MicroServer/appsettings.Development.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Debug", - "System": "Information", - "Grpc": "Information", - "Microsoft": "Information" - } - }, - "MagicOnion": { - "Service": { - "IsReturnExceptionStackTraceInErrorDetail": true - } - } -} diff --git a/samples/ChatApp.Telemetry/MicroServer/appsettings.json b/samples/ChatApp.Telemetry/MicroServer/appsettings.json deleted file mode 100644 index cb6023ee6..000000000 --- a/samples/ChatApp.Telemetry/MicroServer/appsettings.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Trace", - "System": "Information", - "Microsoft": "Information" - } - }, - "Kestrel": { - "EndpointDefaults": { - "Protocols": "Http2" - } - }, - "MagicOnion": { - "OpenTelemetry": { - "ServiceName": "MicroServer", - // "ExposeRpcScope": false, - "TracingTags": { - "foo": "bar" - } - } - }, - "UseExporter": "jaeger", // select "console", "zipkin", "jaeger" - "Jaeger": { - "AgentHost": "localhost", - "AgentPort": 6831 - }, - "Zipkin": { - "Endpoint": "http://localhost:9411/api/v2/spans" - }, - "AspNetCoreInstrumentation": { - "RecordException": "true" - } -} diff --git a/samples/ChatApp.Telemetry/Nuget.config b/samples/ChatApp.Telemetry/Nuget.config deleted file mode 100644 index e05d8fc6f..000000000 --- a/samples/ChatApp.Telemetry/Nuget.config +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/samples/ChatApp.Telemetry/README.md b/samples/ChatApp.Telemetry/README.md deleted file mode 100644 index ded15a662..000000000 --- a/samples/ChatApp.Telemetry/README.md +++ /dev/null @@ -1,177 +0,0 @@ -# MagicOnionSample - -This is Sample to run MagicOnion with OpenTelemetry implementation. - -## Getting started - -Option1. Run ChatApp.Server on VisualStudio, and run zipkin, jeager in docker. - -1. Run `docker-compose -f docker-compose.telemetry.yaml up`. -1. Launch `ChatApp.Server.Telemetry` from VisualStudio. -1. Launch UnityEditor for `sample/ChatApp/ChatApp.Unity`, open `ChatScene` then do any operations. -1. Access Telemery's Web UI. - -Option2. Run all ChatApp.Server, zipkin and jeager in container - -1. Run `docker-compose -f docker-compose.yaml -f docker-compose.telemetry.yaml up`. -1. Launch UnityEditor for `sample/ChatApp/ChatApp.Unity`, open `ChatScene` then do any operations. -1. Access Telemery's Web UI. - -Telemetry's Web UI address. (default send to jeager) - -* [jaeger](http://localhost:16686/) -* [zipkin](http://localhost:9411/) - * no data on default. you can switch by appsettings.json - -## Projects - -There are 3 projects for this sample. - -1. ChatApp.Server (samples/ChatApp.Telemetry/) -1. ChatApp.Shared (samples/ChatApp.Telemetry/) -1. ChatApp.Unity (samples/ChatApp/) - -and optional Server to Server - -**ChatApp.Server** is Serverside MagicOnion implementation with OpenTelemetry. - -**ChatApp.Shared** is class library shared with both ChatApp.Server and ChatApp.Unity. - -**ChatApp.Unity** is Unity App to connect ChatApp.Server. - -## ChatApp.Server - -This is Sample Serverside MagicOnion. -You can lanunch via Visual Studio 2019, open `MagicOnion.Experimental.sln` > samples > set `ChatApp.Server` project as start up and Start Debug. - -> NOTE: To avoid port conflict, stop docker/kubernetes ChatApp.Server before debug on Visual Studio. - -### Docker - -Launch ChatApp.Server and telemetry applications on docker. - -Run both ChatApp.Server and telemetry applications on container via command. - -```shell -docker-compose -f docker-compose.yaml -f docker-compose.telemetry.yaml up -``` - -If you want run just telemetry applications on Docker, and want run ChatApp.Server via VS, use following command. - -```shell -docker-compose -f docker-compose.telemetry.yaml up -``` - -Now ChatApp.Unity can access to ChatApp.Server running on docker. - -### Kubernetes - -Launch ChatApp.Server and telemetry applications on kubernetes. - -* kubectl 1.18 -* kubectx -* wsl - -> ProTips: If you are using Windows, you can use kubernetes on Docker for Windows. - -Run ChatApp on kubernetes cluster, deploy your manifests to the cluster. - -```shell -cd samples/ChatApp.Telemetry -kubectx docker-desktop - -helm repo add stable https://charts.helm.sh/stable -helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx -helm repo add prometheus-community https://prometheus-community.github.io/helm-charts -helm repo add bitnami https://charts.bitnami.com/bitnami -helm repo update - -kubectl kustomize ./k8s/common | kubectl apply -f - -helm upgrade --install nginx-ingress --namespace chatapp stable/nginx-ingress -helm upgrade --install prometheus --namespace chatapp -f ./k8s/prometheus/values.yaml stable/prometheus -helm upgrade --install grafana --namespace chatapp -f ./k8s/grafana/values.yaml stable/grafana -``` - -wait until resources are launch complete. - -```shell -kubectl rollout status deploy chatapp -n chatapp -kubectl rollout status deploy nginx-ingress-controller -n chatapp -kubectl rollout status deploy nginx-ingress-default-backend -n chatapp -kubectl rollout status deploy prometheus-server -n chatapp -kubectl rollout status deploy grafana -n chatapp -``` - -Everything is done, check kubernetes resources is up and running. - -```shell -kubens chatapp -kubectl get deploy,svc,daemonset,ingress -``` - -Now ChatApp.Unity can access to ChatApp.Server running on kubernetes. - - -## ChatApp.Unity - -Sample Clientside Unity automatically connect to MagicOnion Server on play. - -## Check Telemetry - -Metrics and trace are automatically collected for ChatApp.Server actions. -Telemetries are visualize for both Metrics and Trace info. - -### Visualize Metrics - -Prometheus collects metrics from ChatApp.Server, and Grafana visualize metrics collected via Prometheus. - -**(for k8s only) hosts file for ingress access** - -Before accesing Grafana dashboard, put `Hosts` entry to your OS, this enable your to access prometheus and grafana via ingress. - -```txt -127.0.0.1 grafana.chatapp.magiconion.local -127.0.0.1 prometheus.chatapp.magiconion.local -``` - -**access to Grafana** - -Grafana visualize ChatApp.Server metrics which collected via Prometheus. -Access to Grafana dashboard. - -> http://127.0.0.1:3000 (when using kubernetes, use http://grafana.chatapp.magiconion.local instead) - -Login user/pass: `admin`/`admin`. - -This example automatically load Grafana dashboard [MagicOnion Overview](https://grafana.com/grafana/dashboards/10584) to visualize MagicOnion metrics. - -![image](https://user-images.githubusercontent.com/3856350/83670579-5d1a9e80-a60e-11ea-9289-89a412dd5877.png) - -### Jaeger - -Jaeger visualize tracer which sent from ChatApp.Server. -Access to Jaeger dashboard. - -> http://localhost:16686/search - -Select Service `chatapp.server` and click `Find Traces` to show traces. - -![image](https://user-images.githubusercontent.com/3856350/99406491-46a09f00-2931-11eb-9861-86a1f1e04720.png) - -> NOTE: You can switch Jaeger to Zipkin via environment vairable `UseExporter=zipkin`. - -## Clean up - -Clean up your resources. - -* docker: `Ctrl + C` to stop docker-compose. -* kubernetes: Remove kubernetes resources. - -```shell -kubectx docker-desktop -helm uninstall nginx-ingress -n chatapp -helm uninstall prometheus -n chatapp -helm uninstall grafana -n chatapp -kubectl kustomize ./k8s/common | kubectl delete -f - -``` - diff --git a/samples/ChatApp.Telemetry/docker-compose.telemetry.yaml b/samples/ChatApp.Telemetry/docker-compose.telemetry.yaml deleted file mode 100644 index 37a989acd..000000000 --- a/samples/ChatApp.Telemetry/docker-compose.telemetry.yaml +++ /dev/null @@ -1,79 +0,0 @@ -version: "3" - -services: - # METRICS: OpenTelemetry-Dotnet removed Metrics Codes from main branch. Let's comment out all untill publish. - # prometheus: - # image: prom/prometheus:v2.22.2 - # volumes: - # # persistent prometheus database - # - ./docker/prometheus/data/:/prometheus - # - ./docker/prometheus/config/prometheus.yml:/etc/prometheus/prometheus.yml - # - ./docker/prometheus/config/alert.rules:/etc/prometheus/alert.rules - # ports: - # - "9090:9090" - - # alertmanager: - # image: prom/alertmanager:v0.21.0 - # volumes: - # - ./docker/alertmanager/config.yml:/etc/alertmanager/config.yml - # command: "--config.file=/etc/alertmanager/config.yml" - # ports: - # - 9093:9093 - - # # if you want monitor linux host machine, install node-exporter or use container. - # # settings detail: https://qiita.com/kanga/items/21acb042237f8a27f437 - # node-exporter: - # image: prom/node-exporter:latest - # ports: - # - 9100:9100 - # volumes: - # - /:/host:ro - # net: host - # pid: host - # command: quay.io/prometheus/node-exporter --path.rootfs /host - - # cAdvisor: - # image: google/cadvisor:latest - # volumes: - # - /var/run:/var/run:rw - # - /sys:/sys:ro - # - /var/lib/docker/:/var/lib/docker:ro - # ports: - # - 8080:8080 - - # grafana: - # build: - # context: . - # dockerfile: ./docker/grafana/Dockerfile - # depends_on: - # - prometheus - # volumes: - # # persistent grafana database - # - ./docker/grafana/data/:/var/lib/grafana - # - ./docker/grafana/conf/provisioning/:/etc/grafana/provisioning/ - # ports: - # - 3000:3000 - - # TRACING - zipkin: - image: openzipkin/zipkin:2.23 - ports: - - 9411:9411 - - jaeger: - image: jaegertracing/all-in-one:1.22 - command: --log-level=debug - ports: - - 6831:6831/udp # client post - - 16686:16686 # web - - # Server to Server - microserver: - image: cysharp/magiconion_sample_chatapp_microserver:4.3.1-1.0.0.rc4 - environment: - - DOTNET_ENVIRONMENT=Development - - UseExporter=jaeger - - Jaeger__AgentHost=jaeger - - Zipkin__Endpoint=http://zipkin:9411/api/v2/spans - ports: - - 4999:80 diff --git a/samples/ChatApp.Telemetry/docker-compose.yaml b/samples/ChatApp.Telemetry/docker-compose.yaml deleted file mode 100644 index 67b1d9e01..000000000 --- a/samples/ChatApp.Telemetry/docker-compose.yaml +++ /dev/null @@ -1,15 +0,0 @@ -version: "3" - -services: - magiconion: - image: cysharp/magiconion_sample_chatapp_telemetry:4.3.1-1.0.0.rc4 - ports: - - 5000:80 - environment: - - DOTNET_ENVIRONMENT=Development - - UseExporter=jaeger - #- UseExporter=zipkin - - Jaeger__AgentHost=jaeger - - Zipkin__Endpoint=http://zipkin:9411/api/v2/spans - - Server2ServerEndpoint=http://microserver:80 - - OTEL_LOG_LEVEL=debug diff --git a/samples/ChatApp.Telemetry/docker/.gitignore b/samples/ChatApp.Telemetry/docker/.gitignore deleted file mode 100644 index a7ea50e85..000000000 --- a/samples/ChatApp.Telemetry/docker/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -grafana/data/**/* -prometheus/data/**/* \ No newline at end of file diff --git a/samples/ChatApp.Telemetry/docker/alertmanager/config.yml b/samples/ChatApp.Telemetry/docker/alertmanager/config.yml deleted file mode 100644 index 5b50e850b..000000000 --- a/samples/ChatApp.Telemetry/docker/alertmanager/config.yml +++ /dev/null @@ -1,10 +0,0 @@ -global: - slack_api_url: "https://hooks.slack.com/services/YOUR/SLACK/IncomingWebhookEndpoint" - -route: - receiver: "slack" - -receivers: - - name: "slack" - slack_configs: - - channel: "#alerts" diff --git a/samples/ChatApp.Telemetry/docker/grafana/Dockerfile b/samples/ChatApp.Telemetry/docker/grafana/Dockerfile deleted file mode 100644 index 3bb38744b..000000000 --- a/samples/ChatApp.Telemetry/docker/grafana/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM grafana/grafana:7.3.2-ubuntu -COPY ["./docker/grafana/download_dashboards.sh", "/etc/grafana/download_dashboards.sh"] -RUN mkdir -p /var/tmp/grafana/dashboards/default && /bin/sh /etc/grafana/download_dashboards.sh diff --git a/samples/ChatApp.Telemetry/docker/grafana/conf/provisioning/dashboards/provider.yaml b/samples/ChatApp.Telemetry/docker/grafana/conf/provisioning/dashboards/provider.yaml deleted file mode 100644 index 5a940db85..000000000 --- a/samples/ChatApp.Telemetry/docker/grafana/conf/provisioning/dashboards/provider.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: 1 -providers: - - disableDeletion: false - editable: true - folder: "" - name: default - options: - path: /var/tmp/grafana/dashboards - orgId: 1 - type: file - editable: true - allowUiUpdates: true diff --git a/samples/ChatApp.Telemetry/docker/grafana/conf/provisioning/datasources/datasource.yaml b/samples/ChatApp.Telemetry/docker/grafana/conf/provisioning/datasources/datasource.yaml deleted file mode 100644 index 353e713fe..000000000 --- a/samples/ChatApp.Telemetry/docker/grafana/conf/provisioning/datasources/datasource.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: 1 -datasources: - - name: Prometheus - type: prometheus - url: http://prometheus:9090 - access: proxy - isDefault: true diff --git a/samples/ChatApp.Telemetry/docker/grafana/download_dashboards.sh b/samples/ChatApp.Telemetry/docker/grafana/download_dashboards.sh deleted file mode 100644 index b90559bd7..000000000 --- a/samples/ChatApp.Telemetry/docker/grafana/download_dashboards.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env sh -set -euf -curl -skf \ ---connect-timeout 60 \ ---max-time 60 \ --H "Accept: application/json" \ --H "Content-Type: application/json;charset=UTF-8" \ - "https://grafana.com/api/dashboards/10584/revisions/8/download" | sed 's/"datasource":[^,]*/"datasource": "Prometheus"/g'\ -> "/var/tmp/grafana/dashboards/default/magiconion-overview.json" \ No newline at end of file diff --git a/samples/ChatApp.Telemetry/docker/prometheus/config/alert.rules b/samples/ChatApp.Telemetry/docker/prometheus/config/alert.rules deleted file mode 100644 index bfd3fb589..000000000 --- a/samples/ChatApp.Telemetry/docker/prometheus/config/alert.rules +++ /dev/null @@ -1,44 +0,0 @@ -groups: - -# ref: https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/ - -- name: node_exporter - rules: - - # Alert for any instance that is unreachable for >15 seconds. - - alert: InstanceDown - expr: up == 0 - for: 15s - labels: - severity: page - annotations: - summary: "Instance {{ $labels.instance }} down" - description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes." - - # Alert for any instance that has a median request latency >1s. - - alert: APIHighRequestLatency - expr: api_http_request_latencies_second{quantile="0.5"} > 1 - for: 5m - annotations: - summary: "High request latency on {{ $labels.instance }}" - description: "{{ $labels.instance }} has a median request latency above 1s (current value: {{ $value }}s)" - - # Alert for any instance that has exceed CPU usage > 90% - - alert: cpu_used - expr: 100 * (1 - avg(rate(node_cpu{job='node',mode='idle'}[5m])) BY (instance)) > 90 - for: 5m - labels: - severity: critical - annotations: - summary: "cpu {{ $labels.instance }} used over 90%" - description: "cpu of {{ $labels.instance }} has been used over 90% for more than 5 minutes." - - # Alert for any instance that has exceed Memory usage > 90% - - alert: memory_used - expr: 100 * (1 - node_memory_MemFree{job='node'} / node_memory_MemTotal{job='node'}) > 90 - for: 5m - labels: - severity: critical - annotations: - summary: "memory {{ $labels.instance }} used over 90%" - description: "memory of {{ $labels.instance }} has been used over 90% for more than 5 minutes." diff --git a/samples/ChatApp.Telemetry/docker/prometheus/config/prometheus.yml b/samples/ChatApp.Telemetry/docker/prometheus/config/prometheus.yml deleted file mode 100644 index 49f964bb8..000000000 --- a/samples/ChatApp.Telemetry/docker/prometheus/config/prometheus.yml +++ /dev/null @@ -1,48 +0,0 @@ -# my global config -global: - scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. - evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. - # scrape_timeout is set to the global default (10s). - -# Alertmanager configuration -alerting: - alertmanagers: - - static_configs: - - targets: - - alertmanager:9093 - -# Load rules once and periodically evaluate them according to the global 'evaluation_interval'. -rule_files: - # - "first_rules.yml" - # - "second_rules.yml" - - /etc/prometheus/alert.rules - -# A scrape configuration containing exactly one endpoint to scrape: -# Here it's Prometheus itself. -scrape_configs: - # The job name is added as a label `job=` to any timeseries scraped from this config. - - job_name: "prometheus" - - # metrics_path defaults to '/metrics' - # scheme defaults to 'http'. - - static_configs: - - targets: - - prometheus:9090 - # if you want - #- node-exporter:9100 - - - job_name: "cAdvisor" - scrape_interval: 5s - static_configs: - - targets: - - "cAdvisor:8080" - - - job_name: "magiconion" - scrape_interval: 10s - static_configs: - - targets: - - "magiconion:9184" - - "host.docker.internal:9184" - labels: - app: "magiconion" diff --git a/samples/ChatApp.Telemetry/docker_build.bat b/samples/ChatApp.Telemetry/docker_build.bat deleted file mode 100644 index 9421d1430..000000000 --- a/samples/ChatApp.Telemetry/docker_build.bat +++ /dev/null @@ -1,5 +0,0 @@ -:: run from Repository Root -:: cysharp/magiconion_sample_chatapp_telemetry -:: cysharp/magiconion_sample_microserver -docker build -t chatapp_magiconion:latest -f samples/ChatApp.Telemetry/ChatApp.Server/Dockerfile . -docker build -t chatapp_microserver:latest -f samples/ChatApp.Telemetry/MicroServer/Dockerfile . diff --git a/samples/ChatApp.Telemetry/docker_push.bat b/samples/ChatApp.Telemetry/docker_push.bat deleted file mode 100644 index fd7bac9dc..000000000 --- a/samples/ChatApp.Telemetry/docker_push.bat +++ /dev/null @@ -1,11 +0,0 @@ -:: cysharp/magiconion_sample_chatapp_telemetry -:: run build first. -docker tag chatapp_magiconion:latest cysharp/magiconion_sample_chatapp_telemetry:latest -docker tag chatapp_magiconion:latest cysharp/magiconion_sample_chatapp_telemetry:4.3.1-1.0.0.rc4 -docker push cysharp/magiconion_sample_chatapp_telemetry:latest -docker push cysharp/magiconion_sample_chatapp_telemetry:4.3.1-1.0.0.rc4 - -docker tag chatapp_microserver:latest cysharp/magiconion_sample_chatapp_microserver:latest -docker tag chatapp_microserver:latest cysharp/magiconion_sample_chatapp_microserver:4.3.1-1.0.0.rc4 -docker push cysharp/magiconion_sample_chatapp_microserver:latest -docker push cysharp/magiconion_sample_chatapp_microserver:4.3.1-1.0.0.rc4 diff --git a/samples/ChatApp.Telemetry/docker_run.bat b/samples/ChatApp.Telemetry/docker_run.bat deleted file mode 100644 index c43a348a3..000000000 --- a/samples/ChatApp.Telemetry/docker_run.bat +++ /dev/null @@ -1,2 +0,0 @@ -docker-compose -f docker-compose.yaml -f docker-compose.telemetry.yaml pull -docker-compose -f docker-compose.yaml -f docker-compose.telemetry.yaml up diff --git a/samples/ChatApp.Telemetry/docker_stop.bat b/samples/ChatApp.Telemetry/docker_stop.bat deleted file mode 100644 index 629de16a0..000000000 --- a/samples/ChatApp.Telemetry/docker_stop.bat +++ /dev/null @@ -1 +0,0 @@ -docker-compose -f docker-compose.yaml -f docker-compose.telemetry.yaml down --remove-orphans --prune \ No newline at end of file diff --git a/samples/ChatApp.Telemetry/k8s/app/deployment.yaml b/samples/ChatApp.Telemetry/k8s/app/deployment.yaml deleted file mode 100644 index 117a202f2..000000000 --- a/samples/ChatApp.Telemetry/k8s/app/deployment.yaml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: chatapp - labels: - app: magiconion -spec: - replicas: 1 - selector: - matchLabels: - app: magiconion - template: - metadata: - labels: - app: magiconion - spec: - containers: - - name: chatapp - image: cysharp/magiconion_sample_chatapp_telemetry:4.0.1-1.0.0.rc2 - ports: - - containerPort: 80 - name: magiconion - - containerPort: 9184 - name: prometheus - env: - - name: DOTNET_ENVIRONMENT - value: Development - - name: MagicOnion__OpenTelemetry__MetricsExporterEndpoint - value: http://127.0.0.1:9184/metrics/ - - name: MagicOnion__OpenTelemetry__MetricsExporterHostingEndpoint - value: http://+:9184/metrics/ - - name: UseExporter - value: console - - name: Jaeger__Host - value: jaeger-agent - - name: Zipkin__Endpoint - value: http://zipkin:9411/api/v2/spans diff --git a/samples/ChatApp.Telemetry/k8s/app/kustomization.yaml b/samples/ChatApp.Telemetry/k8s/app/kustomization.yaml deleted file mode 100644 index 0b19c3c7a..000000000 --- a/samples/ChatApp.Telemetry/k8s/app/kustomization.yaml +++ /dev/null @@ -1,8 +0,0 @@ -resources: - - deployment.yaml - -# mark Deployment to be collected via Prometheus -commonAnnotations: - prometheus.io/scrape: "true" - prometheus.io/path: /metrics - prometheus.io/port: "9184" diff --git a/samples/ChatApp.Telemetry/k8s/common/kustomization.yaml b/samples/ChatApp.Telemetry/k8s/common/kustomization.yaml deleted file mode 100644 index d2dd32989..000000000 --- a/samples/ChatApp.Telemetry/k8s/common/kustomization.yaml +++ /dev/null @@ -1,6 +0,0 @@ -namespace: chatapp - -bases: - - ../namespace/ - - ../app/ - - ../service/ diff --git a/samples/ChatApp.Telemetry/k8s/grafana/values.yaml b/samples/ChatApp.Telemetry/k8s/grafana/values.yaml deleted file mode 100644 index 94d06b2b2..000000000 --- a/samples/ChatApp.Telemetry/k8s/grafana/values.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# as wsl could not mount volume, no persistence -ingress: - enabled: true - hosts: - - grafana.chatapp.magiconion.local - -datasources: - datasources.yaml: - apiVersion: 1 - datasources: - - name: Prometheus - type: prometheus - url: http://prometheus-server.chatapp.svc.cluster.local - access: proxy - isDefault: true - -dashboardProviders: - dashboardproviders.yaml: - apiVersion: 1 - providers: - - name: "default" - orgId: 1 - folder: "" - type: file - disableDeletion: false - editable: true - options: - path: /var/lib/grafana/dashboards - -dashboards: - default: - kube-cluster: - gnetId: 6417 - revision: 1 - datasource: Prometheus - magiconion-overview: - gnetId: 10584 - revision: 9 - datasource: Prometheus - -adminPassword: admin diff --git a/samples/ChatApp.Telemetry/k8s/namespace/kustomization.yaml b/samples/ChatApp.Telemetry/k8s/namespace/kustomization.yaml deleted file mode 100644 index 736967b1a..000000000 --- a/samples/ChatApp.Telemetry/k8s/namespace/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: - - namespace.yaml diff --git a/samples/ChatApp.Telemetry/k8s/namespace/namespace.yaml b/samples/ChatApp.Telemetry/k8s/namespace/namespace.yaml deleted file mode 100644 index f8f1faeb2..000000000 --- a/samples/ChatApp.Telemetry/k8s/namespace/namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: chatapp diff --git a/samples/ChatApp.Telemetry/k8s/prometheus/values.yaml b/samples/ChatApp.Telemetry/k8s/prometheus/values.yaml deleted file mode 100644 index b6f1956cd..000000000 --- a/samples/ChatApp.Telemetry/k8s/prometheus/values.yaml +++ /dev/null @@ -1,11 +0,0 @@ -server: - ingress: - enabled: true - hosts: - - prometheus.chatapp.magiconion.local - retention: "12h" -alertmanager: - ingress: - enabled: false -pushgateway: - enabled: false diff --git a/samples/ChatApp.Telemetry/k8s/service/kustomization.yaml b/samples/ChatApp.Telemetry/k8s/service/kustomization.yaml deleted file mode 100644 index b2d577597..000000000 --- a/samples/ChatApp.Telemetry/k8s/service/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: - - service.yaml diff --git a/samples/ChatApp.Telemetry/k8s/service/service.yaml b/samples/ChatApp.Telemetry/k8s/service/service.yaml deleted file mode 100644 index 572025c06..000000000 --- a/samples/ChatApp.Telemetry/k8s/service/service.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: chatapp-svc -spec: - selector: - app: magiconion - type: LoadBalancer - ports: - - protocol: TCP - port: 5000 - targetPort: magiconion ---- -apiVersion: v1 -kind: Service -metadata: - name: chatapp-prometheus-svc -spec: - selector: - app: magiconion - ports: - - protocol: TCP - port: 9184 - targetPort: prometheus diff --git a/src/MagicOnion.Server.OpenTelemetry/Internal/MagicOnionInstrumentation.cs b/src/MagicOnion.Server.OpenTelemetry/Internal/MagicOnionInstrumentation.cs deleted file mode 100644 index fb0fcb7fc..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/Internal/MagicOnionInstrumentation.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Reflection; - -namespace MagicOnion.Server.OpenTelemetry.Internal -{ - internal static class MagicOnionInstrumentation - { - /// - /// The assembly name. - /// - internal static readonly AssemblyName AssemblyName = typeof(MagicOnionInstrumentation).Assembly.GetName(); - - /// - /// The activity source name. - /// - internal static readonly string ActivitySourceName = AssemblyName.Name; - - /// - /// The version. - /// - internal static readonly Version Version = AssemblyName.Version; - } -} diff --git a/src/MagicOnion.Server.OpenTelemetry/Internal/MagicOnionTelemetryConstants.cs b/src/MagicOnion.Server.OpenTelemetry/Internal/MagicOnionTelemetryConstants.cs deleted file mode 100644 index 013912938..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/Internal/MagicOnionTelemetryConstants.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace MagicOnion.Server.OpenTelemetry.Internal -{ - internal static class MagicOnionTelemetryConstants - { - public const string ServiceContextItemKeyTrace = ".TraceContext"; - } -} diff --git a/src/MagicOnion.Server.OpenTelemetry/Internal/OpenTelemetryHelper.cs b/src/MagicOnion.Server.OpenTelemetry/Internal/OpenTelemetryHelper.cs deleted file mode 100644 index 6f7b69f5e..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/Internal/OpenTelemetryHelper.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Grpc.Core; - -namespace MagicOnion.Server.OpenTelemetry.Internal -{ - internal static class OpenTelemetryHelper - { - /// - /// Convert gRPC StatusCode to OpenTelemetry Status. - /// - /// spec: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/api.md#set-status - /// - /// - internal static global::OpenTelemetry.Trace.Status GrpcToOpenTelemetryStatus(StatusCode code) - { - return code switch - { - StatusCode.OK => global::OpenTelemetry.Trace.Status.Ok, - _ => global::OpenTelemetry.Trace.Status.Error, - }; - } - } -} \ No newline at end of file diff --git a/src/MagicOnion.Server.OpenTelemetry/Internal/PropagatorExtensions.cs b/src/MagicOnion.Server.OpenTelemetry/Internal/PropagatorExtensions.cs deleted file mode 100644 index cf0aa1d28..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/Internal/PropagatorExtensions.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Diagnostics; -using OpenTelemetry.Context.Propagation; -using Grpc.Core; -using System.Collections.Generic; -using System.Linq; -using OpenTelemetry; - -// ReSharper disable once CheckNamespace - -namespace MagicOnion.Server.OpenTelemetry.Internal -{ - internal static class PropagatorExtensions - { - /// - /// Injects the context into a carrier - /// - /// - /// - /// - public static void Inject(this TextMapPropagator propagator, PropagationContext context, CallOptions carrier) - { - static void SetMetadata(Metadata metadata, string key, string value) => metadata.Add(new Metadata.Entry(key, value)); - propagator.Inject(context, carrier.Headers, SetMetadata); - } - - /// - /// Extract the context from a carrier - /// - /// - /// - /// - /// - public static PropagationContext Extract(this TextMapPropagator propagator, ActivityContext? activityContext, Metadata carrier) - { - static IEnumerable GetMetadata(Metadata metadata, string key) - { - for (var i = 0; i < metadata.Count; i++) - { - var entry = metadata[i]; - if (entry.Key.Equals(key)) - { - return new string[1] { entry.Value }; - } - } - - return Enumerable.Empty(); - } - return propagator.Extract(new PropagationContext(activityContext ?? default, Baggage.Current), carrier, GetMetadata); - } - } -} \ No newline at end of file diff --git a/src/MagicOnion.Server.OpenTelemetry/Internal/SemanticConventions.cs b/src/MagicOnion.Server.OpenTelemetry/Internal/SemanticConventions.cs deleted file mode 100644 index 0b1eaf195..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/Internal/SemanticConventions.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace MagicOnion.Server.OpenTelemetry.Internal -{ - /// - /// OpenTelemetry Tag Keys - /// - internal static class SemanticConventions - { - // tag spec: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/rpc.md#grpc - public const string AttributeServiceName = "service.name"; - public const string AttributeException = "exception"; - - public const string AttributeHttpHost = "http.host"; - public const string AttributeHttpUrl = "http.url"; - public const string AttributeHttpUserAgent = "http.user_agent"; - - public const string AttributeRpcGrpcMethod = "rpc.grpc.method"; - public const string AttributeRpcGrpcStatusCode = "rpc.grpc.status_code"; - public const string AttributeRpcGrpcStatusDetail = "rpc.grpc.status_detail"; - public const string AttributeRpcSystem = "rpc.system"; - public const string AttributeRpcService = "rpc.service"; - public const string AttributeRpcMethod = "rpc.method"; - - public const string AttributeMessageId = "message.id"; - public const string AttributeMessageCompressedSize = "message.compressed_size"; - public const string AttributeMessageUncompressedSize = "message.uncompressed_size"; - - public const string AttributeMagicOnionPeerName = "magiconion.peer.ip"; - public const string AttributeMagicOnionAuthEnabled = "magiconion.auth.enabled"; - public const string AttributeMagicOnionAuthPeerAuthenticated = "magiconion.auth.peer_authenticated"; - } -} diff --git a/src/MagicOnion.Server.OpenTelemetry/MagicOnion.Server.OpenTelemetry.csproj b/src/MagicOnion.Server.OpenTelemetry/MagicOnion.Server.OpenTelemetry.csproj deleted file mode 100644 index 303e6d85d..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/MagicOnion.Server.OpenTelemetry.csproj +++ /dev/null @@ -1,40 +0,0 @@ - - - - net6.0;net7.0 - Library - False - true - ..\MagicOnion\opensource.snk - true - true - True - 1701;1702;1705;1591 - NON_UNITY - - latest - - - MagicOnion.Server.OpenTelemetry - Telemetry Extensions of MagicOnion. - $(PackageTags);OpenTelemetry - - preview-1.3.2 - - - - - - - - - - - - - - - - - - diff --git a/src/MagicOnion.Server.OpenTelemetry/MagicOnionActivitySources.cs b/src/MagicOnion.Server.OpenTelemetry/MagicOnionActivitySources.cs deleted file mode 100644 index 4cbf457c5..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/MagicOnionActivitySources.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; - -namespace MagicOnion.Server.OpenTelemetry -{ - /// - /// ActivitySource for MagicOnion OpenTelemetry - /// - /// Avoid directly register ActivitySource to Singleton for easier identification. - public class MagicOnionActivitySources - { - private readonly ActivitySource activitySource; - - /// - /// used for MagicOnion - /// - public ActivitySource Current => activitySource; - - public MagicOnionActivitySources(ActivitySource activitySource) - { - this.activitySource = activitySource ?? throw new ArgumentNullException(nameof(activitySource)); - } - } -} diff --git a/src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryClientFilter.cs b/src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryClientFilter.cs deleted file mode 100644 index 8b72dbe1d..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryClientFilter.cs +++ /dev/null @@ -1,90 +0,0 @@ -using Grpc.Core; -using MagicOnion.Client; -using MagicOnion.Server.OpenTelemetry.Internal; -using OpenTelemetry; -using OpenTelemetry.Context.Propagation; -using System; -using System.Diagnostics; -using System.Threading.Tasks; - -namespace MagicOnion.Server.OpenTelemetry -{ - // note: move package to MagicOnion.Client.OpenTelemetry? - /// - /// Collect OpenTelemetry Tracer with Client filter (Unary). - /// - public class MagicOnionOpenTelemetryClientFilter : IClientFilter - { - readonly ActivitySource source; - readonly MagicOnionOpenTelemetryOptions options; - - public MagicOnionOpenTelemetryClientFilter(ActivitySource activitySource, MagicOnionOpenTelemetryOptions options) - { - this.source = activitySource; - this.options = options; - } - - public async ValueTask SendAsync(RequestContext context, Func> next) - { - var rpcService = context.MethodPath.Split('/')[0]; - using var rpcScope = new ClientRpcScope(rpcService, context.MethodPath, context, source, options); - rpcScope.SetTags(options.TracingTags); - - try - { - var response = await next(context); - - rpcScope.Complete(); - return response; - } - catch (Exception ex) - { - rpcScope.CompleteWithException(ex); - throw; - } - finally - { - rpcScope.RestoreParentActivity(); - } - } - } - - internal class ClientRpcScope : RpcScope - { - public ClientRpcScope(string rpcService, string rpcMethod, RequestContext context, ActivitySource source, MagicOnionOpenTelemetryOptions options) - : base(rpcService, rpcMethod, options.ServiceName) - { - // capture the current activity - this.ParentActivity = Activity.Current; - - if (!source.HasListeners()) - return; - - var rpcActivity = source.StartActivity( - context.MethodPath.TrimStart('/'), - ActivityKind.Client, - ParentActivity == default ? default : ParentActivity.Context); - - if (rpcActivity == null) - return; - - var callOptions = context.CallOptions; - if (callOptions.Headers == null) - { - callOptions = callOptions.WithHeaders(new Metadata()); - } - - SetActivity(rpcActivity); - - Propagators.DefaultTextMapPropagator.Inject(new PropagationContext(rpcActivity.Context, Baggage.Current), callOptions); - } - - /// - /// Restores the parent activity. - /// - public void RestoreParentActivity() - { - Activity.Current = this.ParentActivity; - } - } -} diff --git a/src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryOption.cs b/src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryOption.cs deleted file mode 100644 index c531c0d3d..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryOption.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; - -namespace MagicOnion.Server.OpenTelemetry -{ - /// - /// OpenTelemetry Options to inject Application Information - /// - public class MagicOnionOpenTelemetryOptions - { - /// - /// ServiceName for Tracer. Especially Zipkin use service.name tag to identify service name. - /// - /// input to tag `service.name` - public string ServiceName { get; set; } - - /// - /// Expose RpsScope to the ServiceContext.Items. RpsScope key begin with .TraceContext - /// - public bool ExposeRpcScope { get; set; } = true; - - /// - /// Application specific OpenTelemetry Tracing tags - /// - public Dictionary TracingTags { get; set; } = new Dictionary(); - } -} \ No newline at end of file diff --git a/src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryTracerFilterAttributes.cs b/src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryTracerFilterAttributes.cs deleted file mode 100644 index 9df84b0dc..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/MagicOnionOpenTelemetryTracerFilterAttributes.cs +++ /dev/null @@ -1,205 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading.Tasks; -using Grpc.Core; -using MagicOnion.Server.Filters; -using MagicOnion.Server.Hubs; -using MagicOnion.Server.OpenTelemetry.Internal; -using Microsoft.Extensions.DependencyInjection; -using OpenTelemetry; -using OpenTelemetry.Context.Propagation; - -namespace MagicOnion.Server.OpenTelemetry -{ - /// - /// Collect OpenTelemetry Tracer with Server filter (Unary). - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] - public class MagicOnionOpenTelemetryTracerFilterFactoryAttribute : Attribute, IMagicOnionFilterFactory - { - public int Order { get; set; } - - MagicOnionFilterAttribute IMagicOnionFilterFactory.CreateInstance(IServiceProvider serviceProvider) - { - var activitySource = serviceProvider.GetService(); - var options = serviceProvider.GetService(); - return new MagicOnionOpenTelemetryTracerFilterAttribute(activitySource.Current, options); - } - } - - internal class MagicOnionOpenTelemetryTracerFilterAttribute : MagicOnionFilterAttribute - { - readonly ActivitySource source; - readonly MagicOnionOpenTelemetryOptions options; - - public MagicOnionOpenTelemetryTracerFilterAttribute(ActivitySource activitySource, MagicOnionOpenTelemetryOptions telemetryOption) - { - this.source = activitySource; - this.options = telemetryOption; - } - - public override async ValueTask Invoke(ServiceContext context, Func next) - { - using var rpcScope = new ServerRpcScope(context.ServiceType.Name, context.CallContext.Method.TrimStart('/'), context.CallContext, source, options); - - if (options.ExposeRpcScope) - { - context.SetTraceScope(rpcScope); - } - - rpcScope.SetTags(options.TracingTags); - rpcScope.SetTags(new Dictionary - { - { SemanticConventions.AttributeRpcGrpcMethod, context.MethodType.ToString() }, - { SemanticConventions.AttributeHttpHost, context.CallContext.Host}, - { SemanticConventions.AttributeHttpUrl, context.CallContext.Host + context.CallContext.Method }, - { SemanticConventions.AttributeHttpUserAgent, context.CallContext.RequestHeaders.GetValue("user-agent")}, - { SemanticConventions.AttributeMessageId, context.ContextId.ToString()}, - { SemanticConventions.AttributeMagicOnionPeerName, context.CallContext.Peer}, - { SemanticConventions.AttributeMagicOnionAuthEnabled, (!string.IsNullOrEmpty(context.CallContext.AuthContext.PeerIdentityPropertyName)).ToString()}, - { SemanticConventions.AttributeMagicOnionAuthPeerAuthenticated, context.CallContext.AuthContext.IsPeerAuthenticated.ToString()}, - }); - - try - { - await next(context); - - OpenTelemetryHelper.GrpcToOpenTelemetryStatus(context.CallContext.Status.StatusCode); - rpcScope.Complete(context.CallContext.Status.StatusCode); - } - catch (Exception ex) - { - rpcScope.SetTags(new Dictionary - { - { SemanticConventions.AttributeRpcGrpcStatusCode, ((long)context.CallContext.Status.StatusCode).ToString()}, - { SemanticConventions.AttributeRpcGrpcStatusDetail, context.CallContext.Status.Detail}, - }); - rpcScope.CompleteWithException(ex); - throw; - } - finally - { - rpcScope.RestoreParentActivity(); - } - } - } - - /// - /// Collect OpenTelemetry Tracer with Server filter (StreamingHub). - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] - public class MagicOnionOpenTelemetryStreamingTracerFilterFactoryAttribute : Attribute, IMagicOnionFilterFactory - { - public int Order { get; set; } - - StreamingHubFilterAttribute IMagicOnionFilterFactory.CreateInstance(IServiceProvider serviceProvider) - { - var activitySource = serviceProvider.GetService(); - var options = serviceProvider.GetService(); - return new MagicOnionOpenTelemetryStreamingTracerFilterAttribute(activitySource.Current, options); - } - } - - internal class MagicOnionOpenTelemetryStreamingTracerFilterAttribute : StreamingHubFilterAttribute - { - readonly ActivitySource source; - readonly MagicOnionOpenTelemetryOptions options; - - public MagicOnionOpenTelemetryStreamingTracerFilterAttribute(ActivitySource activitySource, MagicOnionOpenTelemetryOptions telemetryOption) - { - this.source = activitySource; - this.options = telemetryOption; - } - - public override async ValueTask Invoke(StreamingHubContext context, Func next) - { - using var rpcScope = new ServerRpcScope(context.ServiceContext.ServiceType.Name, context.Path, context.ServiceContext.CallContext, source, options); - - if (options.ExposeRpcScope) - { - context.SetTraceScope(rpcScope); - } - - rpcScope.SetTags(options.TracingTags); - rpcScope.SetTags(new Dictionary - { - { SemanticConventions.AttributeRpcGrpcMethod, context.ServiceContext.MethodType.ToString() }, - { SemanticConventions.AttributeHttpHost, context.ServiceContext.CallContext.Host}, - { SemanticConventions.AttributeHttpUrl, context.ServiceContext.CallContext.Host + "/" + context.Path }, - { SemanticConventions.AttributeHttpUserAgent, context.ServiceContext.CallContext.RequestHeaders.GetValue("user-agent")}, - { SemanticConventions.AttributeMessageId, context.ServiceContext.ContextId.ToString()}, - { SemanticConventions.AttributeMessageUncompressedSize, context.Request.Length.ToString()}, - { SemanticConventions.AttributeMagicOnionPeerName, context.ServiceContext.CallContext.Peer}, - { SemanticConventions.AttributeMagicOnionAuthEnabled, (!string.IsNullOrEmpty(context.ServiceContext.CallContext.AuthContext.PeerIdentityPropertyName)).ToString()}, - { SemanticConventions.AttributeMagicOnionAuthPeerAuthenticated, context.ServiceContext.CallContext.AuthContext.IsPeerAuthenticated.ToString()}, - }); - - try - { - await next(context); - - OpenTelemetryHelper.GrpcToOpenTelemetryStatus(context.ServiceContext.CallContext.Status.StatusCode); - rpcScope.Complete(context.ServiceContext.CallContext.Status.StatusCode); - } - catch (Exception ex) - { - rpcScope.SetTags(new Dictionary - { - { SemanticConventions.AttributeRpcGrpcStatusCode, ((long)context.ServiceContext.CallContext.Status.StatusCode).ToString()}, - { SemanticConventions.AttributeRpcGrpcStatusDetail, context.ServiceContext.CallContext.Status.Detail}, - }); - rpcScope.CompleteWithException(ex); - throw; - } - finally - { - rpcScope.RestoreParentActivity(); - } - } - } - - internal class ServerRpcScope : RpcScope - { - public ServerRpcScope(string rpcService, string rpcMethod, ServerCallContext context, ActivitySource source, MagicOnionOpenTelemetryOptions options) - : base(rpcService, rpcMethod, options.ServiceName) - { - // activity may be null if "no one is listening" or "all listener returns ActivitySamplingResult.None in Sample or SampleUsingParentId callback". - if (!source.HasListeners()) - return; - - var currentContext = Activity.Current?.Context; - - // Extract the SpanContext, if any from the headers - var metadata = context.RequestHeaders; - if (metadata != null) - { - var propagationContext = Propagators.DefaultTextMapPropagator.Extract(currentContext, metadata); - if (propagationContext.ActivityContext.IsValid()) - { - currentContext = propagationContext.ActivityContext; - } - if (propagationContext.Baggage != default) - { - Baggage.Current = propagationContext.Baggage; - } - } - - // span name should be `$package.$service/$method` but MagicOnion has no $package. - var rpcActivity = source.StartActivity( - rpcMethod, - ActivityKind.Server, - currentContext ?? default); - - SetActivity(rpcActivity); - } - - /// - /// Restores the parent activity. - /// - public void RestoreParentActivity() - { - Activity.Current = this.ParentActivity; - } - } -} \ No newline at end of file diff --git a/src/MagicOnion.Server.OpenTelemetry/MagicOnionServerBuilderExtensions.cs b/src/MagicOnion.Server.OpenTelemetry/MagicOnionServerBuilderExtensions.cs deleted file mode 100644 index d53a00c4f..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/MagicOnionServerBuilderExtensions.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Diagnostics; -using MagicOnion.Server.OpenTelemetry.Internal; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; - -namespace MagicOnion.Server.OpenTelemetry -{ - /// MagicOnion extensions for Microsoft.Extensions.Hosting classes - public static class MagicOnionServerBuilderExtensions - { - /// - /// Configures OpenTelemetry to listen for the Activities created by the MagicOnion Filter. - /// - /// - /// - /// - public static IMagicOnionServerBuilder AddOpenTelemetry(this IMagicOnionServerBuilder builder, string overrideServiceName = "") - { - var options = CreateDefaultOptions(builder, overrideServiceName); - return AddOpenTelemetry(builder, options); - } - - /// - /// Configures OpenTelemetry to listen for the Activities created by the MagicOnion Filter. - /// - /// - /// - /// - public static IMagicOnionServerBuilder AddOpenTelemetry(this IMagicOnionServerBuilder builder, MagicOnionOpenTelemetryOptions options) - { - if (options == null) throw new ArgumentNullException(nameof(options)); - if (builder == null) throw new ArgumentNullException(nameof(builder)); - - // listen ActivitySource - var activitySource = new ActivitySource(MagicOnionInstrumentation.ActivitySourceName, MagicOnionInstrumentation.Version.ToString()); - - // DI - builder.Services.TryAddSingleton(options); - builder.Services.TryAddSingleton(new MagicOnionActivitySources(activitySource)); - - return builder; - } - - /// - /// Generate MagicOnionTelemetryOptions and configure if configuration exists. - /// - /// - /// - /// - private static MagicOnionOpenTelemetryOptions CreateDefaultOptions(IMagicOnionServerBuilder builder, string overrideServiceName) - { - const string configKey = "MagicOnion:OpenTelemetry"; - var serviceProvider = builder.Services.BuildServiceProvider(); - var config = serviceProvider.GetService(); - var options = new MagicOnionOpenTelemetryOptions(); - - var section = config.GetSection(configKey); - if (section == null) - throw new ArgumentOutOfRangeException($"{configKey} not exists in {nameof(IConfiguration)}."); - section.Bind(options); - if (!string.IsNullOrEmpty(overrideServiceName)) - { - options.ServiceName = overrideServiceName; - } - return options; - } - } -} diff --git a/src/MagicOnion.Server.OpenTelemetry/README.md b/src/MagicOnion.Server.OpenTelemetry/README.md deleted file mode 100644 index 9a4283037..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/README.md +++ /dev/null @@ -1,363 +0,0 @@ -# MagicOnion.Server.OpenTelemetry - -**Supported OpenTelemetry-dotnet version: [0.5.0-beta.2](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/0.5.0-beta)** - -MagicOnion offer OpenTelemetry support with `MagicOnion.OpenTelemetry` package. -Let's see overview and how to try on localhost. - -* overview -* try sample app for OpenTelemetry -* hands on -* try visualization on localhost -* metrics customization -* implement your own metrics - -## Overview - -MagicOnion.OpenTelemetry is implementation of [open\-telemetry/opentelemetry\-dotnet: OpenTelemetry \.NET SDK](https://github.com/open-telemetry/opentelemetry-dotnet), so you can use any OpenTelemetry exporter, like [Prometheus](https://prometheus.io/), [StackDriver](https://cloud.google.com/stackdriver/pricing), [Zipkin](https://zipkin.io/) and others. - -You can collect telemetry and use exporter on MagicOnion Serverside. - -## Try sample app for OpenTelemetry - -Try OpenTelemetry with ChatApp sample app. - -goto [samples/ChatApp](https://github.com/Cysharp/MagicOnion/tree/master/samples/ChatApp) and see README. - -## Hands on - -What you need to do for Telemetry is followings. - -* add reference to the MagicOnion.OpenTelemetry. -* configuration for OpenTelemery. -* configure DI for OpenTelemetry-dotnet. -* (optional) add PrometheusExporterMetricsService for prometheus exporter. -* configure filters/logger for telemetry. -* try your telemetry. - -Let's follow the steps. - -### Add reference to the MagicOnion.OpenTelemetry - -Add [MagicOnion.OpenTelemetry](https://www.nuget.org/packages/MagicOnion.OpenTelemetry) nuget package to your MagicOnion server project. - -```shell -dotnet add package MagicOnion.OpenTelemetry -``` - -You are ready to configure MagicOnion Filter & Logger for OpenTelemetry. - -### Configuration for OpenTelemetry - -MagicOnion.OpenTelemetry offers configuration binder. -Default configuration key is `MagicOnion:OpenTelemery`. - -* `ServiceName`: Configure Tracer ServiceName -* `MetricsExporterEndpoint`: Configure your metrics exporter's push endpoint. (e.g. Prometheus) -* `TracerExporterEndpoint`: Configure your tracer exporter's push endpoint. (e.g. Zipkin) - -```json -{ - "MagicOnion": { - "OpenTelemetry": { - "ServiceName": "ChatApp.Server", - "MetricsExporterEndpoint": "http://127.0.0.1:9184/metrics/", - "TracerExporterEndpoint": "http://127.0.0.1:9411/api/v2/spans" - } - } -} -``` - -### Configure DI for OpenTelemetry-dotnet - -MagicOnion.OpenTelemetry offers extensions for IServiceCollection, `AddMagicOnionOpenTelemetry`. -Register `MagicOnionOpenTelemetryOptions`, `Action` and `Action` to configure MeterFactory & TracerFactory. - -> TIPS: `AddMagicOnionOpenTelemetry` register MagicOnionOpenTelemetryOptions, MeterFactory and TracerFactory as Singleton for you. - -```csharp -await MagicOnionHost.CreateDefaultBuilder() - .UseMagicOnion() - .ConfigureServices((hostContext, services) => - { - services.AddMagicOnionOpenTelemetry((options, meterOptions) => - { - // open-telemetry with Prometheus exporter - meterOptions.MetricExporter = new PrometheusExporter(new PrometheusExporterOptions() { Url = options.MetricsExporterEndpoint }); - }, - (options, provider, tracerBuilder) => - { - // open-telemetry with Zipkin exporter - tracerBuilder.AddZipkinExporter(o => - { - o.ServiceName = "MyApp"; - o.Endpoint = new Uri(options.TracerExporterEndpoint); - }); - // ConsoleExporter will show current tracer activity - tracerBuilder.AddConsoleExporter(); - }); - }) -``` - - -### (Optional) Add PrometheusExporterMetricsService for prometheus exporter. - -If you use Prometheus Exporter and require Prometheus Server to recieve pull request from Prometheus Collector Server, see sample IHostedService implementation. - -> [PrometheusExporterMetricsService](https://github.com/Cysharp/MagicOnion/blob/master/samples/ChatApp/ChatApp.Server.Telemery/PrometheusExporterMetricsService.cs) -> [PrometheusExporterMetricsHttpServerCustom](https://github.com/Cysharp/MagicOnion/blob/master/samples/ChatApp/ChatApp.Server.Telemery/PrometheusExporterMetricsHttpServerCustom.cs) - -```csharp -# Program.cs -.ConfigureServices((hostContext, services) => -{ - services.AddMagicOnionOpenTelemetry((options, meterOptions) => - { - // your metrics exporter implementation. - meterOptions.MetricExporter = new PrometheusExporter(new PrometheusExporterOptions() { Url = options.MetricsExporterEndpoint }); - }, - (options, tracerBuilder) => - { - // your tracer exporter implementation. - }); - // host your prometheus metrics server - services.AddHostedService(); -}) -``` - -### Configure filters/logger for telemetry - -You can collect MagicOnion metrics with `MagicOnionFilter`. MagicOnion.OpenTelemetry offers `OpenTelemetryCollectorFilter` and `OpenTelemetryHubCollectorFilter` for you. -You can trace Unary and StreamingHub API by register MagicOnionLogger on each hook point prepared via `IMagicOnionLogger`. MagicOnion.OpenTelemetry offers `OpenTelemetryCollectorLogger` for you. - -```csharp -await MagicOnionHost.CreateDefaultBuilder() - .UseMagicOnion() - .ConfigureServices((hostContext, services) => - { - services.AddMagicOnionOpenTelemetry((options, meterOptions) => - { - // your metrics exporter implementation. - }, - (options, tracerBuilder) => - { - // your tracer exporter implementation. - }); - }) - .ConfigureServices((hostContext, services) => - { - var meterFactory = services.BuildServiceProvider().GetService(); - services.Configure(options => - { - options.Service.GlobalFilters.Add(new OpenTelemetryCollectorFilterFactoryAttribute()); - options.Service.GlobalStreamingHubFilters.Add(new OpenTelemetryHubCollectorFilterFactoryAttribute()); - options.Service.MagicOnionLogger = new OpenTelemetryCollectorLogger(meterProvider); - }); - }) - .RunConsoleAsync(); -``` - -### Try your telemetry - -All implementation is done, let's Debug run MagicOnion and confirm you can see metrics and tracer. - -SampleApp `samples/ChatApp.Telemetry/ChatApp.Server` offers sample for Prometheus Metrics exporter and Zipkin Tracer exporter. - -Run Zipkin on Docker to recieve tracer from ChatApp.Server.Telemery. - -```shell -cd samples/ChatApp.Telemetry -docker-compose -f docker-compose.telemetry.yaml up -``` - -* Prometheus metrics wlll show on http://localhost:9184/metrics. -* Zipkin tracer will show on http://localhost:9411/zipkin/ - -Zipkin tracer will be shown as below. - -![image](https://user-images.githubusercontent.com/3856350/82529117-3b80d800-9b75-11ea-9e70-4bf15411becc.png) - -Prometheus Metrics will be shown as like follows. - -```txt -# HELP magiconion_buildservicedefinition_duration_millisecondsMagicOnionmagiconion_buildservicedefinition_duration_milliseconds -# TYPE magiconion_buildservicedefinition_duration_milliseconds summary -magiconion_buildservicedefinition_duration_milliseconds_sum{method="EndBuildServiceDefinition"} 0 1591066746669 -magiconion_buildservicedefinition_duration_milliseconds_count{method="EndBuildServiceDefinition"} 0 1591066746669 -magiconion_buildservicedefinition_duration_milliseconds{method="EndBuildServiceDefinition",quantile="0"} 1.7976931348623157E+308 1591066746669 -magiconion_buildservicedefinition_duration_milliseconds{method="EndBuildServiceDefinition",quantile="1"} -1.7976931348623157E+308 1591066746669 -# HELP magiconion_broadcast_request_sizeMagicOnionmagiconion_broadcast_request_size -# TYPE magiconion_broadcast_request_size summary -magiconion_broadcast_request_size_sum{GroupName="SampleRoom"} 0 1591066746669 -magiconion_broadcast_request_size_count{GroupName="SampleRoom"} 0 1591066746669 -magiconion_broadcast_request_size{GroupName="SampleRoom",quantile="0"} 9.223372036854776E+18 1591066746669 -magiconion_broadcast_request_size{GroupName="SampleRoom",quantile="1"} -9.223372036854776E+18 1591066746669 -# HELP magiconion_streaminghub_elapsed_millisecondsMagicOnionmagiconion_streaminghub_elapsed_milliseconds -# TYPE magiconion_streaminghub_elapsed_milliseconds summary -magiconion_streaminghub_elapsed_milliseconds_sum{methodType="DuplexStreaming"} 0 1591066746669 -magiconion_streaminghub_elapsed_milliseconds_count{methodType="DuplexStreaming"} 0 1591066746669 -magiconion_streaminghub_elapsed_milliseconds{methodType="DuplexStreaming",quantile="0"} 1.7976931348623157E+308 1591066746669 -magiconion_streaminghub_elapsed_milliseconds{methodType="DuplexStreaming",quantile="1"} -1.7976931348623157E+308 1591066746670 -# HELP magiconion_unary_response_sizeMagicOnionmagiconion_unary_response_size -# TYPE magiconion_unary_response_size summary -magiconion_unary_response_size_sum{method="/IChatService/GenerateException"} 0 1591066746669 -magiconion_unary_response_size_count{method="/IChatService/GenerateException"} 0 1591066746669 -magiconion_unary_response_size{method="/IChatService/GenerateException",quantile="0"} 9.223372036854776E+18 1591066746669 -magiconion_unary_response_size{method="/IChatService/GenerateException",quantile="1"} -9.223372036854776E+18 1591066746669 -magiconion_unary_response_size_sum{methodType="Unary"} 0 1591066746669 -magiconion_unary_response_size_count{methodType="Unary"} 0 1591066746669 -magiconion_unary_response_size{methodType="Unary",quantile="0"} 9.223372036854776E+18 1591066746669 -magiconion_unary_response_size{methodType="Unary",quantile="1"} -9.223372036854776E+18 1591066746669 -``` - -You may find `MagicOnion/measure/BuildServiceDefinition{MagicOnion_keys_Method="EndBuildServiceDefinition",quantile="0"}` are collected, and other metrics will shown as #HELP. -They will export when Unary/StreamingHub request is comming. - -### Tips - -* Want insert your own tag to default metrics? - -Add defaultTags when register `OpenTelemetryCollectorLogger`. - -* Want replace magiconion metrics prefix to my magiconion metrics? - -Set metricsPrefix when register `OpenTelemetryCollectorLogger`. -If you pass `yourprefix`, then metrics prefix will change to followings. - -``` -yourprefix_buildservicedefinition_duration_milliseconds_sum{method="EndBuildServiceDefinition"} 66.7148 1591066185908 -``` - -* Want contain `version` tag to your metrics? - -Add version when register `OpenTelemetryCollectorLogger`. - -This should output like follows, however current opentelemetry-dotnet Prometheus exporter not respect version tag. - -``` -magiconion_buildservicedefinition_duration_milliseconds_sum{method="EndBuildServiceDefinition",version="1.0.0"} 66.7148 1591066185908 -``` - -## Implement your own trace - -Here's Zipkin Tracer sample with MagicOnion.OpenTelemetry. - -![image](https://user-images.githubusercontent.com/3856350/91792704-1a8a5180-ec51-11ea-84d6-b05b201eda7b.png) - -Let's see example trace. -MagicOnion.OpenTelemetry automatically trace each StreamingHub and Unary request. - -![image](https://user-images.githubusercontent.com/3856350/91793243-9e910900-ec52-11ea-8d2a-a10b6fbc93fe.png) - -If you want add your own application trace, use `ActivitySource` which automatically injected by MagicOnion. - -![image](https://user-images.githubusercontent.com/3856350/91793396-09424480-ec53-11ea-8c93-a21d1590d06a.png) - -Code sample. - -```csharp -public class ChatHub : StreamingHubBase, IChatHub -{ - private ActivitySource activitySource; - - public ChatHub(ActivitySource activitySource) - { - this.activitySource = activitySource; - } - - public async Task JoinAsync(JoinRequest request) - { - // your logic - - // Trace database operation dummy. - using (var activity = activitySource.StartActivity("db:room/insert", ActivityKind.Internal)) - { - // this is sample. use orm or any safe way. - activity.SetTag("table", "rooms"); - activity.SetTag("query", $"INSERT INTO rooms VALUES (0, '{request.RoomName}', '{request.UserName}', '1');"); - activity.SetTag("parameter.room", request.RoomName); - activity.SetTag("parameter.username", request.UserName); - await Task.Delay(TimeSpan.FromMilliseconds(2)); - } - } -} -``` - -If you don't want your Trace relates to invoked mehod, use `this.Context.GetTraceContext()` to get your Context's trace directly. - -```csharp -// if you don't want set relation to this method, but directly this streaming hub, set hub trace context to your activiy. -var hubTraceContext = this.Context.GetTraceContext(); -using (var activity = activitySource.StartActivity("sample:hub_context_relation", ActivityKind.Internal, hubTraceContext)) -{ - // this is sample. use orm or any safe way. - activity.SetTag("message", "this span has no relationship with this method but has with hub context."); -} -``` - -![image](https://user-images.githubusercontent.com/3856350/91793693-dd738e80-ec53-11ea-8a50-a1fbd6fb4cd0.png) - - -## Implement your own metrics - -Here's Prometheus exporter sample with MagicOnion.OpenTelemetry. - -![image](https://user-images.githubusercontent.com/3856350/91793545-72c25300-ec53-11ea-92f6-e1f167054926.png) - -Implement `IMagicOnionLogger` to configure your metrics. You can collect metrics when following callbacks are invoked by filter. - -```csharp -namespace MagicOnion.Server -{ - public interface IMagicOnionLogger - { - void BeginBuildServiceDefinition(); - void BeginInvokeHubMethod(StreamingHubContext context, ArraySegment request, Type type); - void BeginInvokeMethod(ServiceContext context, byte[] request, Type type); - void EndBuildServiceDefinition(double elapsed); - void EndInvokeHubMethod(StreamingHubContext context, int responseSize, Type type, double elapsed, bool isErrorOrInterrupted); - void EndInvokeMethod(ServiceContext context, byte[] response, Type type, double elapsed, bool isErrorOrInterrupted); - void InvokeHubBroadcast(string groupName, int responseSize, int broadcastGroupCount); - void ReadFromStream(ServiceContext context, byte[] readData, Type type, bool complete); - void WriteToStream(ServiceContext context, byte[] writeData, Type type); - } -} -``` - -When implement your own metrics, define `IView` and register it `Stats.ViewManager.RegisterView(YOUR_VIEW);`, then send metrics. - -There are several way to send metrics. - -> Send each metrics each line. - -```csharp -statsRecorder.NewMeasureMap().Put(YOUR_METRICS, 1).Record(TagContext); -``` - -> Put many metrics and send at once: - -```csharp -var map = statsRecorder.NewMeasureMap(); map.Put(YOUR_METRICS, 1); -map.Put(YOUR_METRICS2, 2); -map.Put(YOUR_METRICS3, 10); -if (isErrorOrInterrupted) -{ - map.Put(YOUR_METRICS4, 3); -} - -map.Record(TagContext); -``` - -> create tag scope and set number of metrics. - -```csharp -var tagContextBuilder = Tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); -using (var scopedTags = tagContextBuilder.BuildScoped()) -{ - StatsRecorder.NewMeasureMap().Put(YOUR_METRICS, 1).Record(); - StatsRecorder.NewMeasureMap().Put(YOUR_METRICS2, 2).Record(); - StatsRecorder.NewMeasureMap().Put(YOUR_METRICS3, 10).Record(); -} -``` - -Make sure your View's column, and metrics TagKey is matched. Otherwise none of metrics will shown. diff --git a/src/MagicOnion.Server.OpenTelemetry/RpcScope.cs b/src/MagicOnion.Server.OpenTelemetry/RpcScope.cs deleted file mode 100644 index 51c7b55b5..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/RpcScope.cs +++ /dev/null @@ -1,134 +0,0 @@ -using Grpc.Core; -using MagicOnion.Server.OpenTelemetry.Internal; -using OpenTelemetry.Trace; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading; - -namespace MagicOnion.Server.OpenTelemetry -{ - /// - /// Manage trace activity scope for this Rpc - /// - public interface IRpcScope - { - /// - /// Set custom tag to the activity. - /// - /// - void SetTags(IDictionary tags); - } - internal abstract class RpcScope : IDisposable, IRpcScope - { - private Activity activity; - private long complete = 0; - - protected string RpcService { get; } - protected string RpcMethod { get; } - protected string ServiceName { get; } - protected Activity ParentActivity { get; set; } - - protected RpcScope(string rpcService, string rpcMethod, string serviceName) - { - RpcService = rpcService; - RpcMethod = rpcMethod; - ServiceName = serviceName; - } - - /// - /// Call or to set activity status. - /// Without complete will records a cancel RPC - /// - public void Dispose() - { - if (activity == null) - { - return; - } - - // If not already completed this will mark the Activity as cancelled. - StopActivity((int)Grpc.Core.StatusCode.Cancelled); - } - - - /// - /// Records a complete RPC - /// - public void Complete(Grpc.Core.StatusCode statusCode = Grpc.Core.StatusCode.OK) - { - if (activity == null) - { - return; - } - - // The overall Span status should remain unset however the grpc status code attribute is required - StopActivity((int)statusCode); - } - - /// - /// Records a failed RPC - /// - /// - public void CompleteWithException(Exception exception) - { - if (activity == null) - { - return; - } - - var grpcStatusCode = Grpc.Core.StatusCode.Unknown; - var description = exception.Message; - - if (exception is RpcException rpcException) - { - grpcStatusCode = rpcException.StatusCode; - description = rpcException.Message; - } - - activity.SetTag(SemanticConventions.AttributeException, exception.ToString()); - StopActivity((int)grpcStatusCode, description); - } - protected void SetActivity(Activity activity) - { - this.activity = activity; - - if (!this.activity.IsAllDataRequested) - { - return; - } - - this.activity.SetTag(SemanticConventions.AttributeServiceName, ServiceName); - this.activity.SetTag(SemanticConventions.AttributeRpcSystem, "grpc"); - this.activity.SetTag(SemanticConventions.AttributeRpcService, RpcService); - this.activity.SetTag(SemanticConventions.AttributeRpcMethod, RpcMethod); - } - - public void SetTags(IDictionary tags) - { - if (activity == null) - { - return; - } - - foreach (var tag in tags) - { - activity.SetTag(tag.Key, tag.Value); - } - } - - private void StopActivity(int statusCode, string statusDescription = null) - { - if (Interlocked.CompareExchange(ref this.complete, 1, 0) == 0) - { - activity.SetTag(SemanticConventions.AttributeRpcGrpcStatusCode, statusCode); - if (statusDescription != null) - { - activity.SetStatus(global::OpenTelemetry.Trace.Status.Error.WithDescription(statusDescription)); - } - - activity.Stop(); - } - } - } -} diff --git a/src/MagicOnion.Server.OpenTelemetry/ServiceContextTelemetryExtensions.cs b/src/MagicOnion.Server.OpenTelemetry/ServiceContextTelemetryExtensions.cs deleted file mode 100644 index f1ef9d806..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/ServiceContextTelemetryExtensions.cs +++ /dev/null @@ -1,57 +0,0 @@ -using MagicOnion.Server.Hubs; -using MagicOnion.Server.OpenTelemetry.Internal; - -namespace MagicOnion.Server.OpenTelemetry -{ - public static class ServiceContextTelemetryExtensions - { - /// - /// Set the trace scope with this service context. - /// - /// - /// - internal static void SetTraceScope(this StreamingHubContext context, IRpcScope scope) - { - context.ServiceContext.Items[MagicOnionTelemetryConstants.ServiceContextItemKeyTrace + "." + context.Path] = scope; - } - - /// - /// Set the trace scope with this service context. This allows user to add their tag directly to this activity. - /// - /// - /// - internal static void SetTraceScope(this ServiceContext context, IRpcScope scope) - { - context.Items[MagicOnionTelemetryConstants.ServiceContextItemKeyTrace] = scope; - } - - /// - /// Gets the trace scope associated with this service context. - /// - /// - /// - public static IRpcScope GetTraceScope(this ServiceContext context) - { - if (context.Items.TryGetValue(MagicOnionTelemetryConstants.ServiceContextItemKeyTrace, out var scope)) - { - return (IRpcScope)scope; - } - return default; - } - /// - /// Gets the trace scope associated with this service context. - /// - /// Add custom tag directly to this activity. - /// - /// IHubClass/MethodName - /// - public static IRpcScope GetTraceScope(this ServiceContext context, string hubPath) - { - if (context.Items.TryGetValue(MagicOnionTelemetryConstants.ServiceContextItemKeyTrace + "." + hubPath, out var scope)) - { - return (IRpcScope)scope; - } - return default; - } - } -} diff --git a/src/MagicOnion.Server.OpenTelemetry/TracerProviderBuilderExtensions.cs b/src/MagicOnion.Server.OpenTelemetry/TracerProviderBuilderExtensions.cs deleted file mode 100644 index f7dc291e6..000000000 --- a/src/MagicOnion.Server.OpenTelemetry/TracerProviderBuilderExtensions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using OpenTelemetry.Trace; -using MagicOnion.Server.OpenTelemetry.Internal; - -namespace MagicOnion.Server.OpenTelemetry -{ - public static class TracerProviderBuilderExtensions - { - public static TracerProviderBuilder AddMagicOnionInstrumentation(this TracerProviderBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - return builder.AddSource(MagicOnionInstrumentation.ActivitySourceName); - } - } -} From fe56aa19f505be547ef60821a51726bdc08b1c4d Mon Sep 17 00:00:00 2001 From: Mayuki Sawatari Date: Wed, 25 Oct 2023 12:12:03 +0900 Subject: [PATCH 2/2] Update workflows --- .github/workflows/build-canary.yml | 19 +------------------ .github/workflows/build-debug.yml | 9 --------- .github/workflows/build-release.yml | 19 +------------------ 3 files changed, 2 insertions(+), 45 deletions(-) diff --git a/.github/workflows/build-canary.yml b/.github/workflows/build-canary.yml index 5700f882e..b7d39d4d8 100644 --- a/.github/workflows/build-canary.yml +++ b/.github/workflows/build-canary.yml @@ -30,25 +30,8 @@ jobs: name: nuget path: ./publish/ - canary-build-experimental: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v3 - - uses: ./.github/actions/setup-dotnet - - run: echo "MAGICONION_VERSION=ci-$(date '+%Y%m%d-%H%M%S')+${GITHUB_SHA:0:6}" >> $GITHUB_ENV - - run: echo "MAGICONION_VERSION=${MAGICONION_VERSION}" - # build - - run: dotnet build ./src/MagicOnion.Server.OpenTelemetry/ -c ${{ env.BUILD_CONFIG }} -p:VersionSuffix=${MAGICONION_VERSION} - # test - - run: dotnet pack ./src/MagicOnion.Server.OpenTelemetry/MagicOnion.Server.OpenTelemetry.csproj -c ${{ env.BUILD_CONFIG }} --include-symbols --include-source --no-build -p:VersionSuffix=${MAGICONION_VERSION} -o ./publish - - uses: actions/upload-artifact@v1 - with: - name: nuget-experimental - path: ./publish/ - canary-push: - needs: [canary-build, canary-build-experimental] + needs: [canary-build] runs-on: ubuntu-latest timeout-minutes: 5 env: diff --git a/.github/workflows/build-debug.yml b/.github/workflows/build-debug.yml index 6eda35b24..56df509eb 100644 --- a/.github/workflows/build-debug.yml +++ b/.github/workflows/build-debug.yml @@ -33,15 +33,6 @@ jobs: - run: dotnet test -c Debug MagicOnion.sln - run: dotnet test -c Release MagicOnion.sln - build-dotnet-experimental: - name: "Build .NET Experimental libraries" - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v3 - - uses: ./.github/actions/setup-dotnet - - run: dotnet build ./src/MagicOnion.Server.OpenTelemetry/ -c ${{ env.BUILD_CONFIG }} - build-unity: name: "Build Unity package" if: "((github.event_name == 'push' && github.repository_owner == 'Cysharp') || startsWith(github.event.pull_request.head.label, 'Cysharp:'))" diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 39009d6bb..ccfb63df2 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -145,23 +145,6 @@ jobs: name: nuget path: ./publish/ - build-dotnet-experimental: - needs: [update-packagejson] - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v3 - with: - ref: ${{ needs.update-packagejson.outputs.sha }} - - uses: ./.github/actions/setup-dotnet - - run: echo ${{ needs.update-packagejson.outputs.sha }} - - run: dotnet build ./src/MagicOnion.Server.OpenTelemetry/ -c Release - - run: dotnet pack ./src/MagicOnion.Server.OpenTelemetry/MagicOnion.Server.OpenTelemetry.csproj -c Release --no-build -o ./publish - - uses: actions/upload-artifact@v1 - with: - name: nuget-experimental - path: ./publish/ - build-unity: needs: [update-packagejson] strategy: @@ -201,7 +184,7 @@ jobs: create-release: if: github.event.inputs.dry_run == 'false' needs: - [update-packagejson, update-sourcegenerator-unity, build-dotnet, build-dotnet-experimental, build-unity] + [update-packagejson, update-sourcegenerator-unity, build-dotnet, build-unity] runs-on: ubuntu-latest steps: - uses: actions/checkout@v3