├── .gitattributes ├── .gitignore ├── DESIGN.md ├── LICENSE.txt ├── Microsoft.Diagnostics.Correlation.sln ├── PublicKey.snk ├── README.md ├── global.json ├── nuspecs └── AspNetSuite │ └── Microsoft.Diagnostics.Correlation.AspNet.nuspec ├── src ├── Microsoft.Diagnostics.Context │ ├── ContextResolver.Net45.cs │ ├── ContextResolver.Net46.cs │ ├── CorrelationContext.cs │ ├── ICorrelationContext.cs │ ├── Microsoft.Diagnostics.Context.xproj │ ├── Properties │ │ └── AssemblyInfo.cs │ └── project.json ├── Microsoft.Diagnostics.Correlation.AspNetCore │ ├── ApplicationBuilderExtensions.cs │ ├── AspNetCoreConfiguration.cs │ ├── AspNetCoreCorrelationConfiguration.cs │ ├── ContextTracingInstrumentation.cs │ ├── CorrelationContextFactory.cs │ ├── Internal │ │ ├── AspNetDiagnosticListenerObserver.cs │ │ ├── CorrelationConfigurationSettings.cs │ │ ├── DiagnosticListenersObserver.cs │ │ └── HttpDiagnosticListenerObserver.cs │ ├── Microsoft.Diagnostics.Correlation.AspNetCore.xproj │ ├── ServiceCollectionExtenstions.cs │ └── project.json ├── Microsoft.Diagnostics.Correlation.Common │ ├── CorrelationHeaderInfo.cs │ ├── Http │ │ ├── ContextRequestHandler.cs │ │ ├── CorrelationContextInjector.cs │ │ ├── CorrelationContextRequestHandler.cs │ │ ├── CorrelationHttpClientBuilder.cs │ │ ├── EndpointFilter.cs │ │ ├── HttpClientBuilder.cs │ │ └── HttpRequestMessageExtensions.cs │ ├── IContextFactory.cs │ ├── IContextInjector.cs │ ├── IEndpointFilter.cs │ ├── Instrumentation │ │ ├── Configuration.cs │ │ └── IOutgoingRequestNotifier.cs │ ├── Microsoft.Diagnostics.Correlation.Common.xproj │ └── project.json ├── Microsoft.Diagnostics.Correlation.Instrumentation │ ├── ContextTracingInstrumentation.cs │ ├── Microsoft.Diagnostics.Correlation.Instrumentation.xproj │ ├── ProfilerConfiguration.cs │ ├── ProfilerCorrelationConfiguration.cs │ └── project.json ├── Microsoft.Diagnostics.Correlation.Mvc │ ├── CorrelationTracingFilter.cs │ ├── Microsoft.Diagnostics.Correlation.Mvc.xproj │ └── project.json ├── Microsoft.Diagnostics.Correlation.Signing │ ├── Microsoft.Diagnostics.Correlation.Signing.csproj │ └── packages.config ├── Microsoft.Diagnostics.Correlation.WebApi │ ├── CorrelationTracingFilter.cs │ ├── Microsoft.Diagnostics.Correlation.WebApi.xproj │ └── project.json └── Microsoft.Diagnostics.Correlation │ ├── Http │ ├── CorrelationContextFactory.cs │ ├── CorrelationTracingHttpModule.cs │ ├── WebRequestCorrelationContextInjector.cs │ └── WebRequestExtensions.cs │ ├── Microsoft.Diagnostics.Correlation.xproj │ ├── Owin │ ├── ContextTracingMiddleware.cs │ ├── CorrelationTracingMiddleware.cs │ └── OwinCorrelationContextFactory.cs │ └── project.json ├── targets ├── DotNet.Web │ ├── Microsoft.DotNet.Web.targets │ └── en-US │ │ └── web.general.browseobject.xaml └── DotNet │ ├── Microsoft.DotNet.Common.targets │ ├── Microsoft.DotNet.Extensions.targets │ ├── Microsoft.DotNet.Publishing.targets │ ├── Microsoft.DotNet.Tasks.dll │ ├── Microsoft.DotNet.props │ ├── Microsoft.DotNet.targets │ ├── Microsoft.VisualStudio.ProjectSystem.DotNet.Runtime.dll │ ├── Newtonsoft.Json.dll │ └── en-US │ ├── Content.xaml │ ├── EmbeddedResource.xaml │ ├── ProjectDebugger.xaml │ ├── ProjectItemsSchema.xaml │ ├── ResolvedDesignTimeHostReferences.xaml │ ├── csharp.browseobject.xaml │ ├── csharp.xaml │ ├── debugger_general.xaml │ ├── folder.xaml │ ├── general.browseobject.xaml │ ├── general.xaml │ ├── general_file.xaml │ ├── none.xaml │ ├── scc.xaml │ └── typescript.xaml ├── test ├── Microsoft.Diagnostics.Correlation.AspNetCore.Test │ ├── ContextTracingInstumentationListenerTests.cs │ ├── CoreConfigurationTests.cs │ ├── CorrelationContextFactoryTests.cs │ ├── DummyObserver.cs │ ├── Microsoft.Diagnostics.Correlation.AspNetCore.Test.xproj │ └── project.json ├── Microsoft.Diagnostics.Correlation.Common.Test │ ├── ContextResolverTests.cs │ ├── CorrelationContextTests.cs │ ├── Http │ │ ├── ContextRequestHandlerTests.cs │ │ ├── CorrelationContextInjectorTests.cs │ │ ├── EndpointValidatorTest.cs │ │ ├── HttpClientBuilderTests.cs │ │ └── HttpRequestExtensionsTest.cs │ ├── Microsoft.Diagnostics.Correlation.Common.Test.xproj │ └── project.json ├── Microsoft.Diagnostics.Correlation.Instrumentation.Test │ ├── ContextTracingInsrumentationProfilerTests.cs │ ├── Microsoft.Diagnostics.Correlation.Instrumentation.Test.xproj │ ├── ProfilerConfigurationTests.cs │ └── project.json ├── Microsoft.Diagnostics.Correlation.Middleware.Test │ ├── ContextTracingMiddlewareTests.cs │ ├── Microsoft.Diagnostics.Correlation.Owin.Test.xproj │ ├── OwinCorrelationContextFactoryTests.cs │ └── project.json └── Microsoft.Diagnostics.Correlation.Test │ ├── CorrelationContextFactoryTests.cs │ ├── Microsoft.Diagnostics.Correlation.Test.xproj │ ├── WebRequestCorrelationContextInjectorTests.cs │ └── project.json └── tools ├── InstallCoreSDK.ps1 ├── createNugetPackages.cmd ├── nuget.exe ├── restore.cmd ├── runtest.cmd └── setEnv.cmd /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | *.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.pfx 193 | *.publishsettings 194 | node_modules/ 195 | orleans.codegen.cs 196 | 197 | # Since there are multiple workflows, uncomment next line to ignore bower_components 198 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 199 | #bower_components/ 200 | 201 | # RIA/Silverlight projects 202 | Generated_Code/ 203 | 204 | # Backup & report files from converting an old project file 205 | # to a newer Visual Studio version. Backup files are not needed, 206 | # because we have git ;-) 207 | _UpgradeReport_Files/ 208 | Backup*/ 209 | UpgradeLog*.XML 210 | UpgradeLog*.htm 211 | 212 | # SQL Server files 213 | *.mdf 214 | *.ldf 215 | 216 | # Business Intelligence projects 217 | *.rdl.data 218 | *.bim.layout 219 | *.bim_*.settings 220 | 221 | # Microsoft Fakes 222 | FakesAssemblies/ 223 | 224 | # GhostDoc plugin setting file 225 | *.GhostDoc.xml 226 | 227 | # Node.js Tools for Visual Studio 228 | .ntvs_analysis.dat 229 | 230 | # Visual Studio 6 build log 231 | *.plg 232 | 233 | # Visual Studio 6 workspace options file 234 | *.opt 235 | 236 | # Visual Studio LightSwitch build output 237 | **/*.HTMLClient/GeneratedArtifacts 238 | **/*.DesktopClient/GeneratedArtifacts 239 | **/*.DesktopClient/ModelManifest.xml 240 | **/*.Server/GeneratedArtifacts 241 | **/*.Server/ModelManifest.xml 242 | _Pvt_Extensions 243 | 244 | # Paket dependency manager 245 | .paket/paket.exe 246 | paket-files/ 247 | 248 | # FAKE - F# Make 249 | .fake/ 250 | 251 | # JetBrains Rider 252 | .idea/ 253 | *.sln.iml 254 | 255 | # CodeRush 256 | .cr/ 257 | 258 | # Python Tools for Visual Studio (PTVS) 259 | __pycache__/ 260 | *.pyc 261 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /PublicKey.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/diagnostics-correlation/91a6f7ae19d884f299e090844b9d1779f953ca59/PublicKey.snk -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "projects": [ 3 | "src", 4 | "test" 5 | ] 6 | } -------------------------------------------------------------------------------- /nuspecs/AspNetSuite/Microsoft.Diagnostics.Correlation.AspNet.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Microsoft.Diagnostics.Correlation.AspNet 5 | 1.0.0-preview1 6 | Microsoft 7 | Microsoft 8 | © Microsoft Corporation. All rights reserved. 9 | true 10 | Microsoft Diagnostic Correlation 11 | Correlation 12 | Microsoft, Diagnostics, Correlation, ASP.NET 13 | https://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Context/ContextResolver.Net45.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | #if NET45 || NET40 7 | using System.Runtime.Remoting.Messaging; 8 | 9 | namespace Microsoft.Diagnostics.Context 10 | { 11 | /// 12 | /// Provides access to generic correlation context 13 | /// 14 | /// 15 | /// Context is stored as object 16 | /// 17 | public class ContextResolver 18 | { 19 | private const string Slot = "x-ms-correlation-id-slot"; 20 | 21 | /// 22 | /// Sets context. 23 | /// 24 | /// Type of correlation context 25 | /// Correlation context value 26 | /// Context value 27 | public static TContext SetContext(TContext context) 28 | { 29 | CallContext.LogicalSetData(Slot, context); 30 | return context; 31 | } 32 | 33 | /// 34 | /// Gets correlation context 35 | /// 36 | /// Type of correlation context 37 | /// Context value 38 | public static TContext GetContext() 39 | { 40 | return (TContext)CallContext.LogicalGetData(Slot); 41 | } 42 | 43 | /// 44 | /// Clears context 45 | /// 46 | public static void ClearContext() 47 | { 48 | CallContext.LogicalSetData(Slot, null); 49 | } 50 | } 51 | } 52 | #endif -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Context/ContextResolver.Net46.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | #if NETSTANDARD1_6 || NET46 7 | using System.Threading; 8 | 9 | namespace Microsoft.Diagnostics.Context 10 | { 11 | /// 12 | /// Provides access to generic correlation context 13 | /// 14 | /// 15 | /// Context is stored as object 16 | /// 17 | public class ContextResolver 18 | { 19 | private static readonly AsyncLocal Context = new AsyncLocal(); 20 | 21 | /// 22 | /// Sets context. 23 | /// 24 | /// Type of correlation context 25 | /// Correlation context value 26 | /// Context value 27 | public static TContext SetContext(TContext context) 28 | { 29 | Context.Value = context; 30 | return context; 31 | } 32 | 33 | /// 34 | /// Gets correlation context 35 | /// 36 | /// Type of correlation context 37 | /// Context value 38 | public static TContext GetContext() 39 | { 40 | return (TContext)Context.Value; 41 | } 42 | 43 | /// 44 | /// Clears context 45 | /// 46 | public static void ClearContext() 47 | { 48 | Context.Value = null; 49 | } 50 | } 51 | } 52 | #endif -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Context/ICorrelationContext.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | namespace Microsoft.Diagnostics.Context 7 | { 8 | /// 9 | /// Base ICorrelationContext interface 10 | /// 11 | /// Type of context 12 | public interface ICorrelationContext 13 | { 14 | /// 15 | /// Creates copy of 'parent' context for outgoing request with child request id 16 | /// 17 | /// Unique id for outgoing request 18 | /// Child context 19 | TContext GetChildRequestContext(string childRequestId); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Context/Microsoft.Diagnostics.Context.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 5953a709-c584-4744-834f-079c38a83e8c 10 | Microsoft.Diagnostics.Context 11 | .\obj 12 | .\bin\ 13 | v4.6.1 14 | 15 | 16 | 17 | 2.0 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Context/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("HP Inc.")] 9 | [assembly: AssemblyProduct("Microsoft.Diagnostics.Context")] 10 | [assembly: AssemblyTrademark("")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("5953a709-c584-4744-834f-079c38a83e8c")] 19 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Context/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "frameworks": { 4 | "netstandard1.6": { 5 | "imports": "dnxcore50", 6 | "dependencies": { 7 | "NETStandard.Library": "1.6.0" 8 | } 9 | }, 10 | "net46": {}, 11 | "net45": { 12 | "frameworkAssemblies": { 13 | "System.Runtime.Remoting": "4.0.0.0" 14 | } 15 | }, 16 | "net40": { 17 | "frameworkAssemblies": { 18 | "System.Runtime.Remoting": "4.0.0.0" 19 | } 20 | } 21 | }, 22 | "packOptions": { 23 | "owners": [ "Microsoft" ], 24 | "summary": "Cross-service telemetry correlation library: common context", 25 | "tags": [ 26 | "Microsoft, Diagnostics, Correlation, Context" 27 | ], 28 | "requireLicenseAcceptance": true, 29 | "licenseUrl": "https://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm" 30 | }, 31 | "buildOptions": { 32 | "keyFile": "../../PublicKey.snk", 33 | "delaySign": true 34 | } 35 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/ApplicationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System.Net.Http; 7 | using Microsoft.AspNetCore.Builder; 8 | using Microsoft.AspNetCore.Hosting; 9 | using Microsoft.Diagnostics.Context; 10 | using Microsoft.Diagnostics.Correlation.Common.Instrumentation; 11 | using Microsoft.Extensions.Configuration; 12 | 13 | namespace Microsoft.Diagnostics.Correlation.AspNetCore 14 | { 15 | public static class ApplicationBuilderExtensions 16 | { 17 | /// 18 | /// Enables Correlation instrumentation 19 | /// 20 | /// application builder 21 | /// Correlation confgiuration 22 | /// application builder 23 | /// Add singleton to services to receive outgoing requests events 24 | public static IApplicationBuilder UseCorrelationInstrumentation(this IApplicationBuilder app, IConfiguration configuration) 25 | { 26 | Initialize(app, new AspNetCoreCorrelationConfiguration(configuration)); 27 | return app; 28 | } 29 | 30 | /// 31 | /// Enables Correlation instrumentation 32 | /// 33 | /// application builder 34 | /// application builder 35 | /// Add singleton to services to receive outgoing requests events 36 | public static IApplicationBuilder UseCorrelationInstrumentation(this IApplicationBuilder app) 37 | { 38 | Initialize(app, new AspNetCoreCorrelationConfiguration()); 39 | return app; 40 | } 41 | 42 | private static void Initialize(IApplicationBuilder app, AspNetCoreCorrelationConfiguration configuration) 43 | { 44 | var notifier = app.ApplicationServices.GetService(typeof(IOutgoingRequestNotifier)); 45 | 46 | if (notifier != null) 47 | configuration.RequestNotifier = notifier as IOutgoingRequestNotifier; 48 | 49 | var instrumentaion = ContextTracingInstrumentation.Enable(configuration); 50 | 51 | var appLifetime = app.ApplicationServices.GetService(typeof(IApplicationLifetime)) as IApplicationLifetime; 52 | 53 | appLifetime?.ApplicationStopped.Register(() => instrumentaion?.Dispose()); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/AspNetCoreConfiguration.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | using System.Net.Http; 8 | using Microsoft.AspNetCore.Http; 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Diagnostics.Context; 11 | using Microsoft.Diagnostics.Correlation.AspNetCore.Internal; 12 | using Microsoft.Diagnostics.Correlation.Common; 13 | using Microsoft.Diagnostics.Correlation.Common.Instrumentation; 14 | using Microsoft.Diagnostics.Correlation.Common.Http; 15 | 16 | namespace Microsoft.Diagnostics.Correlation.AspNetCore 17 | { 18 | /// 19 | /// Provides generic instrumentation configuration for ASP.NET Core apps: set of injectors and other instrumetnation parameters 20 | /// 21 | /// Type of correlation context 22 | public class AspNetCoreConfiguration : Configuration where TContext : ICorrelationContext 23 | { 24 | /// 25 | /// Constructs default with enabled outgoing requests instrumentation and default 26 | /// 27 | public AspNetCoreConfiguration() 28 | { 29 | InstrumentOutgoingRequests = true; 30 | EndpointFilter = new EndpointFilter(); 31 | } 32 | 33 | /// 34 | /// Constructs 35 | /// 36 | /// Correlation configuration 37 | public AspNetCoreConfiguration(IConfiguration configuration) 38 | { 39 | if (configuration == null) 40 | throw new ArgumentNullException(nameof(configuration)); 41 | 42 | var settings = new CorrelationConfigurationSettings(); 43 | configuration.Bind(settings); 44 | 45 | InstrumentOutgoingRequests = settings.InstrumentOutgoingRequests ?? true; 46 | if (settings.Headers != null) 47 | { 48 | if (settings.Headers.CorrelationIdHeaderName != null && settings.Headers.RequestIdHeaderName != null) 49 | { 50 | CorrelationHeaderInfo.CorrelationIdHeaderName = settings.Headers.CorrelationIdHeaderName; 51 | CorrelationHeaderInfo.RequestIdHeaderName = settings.Headers.RequestIdHeaderName; 52 | } 53 | else 54 | { 55 | throw new ArgumentException($"\"Headers\" section must define \"{nameof(CorrelationHeaderInfo.CorrelationIdHeaderName)}\" and \"{CorrelationHeaderInfo.RequestIdHeaderName}\""); 56 | } 57 | } 58 | 59 | if (settings.EndpointFilter != null) 60 | { 61 | if (settings.EndpointFilter.Endpoints != null) 62 | { 63 | EndpointFilter = new EndpointFilter(settings.EndpointFilter.Endpoints, settings.EndpointFilter.Allow); 64 | } 65 | else 66 | { 67 | throw new ArgumentException($"\"EndpointFilter\" section must define \"{nameof(settings.EndpointFilter.Endpoints)}\" list"); 68 | } 69 | } 70 | else 71 | { 72 | EndpointFilter = new EndpointFilter(); 73 | } 74 | } 75 | 76 | /// 77 | /// Controls if outgoing requests should be instumented with 78 | /// 79 | public bool InstrumentOutgoingRequests { get; set; } 80 | 81 | /// 82 | /// Sets to control how context is extracted from the incoming request 83 | /// 84 | public IContextFactory ContextFactory { get; set; } 85 | 86 | /// 87 | /// Sets to control how context is extracted from the incoming request 88 | /// 89 | /// instance 90 | /// Current for chaining 91 | public Configuration WithContextFactory( 92 | IContextFactory contextFactory) 93 | { 94 | ContextFactory = contextFactory; 95 | return this; 96 | } 97 | 98 | /// 99 | /// Controls if incoming requests should be instumented with 100 | /// 101 | /// Current for chaining 102 | public Configuration DiableOutgoingRequestInstrumentation() 103 | { 104 | InstrumentOutgoingRequests = false; 105 | return this; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/AspNetCoreCorrelationConfiguration.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System.Collections.Generic; 7 | using System.Net.Http; 8 | using Microsoft.Diagnostics.Context; 9 | using Microsoft.Diagnostics.Correlation.Common; 10 | using Microsoft.Diagnostics.Correlation.Common.Http; 11 | using Microsoft.Extensions.Configuration; 12 | 13 | namespace Microsoft.Diagnostics.Correlation.AspNetCore 14 | { 15 | /// 16 | /// Provides default instrumentation configuration for ASP.NET Core apps, configures to be used 17 | /// 18 | public class AspNetCoreCorrelationConfiguration : AspNetCoreConfiguration 19 | { 20 | /// 21 | /// constructor, sets up default and 22 | /// 23 | public AspNetCoreCorrelationConfiguration() 24 | { 25 | Initialize(); 26 | } 27 | 28 | /// 29 | /// constructor, sets up default and 30 | /// 31 | /// Correlation configuration 32 | public AspNetCoreCorrelationConfiguration(IConfiguration configuration) 33 | : base(configuration) 34 | { 35 | Initialize(); 36 | } 37 | 38 | private void Initialize() 39 | { 40 | ContextFactory = new CorrelationContextFactory(); 41 | ContextInjectors = new List> 42 | { 43 | new CorrelationContextInjector() 44 | }; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/ContextTracingInstrumentation.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | using System.Net.Http; 10 | using Microsoft.Diagnostics.Context; 11 | using Microsoft.Diagnostics.Correlation.AspNetCore.Internal; 12 | using Microsoft.Diagnostics.Correlation.Common.Http; 13 | using Microsoft.Diagnostics.Correlation.Common.Instrumentation; 14 | using Microsoft.Extensions.Configuration; 15 | 16 | namespace Microsoft.Diagnostics.Correlation.AspNetCore 17 | { 18 | /// 19 | /// Implements outgoing HTTP requests instrumentation with 20 | /// 21 | public class ContextTracingInstrumentation 22 | { 23 | private const string HttpListenerName = "HttpHandlerDiagnosticListener"; 24 | private const string AspNetListenerName = "Microsoft.AspNetCore"; 25 | 26 | /// 27 | /// Enables instrumentation of outgoing (and possibly incoming requests) 28 | /// Extracts from incoming request and injects it to outgoing requests 29 | /// 30 | /// Instrumentation configuration 31 | /// for the observers 32 | public static IDisposable Enable(IConfiguration configuration) 33 | { 34 | return Enable(new AspNetCoreCorrelationConfiguration(configuration)); 35 | } 36 | 37 | /// 38 | /// Enables instrumentation of outgoing (and possibly incoming requests) 39 | /// Extracts from incoming request and injects it to outgoing requests 40 | /// 41 | /// Instrumentation configuration 42 | /// for the observers 43 | public static IDisposable Enable(AspNetCoreCorrelationConfiguration configuration) 44 | { 45 | return Enable(configuration); 46 | } 47 | 48 | /// 49 | /// Enables instrumentation of outgoing (and possibly incoming requests) 50 | /// Extracts generic correlation context from incoming request and injects it to outgoing requests 51 | /// 52 | /// Instrumentation 53 | /// for the observers 54 | public static IDisposable Enable(Configuration configuration) where TContext : ICorrelationContext 55 | { 56 | if (configuration == null) 57 | throw new ArgumentNullException(nameof(configuration)); 58 | 59 | var coreConfig = configuration as AspNetCoreConfiguration; 60 | if (coreConfig == null) 61 | throw new ArgumentException($"{nameof(configuration)} is not instance of AspNetCoreConfiguration"); 62 | 63 | if (configuration.ContextInjectors == null) 64 | throw new ArgumentNullException(nameof(configuration.ContextInjectors)); 65 | 66 | if (coreConfig.ContextFactory == null) 67 | throw new ArgumentNullException(nameof(coreConfig.ContextFactory)); 68 | 69 | var observers = new Dictionary>> 70 | { 71 | { 72 | AspNetListenerName, new AspNetDiagnosticListenerObserver(coreConfig.ContextFactory) 73 | } 74 | }; 75 | 76 | if (coreConfig.InstrumentOutgoingRequests) 77 | { 78 | observers.Add( 79 | HttpListenerName, new HttpDiagnosticListenerObserver( 80 | configuration.ContextInjectors, 81 | configuration.EndpointFilter, 82 | new NotifierWrapper(configuration.RequestNotifier))); 83 | } 84 | 85 | return DiagnosticListener.AllListeners.Subscribe(new DiagnosticListenersObserver(observers)); 86 | } 87 | 88 | private class NotifierWrapper : IOutgoingRequestNotifier where TContext : ICorrelationContext 89 | { 90 | private readonly IOutgoingRequestNotifier requestNotifier; 91 | 92 | public NotifierWrapper(IOutgoingRequestNotifier requestNotifier) 93 | { 94 | this.requestNotifier = requestNotifier; 95 | } 96 | 97 | public void OnBeforeRequest(TContext context, HttpRequestMessage request) 98 | { 99 | try 100 | { 101 | requestNotifier?.OnBeforeRequest(context.GetChildRequestContext(request.GetChildRequestId()), request); 102 | } 103 | catch (Exception) 104 | { 105 | //ignored 106 | } 107 | } 108 | 109 | public void OnAfterResponse(TContext context, HttpResponseMessage response) 110 | { 111 | try 112 | { 113 | requestNotifier?.OnAfterResponse(context.GetChildRequestContext(response.RequestMessage.GetChildRequestId()), response); 114 | } 115 | catch (Exception) 116 | { 117 | //ignored 118 | } 119 | 120 | } 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/CorrelationContextFactory.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | using System.Linq; 8 | using Microsoft.AspNetCore.Http; 9 | using Microsoft.Diagnostics.Context; 10 | using Microsoft.Diagnostics.Correlation.Common; 11 | 12 | namespace Microsoft.Diagnostics.Correlation.AspNetCore 13 | { 14 | /// 15 | /// Implementation to extract from 16 | /// 17 | public class CorrelationContextFactory : IContextFactory 18 | { 19 | /// 20 | /// Extracts from 21 | /// 22 | /// Incoming HTTP request 23 | /// Correlation context 24 | public CorrelationContext CreateContext(HttpRequest request) 25 | { 26 | if (request == null) 27 | throw new ArgumentNullException(nameof(request)); 28 | 29 | string correlationId = null; 30 | if (request.Headers.ContainsKey(CorrelationHeaderInfo.CorrelationIdHeaderName)) 31 | correlationId = request.Headers[CorrelationHeaderInfo.CorrelationIdHeaderName].First(); 32 | 33 | string requestId = null; 34 | if (request.Headers.ContainsKey(CorrelationHeaderInfo.RequestIdHeaderName)) 35 | requestId = request.Headers[CorrelationHeaderInfo.RequestIdHeaderName].First(); 36 | 37 | if (requestId == null) 38 | requestId = request.HttpContext.TraceIdentifier; 39 | 40 | return new CorrelationContext(correlationId ?? newGuid(), requestId ?? newGuid()); 41 | } 42 | 43 | private string newGuid() 44 | { 45 | return Guid.NewGuid().ToString(); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/Internal/AspNetDiagnosticListenerObserver.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Reflection; 9 | using Microsoft.AspNetCore.Http; 10 | using Microsoft.Diagnostics.Context; 11 | using Microsoft.Diagnostics.Correlation.Common; 12 | 13 | namespace Microsoft.Diagnostics.Correlation.AspNetCore.Internal 14 | { 15 | internal class AspNetDiagnosticListenerObserver : IObserver> 16 | { 17 | private readonly IContextFactory contextFactory; 18 | 19 | public AspNetDiagnosticListenerObserver(IContextFactory contextFactory) 20 | { 21 | this.contextFactory = contextFactory; 22 | } 23 | 24 | public void OnNext(KeyValuePair value) 25 | { 26 | if (value.Key != "Microsoft.AspNetCore.Hosting.BeginRequest" || value.Value == null) 27 | return; 28 | 29 | var httpContextInfo = value.Value.GetType().GetProperty("httpContext"); 30 | var httpContext = (DefaultHttpContext) httpContextInfo?.GetValue(value.Value, null); 31 | if (httpContext != null) 32 | { 33 | var ctx = contextFactory.CreateContext(httpContext.Request); 34 | if (ctx != null) 35 | ContextResolver.SetContext(ctx); 36 | } 37 | } 38 | 39 | public void OnCompleted() { } 40 | 41 | public void OnError(Exception error) { } 42 | } 43 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/Internal/CorrelationConfigurationSettings.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System.Collections.Generic; 7 | 8 | namespace Microsoft.Diagnostics.Correlation.AspNetCore.Internal 9 | { 10 | internal class CorrelationConfigurationSettings 11 | { 12 | internal class HeadersSettings 13 | { 14 | public string CorrelationIdHeaderName { get; set; } 15 | public string RequestIdHeaderName { get; set; } 16 | } 17 | 18 | internal class EndpointFilterSettings 19 | { 20 | public bool Allow { get; set; } 21 | public List Endpoints { get; set; } 22 | } 23 | 24 | public bool? InstrumentOutgoingRequests { get; set; } 25 | public HeadersSettings Headers { get; set; } 26 | public EndpointFilterSettings EndpointFilter { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/Internal/DiagnosticListenersObserver.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | 10 | namespace Microsoft.Diagnostics.Correlation.AspNetCore.Internal 11 | { 12 | internal class DiagnosticListenersObserver : IObserver 13 | { 14 | private readonly IDictionary>> observers; 15 | 16 | public DiagnosticListenersObserver(IDictionary>> observers) 17 | { 18 | this.observers = observers; 19 | } 20 | 21 | public void OnNext(DiagnosticListener value) 22 | { 23 | if (observers.ContainsKey(value.Name)) 24 | value.Subscribe(observers[value.Name]); 25 | } 26 | 27 | public void OnCompleted() { } 28 | 29 | public void OnError(Exception error) { } 30 | } 31 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/Internal/HttpDiagnosticListenerObserver.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Net.Http; 9 | using System.Reflection; 10 | using Microsoft.Diagnostics.Context; 11 | using Microsoft.Diagnostics.Correlation.Common; 12 | using Microsoft.Diagnostics.Correlation.Common.Instrumentation; 13 | 14 | namespace Microsoft.Diagnostics.Correlation.AspNetCore.Internal 15 | { 16 | internal class HttpDiagnosticListenerObserver : IObserver> where TContext : ICorrelationContext 17 | { 18 | private readonly List> contextInjectors; 19 | private readonly IEndpointFilter endpointFilter; 20 | private readonly IOutgoingRequestNotifier requestNotifier; 21 | 22 | public HttpDiagnosticListenerObserver( 23 | IEnumerable> contextInjectors, 24 | IEndpointFilter endpointFilter, 25 | IOutgoingRequestNotifier requestNotifier) 26 | { 27 | this.endpointFilter = endpointFilter; 28 | this.contextInjectors = new List>(contextInjectors); 29 | this.requestNotifier = requestNotifier; 30 | } 31 | 32 | public void OnNext(KeyValuePair value) 33 | { 34 | if (value.Value == null) 35 | return; 36 | 37 | if (value.Key == "System.Net.Http.Request") 38 | { 39 | var requestInfo = value.Value.GetType().GetProperty("Request"); 40 | var request = (HttpRequestMessage) requestInfo?.GetValue(value.Value, null); 41 | 42 | if (request != null) 43 | { 44 | var ctx = ContextResolver.GetContext(); 45 | if (endpointFilter.Validate(request.RequestUri)) 46 | { 47 | foreach (var injector in contextInjectors) 48 | { 49 | injector.UpdateRequest(ctx, request); 50 | } 51 | requestNotifier.OnBeforeRequest(ctx, request); 52 | } 53 | } 54 | } 55 | else if (value.Key == "System.Net.Http.Response") 56 | { 57 | var responseInfo = value.Value.GetType().GetProperty("Response"); 58 | var response = (HttpResponseMessage)responseInfo?.GetValue(value.Value, null); 59 | if (response != null) 60 | { 61 | if (endpointFilter.Validate(response.RequestMessage.RequestUri)) 62 | { 63 | requestNotifier.OnAfterResponse(ContextResolver.GetContext(), response); 64 | } 65 | } 66 | } 67 | } 68 | 69 | public void OnCompleted() {} 70 | 71 | public void OnError(Exception error) {} 72 | } 73 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/Microsoft.Diagnostics.Correlation.AspNetCore.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 10 | ce57b0f8-b6ec-4bb9-a0d9-78ba68e440e1 11 | Microsoft.Diagnostics.Correlation.AspNetCore 12 | .\obj 13 | .\bin\ 14 | v4.6.1 15 | 16 | 17 | 18 | 2.0 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/ServiceCollectionExtenstions.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System.Net.Http; 7 | using Microsoft.Diagnostics.Context; 8 | using Microsoft.Diagnostics.Correlation.Common.Instrumentation; 9 | using Microsoft.Extensions.DependencyInjection; 10 | 11 | namespace Microsoft.Diagnostics.Correlation.AspNetCore 12 | { 13 | public static class ServiceCollectionExtenstions 14 | { 15 | /// 16 | /// Adds request notifier service 17 | /// 18 | /// services 19 | /// IInstance of 20 | /// services 21 | public static IServiceCollection AddRequestNotifier(this IServiceCollection services, 22 | IOutgoingRequestNotifier notifier) 23 | { 24 | services.AddSingleton> 25 | (notifier); 26 | return services; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.AspNetCore/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "dependencies": { 4 | "Microsoft.AspNetCore.Http": "1.0.0", 5 | "Microsoft.AspNetCore.Hosting.Abstractions": "1.0.0", 6 | "Microsoft.Extensions.Configuration.Abstractions": "1.0.0", 7 | "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", 8 | "Microsoft.Diagnostics.Correlation.Common": "1.0.0-*", 9 | "NETStandard.Library": "1.6.0", 10 | "System.Diagnostics.DiagnosticSource": "4.0.0" 11 | }, 12 | 13 | "frameworks": { 14 | "netstandard1.6": { 15 | "imports": "dnxcore50" 16 | }, 17 | "net46": {}, 18 | "net451": {} 19 | }, 20 | "packOptions": { 21 | "owners": [ "Microsoft" ], 22 | "summary": "Cross-service telemetry correlation library for ASP.NET Core applications", 23 | "tags": [ 24 | "Microsoft, Diagnostics, Correlation, ASP.NET Core" 25 | ], 26 | "requireLicenseAcceptance": true, 27 | "licenseUrl": "https://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm" 28 | }, 29 | "buildOptions": { 30 | "keyFile": "../../PublicKey.snk", 31 | "delaySign": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/CorrelationHeaderInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Diagnostics.Correlation.Common 2 | { 3 | /// 4 | /// Correlation header names 5 | /// 6 | public class CorrelationHeaderInfo 7 | { 8 | /// 9 | /// CorrelationId header name 10 | /// 11 | public static string CorrelationIdHeaderName = "x-ms-request-root-id"; 12 | 13 | /// 14 | /// RequestId header name 15 | /// 16 | public static string RequestIdHeaderName = "x-ms-request-id"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/Http/ContextRequestHandler.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | #if !NET40 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Net.Http; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | using Microsoft.Diagnostics.Context; 13 | 14 | namespace Microsoft.Diagnostics.Correlation.Common.Http 15 | { 16 | /// 17 | /// Provides to inject generic correlation context onto the outgoing request 18 | /// 19 | /// Type of correlation context 20 | public class ContextRequestHandler : DelegatingHandler 21 | { 22 | private readonly IEnumerable> contextInjectors; 23 | 24 | /// 25 | /// ContextRequestHandler constructor 26 | /// 27 | /// Collection of to be used for header injection 28 | public ContextRequestHandler(IEnumerable> contextInjectors) 29 | { 30 | if (contextInjectors == null) 31 | throw new ArgumentNullException(nameof(contextInjectors)); 32 | this.contextInjectors = new List>(contextInjectors); //prevent list modification 33 | } 34 | 35 | /// 36 | /// ContextRequestHandler constructor 37 | /// 38 | /// Collection of to be used for header injection 39 | /// Inner handler to be called after ContextRequestHandler 40 | public ContextRequestHandler(IEnumerable> contextInjectors, 41 | HttpMessageHandler innerHandler) : base(innerHandler) 42 | { 43 | if (contextInjectors == null) 44 | throw new ArgumentNullException(nameof(contextInjectors)); 45 | this.contextInjectors = new List>(contextInjectors); //prevent list modification 46 | } 47 | 48 | protected override Task SendAsync(HttpRequestMessage request, 49 | CancellationToken cancellationToken) 50 | { 51 | var ctx = ContextResolver.GetContext(); 52 | if (ctx != null) 53 | { 54 | foreach (var injector in contextInjectors) 55 | { 56 | injector.UpdateRequest(ctx, request); 57 | } 58 | } 59 | 60 | return base.SendAsync(request, cancellationToken); 61 | } 62 | } 63 | } 64 | #endif -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/Http/CorrelationContextInjector.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | #if !NET40 7 | using System; 8 | using System.Net.Http; 9 | using Microsoft.Diagnostics.Context; 10 | 11 | namespace Microsoft.Diagnostics.Correlation.Common.Http 12 | { 13 | /// 14 | /// implementation specific to and HttpRequestMessage 15 | /// 16 | /// injects correlation-id header and child-request-id header. Names could be configured with 17 | public class CorrelationContextInjector : IContextInjector 18 | { 19 | /// 20 | /// Injects into 21 | /// 22 | /// to be injected 23 | /// Outgoing request 24 | public void UpdateRequest(CorrelationContext context, HttpRequestMessage request) 25 | { 26 | if (request == null) 27 | throw new ArgumentNullException(nameof(request)); 28 | 29 | if (context == null) 30 | throw new ArgumentNullException(nameof(context)); 31 | 32 | if (request.Headers.Contains(CorrelationHeaderInfo.CorrelationIdHeaderName)) 33 | throw new ArgumentException($"{CorrelationHeaderInfo.CorrelationIdHeaderName} header already exists"); 34 | 35 | request.Headers.Add(CorrelationHeaderInfo.CorrelationIdHeaderName, context.CorrelationId); 36 | request.Headers.Add(CorrelationHeaderInfo.RequestIdHeaderName, Guid.NewGuid().ToString()); 37 | } 38 | } 39 | } 40 | #endif 41 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/Http/CorrelationContextRequestHandler.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | #if !NET40 7 | using System.Collections.Generic; 8 | using System.Net.Http; 9 | using Microsoft.Diagnostics.Context; 10 | 11 | namespace Microsoft.Diagnostics.Correlation.Common.Http 12 | { 13 | /// 14 | /// Provides to inject to to 15 | /// 16 | public class CorrelationContextRequestHandler : ContextRequestHandler 17 | { 18 | /// 19 | /// CorrelationContextRequestHandler constructor 20 | /// 21 | /// Collection of to be used for header injection 22 | public CorrelationContextRequestHandler(IEnumerable> contextInjectors) : 23 | base(contextInjectors) 24 | { 25 | } 26 | 27 | /// 28 | /// CorrelationContextRequestHandler constructor 29 | /// 30 | /// Collection of to be used for header injection 31 | /// Inner handler to be called after CorrelationContextRequestHandler 32 | public CorrelationContextRequestHandler(IEnumerable> contextInjectors, HttpMessageHandler innerHandler) : 33 | base(contextInjectors, innerHandler) 34 | { 35 | } 36 | } 37 | } 38 | #endif -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/Http/CorrelationHttpClientBuilder.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | #if !NET40 7 | using System.Collections.Generic; 8 | using System.Net.Http; 9 | using Microsoft.Diagnostics.Context; 10 | 11 | namespace Microsoft.Diagnostics.Correlation.Common.Http 12 | { 13 | /// 14 | /// Builds HttpClient with in DelegaingHandler's pipeline 15 | /// 16 | public class CorrelationHttpClientBuilder : HttpClientBuilder 17 | { 18 | private static readonly List> Injectors = new List 19 | > 20 | { 21 | new CorrelationContextInjector() 22 | }; 23 | 24 | /// 25 | /// Create HttpClient with single and default 26 | /// 27 | /// 28 | public static HttpClient CreateClient() 29 | { 30 | return CreateClient(Injectors); 31 | } 32 | 33 | /// 34 | /// Create HttpClient with , configured inner HTTP handler and custom DelegatingHandlers 35 | /// 36 | /// Instance of inner 37 | /// Custom handlers to be added to the pipeline after 38 | /// instance 39 | public static HttpClient CreateClient(HttpMessageHandler innerHandler, 40 | params DelegatingHandler[] handlers) 41 | { 42 | return CreateClient(innerHandler, Injectors, handlers); 43 | } 44 | 45 | /// 46 | /// Create HttpClient with , default and collection of custom 47 | /// 48 | /// Custom handlers to be added to the pipeline after 49 | /// instance 50 | public static HttpClient CreateClient(params DelegatingHandler[] handlers) 51 | { 52 | return CreateClient(Injectors, handlers); 53 | } 54 | } 55 | } 56 | #endif -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/Http/EndpointFilter.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text.RegularExpressions; 10 | 11 | namespace Microsoft.Diagnostics.Correlation.Common.Http 12 | { 13 | /// 14 | /// Implements allowing to disable/enable outgoing request instrumentation for list of HTTP endpoints 15 | /// 16 | public class EndpointFilter : IEndpointFilter 17 | { 18 | private readonly HashSet endpoints = new HashSet(); 19 | private readonly bool allow; 20 | 21 | /// 22 | /// Constructs EndpointFilter to disable instrumentation for HTTP requests done to Azure Storage and ApplicationInsights APIs 23 | /// 24 | public EndpointFilter() 25 | { 26 | allow = false; 27 | endpoints.Add(@"core\.windows\.net"); 28 | endpoints.Add(@"dc\.services\.visualstudio\.com"); 29 | } 30 | 31 | /// 32 | /// Constructs EndpointFilter 33 | /// 34 | /// List of Regex patterns for endpoints 35 | /// Allows to instrument enpoints matching the pattern (if set to true) or NOT matching the pattern (if set to false) 36 | public EndpointFilter(IEnumerable endpointPatterns, bool allow = true) 37 | { 38 | if (endpoints == null) return; 39 | 40 | foreach (var endpoint in endpointPatterns) 41 | { 42 | endpoints.Add(endpoint); 43 | } 44 | 45 | this.allow = allow; 46 | } 47 | 48 | /// 49 | /// Adds endpoint pattern 50 | /// 51 | /// Pattern to add 52 | /// Current EndpointFilter 53 | public EndpointFilter AddEndpoint(string endpointPattern) 54 | { 55 | endpoints.Add(endpointPattern); 56 | return this; 57 | } 58 | 59 | /// 60 | /// Validates Uri to check if it should be instrumented 61 | /// 62 | /// Uri to check 63 | /// True if endpoint should be instrumented, false otherwise 64 | public bool Validate(Uri uri) 65 | { 66 | if (endpoints.Count == 0) return true; 67 | 68 | if (endpoints.Any(endpoint => Regex.Match(uri.ToString(), endpoint).Success)) 69 | { 70 | return allow; 71 | } 72 | return !allow; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/Http/HttpClientBuilder.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | #if !NET40 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Net.Http; 11 | 12 | namespace Microsoft.Diagnostics.Correlation.Common.Http 13 | { 14 | /// 15 | /// Provides HttpClient builder with 16 | /// 17 | public class HttpClientBuilder 18 | { 19 | //There is HttpClientFactory class in Microsoft.AspNet.WebApi.Client package 20 | //We implement it here to avoid bringing new dependencies 21 | protected static class HttpClientFactory 22 | { 23 | public static HttpMessageHandler CreatePipeline(HttpMessageHandler innerHandler, IEnumerable handlers) 24 | { 25 | HttpMessageHandler httpMessageHandler = innerHandler; 26 | foreach (var delegatingHandler in handlers.Reverse()) 27 | { 28 | delegatingHandler.InnerHandler = httpMessageHandler; 29 | httpMessageHandler = delegatingHandler; 30 | } 31 | return httpMessageHandler; 32 | } 33 | } 34 | 35 | /// 36 | /// Creates HttpClient with and custom DelegatingHandlers 37 | /// 38 | /// Type of correlation context 39 | /// Collection of to be used for headers injection 40 | /// Custom handlers to be added to the HttpClient pipeline after 41 | /// HttpClient instance 42 | public static HttpClient CreateClient(IEnumerable> contextInjectors, 43 | params DelegatingHandler[] handlers) 44 | { 45 | HttpMessageHandler innerHandler = new HttpClientHandler(); 46 | return CreateClient(innerHandler, contextInjectors, handlers); 47 | } 48 | 49 | /// 50 | /// Creates HttpClient with ContextRequestHandler, configured inner HTTP handler and custom DelegatingHandlers 51 | /// 52 | /// Type of correlation context 53 | /// Instance of inner HttpMessageHandler 54 | /// Collection of to be used for headers injection 55 | /// Custom handlers to be added to the HttpClient pipeline after 56 | /// HttpClient instance 57 | public static HttpClient CreateClient(HttpMessageHandler innerHandler, 58 | IEnumerable> contextInjectors, 59 | params DelegatingHandler[] handlers) 60 | { 61 | if (innerHandler == null) 62 | throw new ArgumentNullException(nameof(innerHandler)); 63 | 64 | var allHandlers = new List { new ContextRequestHandler(contextInjectors) }; 65 | if (handlers != null) 66 | allHandlers.AddRange(handlers); 67 | 68 | var pipeline = HttpClientFactory.CreatePipeline(innerHandler, allHandlers); 69 | return new HttpClient(pipeline); 70 | } 71 | } 72 | } 73 | #endif -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/Http/HttpRequestMessageExtensions.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | #if !NET40 7 | using System.Linq; 8 | using System.Net.Http; 9 | 10 | namespace Microsoft.Diagnostics.Correlation.Common.Http 11 | { 12 | /// 13 | /// Provides HttpRequestMessage extensions to work with child request id 14 | /// 15 | public static class HttpRequestMessageExtensions 16 | { 17 | /// 18 | /// Gets child request id from the 19 | /// 20 | /// containing child request id 21 | /// Child request id or null 22 | public static string GetChildRequestId(this HttpRequestMessage request) 23 | { 24 | if (request.Headers.Contains(CorrelationHeaderInfo.RequestIdHeaderName)) 25 | return request.Headers.GetValues(CorrelationHeaderInfo.RequestIdHeaderName).First(); 26 | 27 | return null; 28 | } 29 | } 30 | } 31 | #endif -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/IContextFactory.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | namespace Microsoft.Diagnostics.Correlation.Common 7 | { 8 | /// 9 | /// Creates context from request 10 | /// 11 | /// Type of context 12 | /// Type of request 13 | public interface IContextFactory 14 | { 15 | /// 16 | /// Creates correlation context from the request 17 | /// 18 | /// HTTP request 19 | /// Correlation context 20 | TContext CreateContext(TRequest request); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/IContextInjector.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | namespace Microsoft.Diagnostics.Correlation.Common 7 | { 8 | /// 9 | /// Injects context into request 10 | /// 11 | /// Type of correlation context 12 | /// Type of HTTP request 13 | public interface IContextInjector 14 | { 15 | /// 16 | /// Injects TContext into TRequest 17 | /// 18 | /// Generic correlation context instance to be injected into request 19 | /// Outgoing request instance 20 | void UpdateRequest(TContext ctx, TRequest request); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/IEndpointFilter.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | 8 | namespace Microsoft.Diagnostics.Correlation.Common 9 | { 10 | /// 11 | /// Validates outgoing request Uri determining if it should be instrumented 12 | /// 13 | public interface IEndpointFilter 14 | { 15 | /// 16 | /// Validates Uri to check if it should be instrumented 17 | /// 18 | /// Uri to check 19 | /// True if endoiunt should be instrumented, false otherwise 20 | bool Validate(Uri uri); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/Instrumentation/Configuration.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System.Collections.Generic; 7 | using Microsoft.Diagnostics.Context; 8 | 9 | namespace Microsoft.Diagnostics.Correlation.Common.Instrumentation 10 | { 11 | /// 12 | /// Provides generic instrumentation configuration: set of factory, injectors and other instrumetnation parameters 13 | /// 14 | /// Type of correlation context 15 | /// Type of ougoing request 16 | /// Type of response to outgoing request 17 | public class Configuration where TContext : ICorrelationContext 18 | { 19 | /// 20 | /// Optional to control which requests to instrument based on their Uri 21 | /// is used by default 22 | /// 23 | public IEndpointFilter EndpointFilter { get; set; } 24 | 25 | /// 26 | /// Optional notifies about outgoing request events 27 | /// Could be used for logging 28 | /// 29 | public IOutgoingRequestNotifier RequestNotifier { get; set; } 30 | 31 | private IEnumerable> contextInjectors; 32 | 33 | /// 34 | /// Collection of to inject headers into outgoing request 35 | /// 36 | public IEnumerable> ContextInjectors 37 | { 38 | get { return contextInjectors; } 39 | set { contextInjectors = new List>(value); } 40 | } 41 | 42 | /// 43 | /// Sets 44 | /// 45 | /// instance 46 | /// Current for chaining 47 | public Configuration WithEndpointValidator(IEndpointFilter endpointFilter) 48 | { 49 | EndpointFilter = endpointFilter; 50 | return this; 51 | } 52 | 53 | /// 54 | /// Sets 55 | /// 56 | /// instance 57 | /// Current for chaining 58 | public Configuration WithOutgoingRequestNotifier( 59 | IOutgoingRequestNotifier requestNotifier) 60 | { 61 | RequestNotifier = requestNotifier; 62 | return this; 63 | } 64 | 65 | /// 66 | /// Sets collection of 67 | /// 68 | /// collection of 69 | /// Current for chaining 70 | public Configuration WithContextInjectors( 71 | IEnumerable> injectors) 72 | { 73 | contextInjectors = new List>(injectors); //prevent list modification 74 | return this; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/Instrumentation/IOutgoingRequestNotifier.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | namespace Microsoft.Diagnostics.Correlation.Common.Instrumentation 7 | { 8 | /// 9 | /// Notifies about outgoing request events, implement this interface to log outgoing requests when using instrumentation 10 | /// 11 | /// Type of correlation context 12 | /// Type of outgoing request 13 | /// Type of outgoing response 14 | public interface IOutgoingRequestNotifier 15 | { 16 | /// 17 | /// Corresponds to the moment reqest is about to be sent 18 | /// 19 | /// Correlation context containing child request id 20 | /// Request instance 21 | void OnBeforeRequest(TContext context, TRequest request); 22 | 23 | /// 24 | /// Corresponds to the moment, response is received 25 | /// 26 | /// Correlation context containing child request id 27 | /// Response instance 28 | void OnAfterResponse(TContext context, TResponse response); 29 | } 30 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/Microsoft.Diagnostics.Correlation.Common.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 10 | 2176f777-d4e6-49d1-8f68-116c37f782c6 11 | Microsoft.Diagnostics.Correlation.Common 12 | .\obj 13 | .\bin\ 14 | v4.6.1 15 | 16 | 17 | 18 | 2.0 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Common/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "dependencies": { 4 | "Microsoft.Diagnostics.Context": "1.0.0-*" 5 | }, 6 | "frameworks": { 7 | "netstandard1.6": { 8 | "imports": "dnxcore50", 9 | "dependencies": { 10 | "NETStandard.Library": "1.6.0" 11 | } 12 | }, 13 | "net46": { 14 | "frameworkAssemblies": { 15 | "System.Net.Http": "4.0.0.0" 16 | } 17 | }, 18 | "net45": { 19 | "frameworkAssemblies": { 20 | "System.Net.Http": "4.0.0.0" 21 | } 22 | }, 23 | "net40": {} 24 | }, 25 | "packOptions": { 26 | "owners": [ "Microsoft" ], 27 | "summary": "Cross-service telemetry correlation library: common cross-platform code", 28 | "tags": [ 29 | "Microsoft, Diagnostics, Correlation" 30 | ], 31 | "requireLicenseAcceptance": true, 32 | "licenseUrl": "https://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm" 33 | }, 34 | "buildOptions": { 35 | "keyFile": "../../PublicKey.snk", 36 | "delaySign": true 37 | } 38 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Instrumentation/ContextTracingInstrumentation.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | using Microsoft.Diagnostics.Instrumentation.Extensions.Intercept; 8 | using System.Net; 9 | using Microsoft.Diagnostics.Context; 10 | using Microsoft.Diagnostics.Correlation.Common.Instrumentation; 11 | using Microsoft.Diagnostics.Correlation.Http; 12 | 13 | namespace Microsoft.Diagnostics.Correlation.Instrumentation 14 | { 15 | /// 16 | /// Implements outgoing HTTP requests instrumentation with profiler 17 | /// 18 | public class ContextTracingInstrumentation 19 | { 20 | /// 21 | /// Enables outgoing request instrumentation: injects in outgoing HttpClient call or WebRequest 22 | /// 23 | /// instance 24 | public static void Enable(ProfilerCorrelationConfiguration configuration) 25 | { 26 | Enable(configuration); 27 | } 28 | 29 | /// 30 | /// Enables outgoing request instrumentation: inject generic correlation context in outgoing or call 31 | /// 32 | /// Type of correlation context 33 | /// Collection of to inject context into outgoing request 34 | public static void Enable(Configuration configuration) where TContext : ICorrelationContext 35 | { 36 | if (configuration == null) 37 | throw new ArgumentNullException(nameof(configuration)); 38 | 39 | if (configuration.ContextInjectors == null) 40 | throw new ArgumentNullException(nameof(configuration.ContextInjectors)); 41 | 42 | if (!Decorator.IsHostEnabled()) 43 | { 44 | throw new InvalidOperationException("Profiler is not available on the host"); 45 | } 46 | 47 | var extesionBaseDirectory = string.IsNullOrWhiteSpace(AppDomain.CurrentDomain.RelativeSearchPath) 48 | ? AppDomain.CurrentDomain.BaseDirectory 49 | : AppDomain.CurrentDomain.RelativeSearchPath; 50 | Decorator.InitializeExtension(extesionBaseDirectory); 51 | 52 | Decorator.Decorate( 53 | "System", 54 | "System.dll", 55 | "System.Net.HttpWebRequest.BeginGetResponse", 56 | 2, 57 | (thisObj, callback, state) => OnBeginGetResponse(thisObj, configuration), 58 | null, 59 | null); 60 | 61 | Decorator.Decorate( 62 | "System", 63 | "System.dll", 64 | "System.Net.HttpWebRequest.EndGetResponse", 65 | 1, 66 | null, 67 | (context, returnValue, thisObj, asyncResult) => OnEndGetResponse(context, returnValue, thisObj, asyncResult, configuration), 68 | null); 69 | 70 | Decorator.Decorate( 71 | "System", 72 | "System.dll", 73 | "System.Net.HttpWebRequest.GetResponse", 74 | 0, 75 | thisObj => OnBeginGetResponse(thisObj, configuration), 76 | (context, returnValue, thisObj) => OnEndGetResponse(context, returnValue, thisObj, null, configuration), 77 | null); 78 | } 79 | 80 | private static object OnBeginGetResponse(object requestObj, Configuration config) where TContext : ICorrelationContext 81 | { 82 | var request = requestObj as HttpWebRequest; 83 | 84 | if (request != null) 85 | { 86 | if (config.EndpointFilter.Validate(request.RequestUri)) 87 | { 88 | var ctx = ContextResolver.GetContext(); 89 | if (ctx != null) 90 | { 91 | foreach (var injector in config.ContextInjectors) 92 | { 93 | injector.UpdateRequest(ctx, request); 94 | } 95 | 96 | try 97 | { 98 | config.RequestNotifier?.OnBeforeRequest(ctx.GetChildRequestContext(request.GetChildRequestId()), request); 99 | } 100 | catch (Exception) 101 | { 102 | //ignored 103 | } 104 | } 105 | } 106 | } 107 | 108 | return requestObj; 109 | } 110 | 111 | private static object OnEndGetResponse(object context, object returnValue, object thisObj, object asyncResult, Configuration config) where TContext : ICorrelationContext 112 | { 113 | var response = returnValue as WebResponse; 114 | var request = thisObj as WebRequest; 115 | if (request != null && response != null) 116 | { 117 | if (config.EndpointFilter.Validate(request.RequestUri)) 118 | { 119 | 120 | var ctx = ContextResolver.GetContext(); 121 | try 122 | { 123 | config.RequestNotifier?.OnAfterResponse( 124 | ctx.GetChildRequestContext(request.GetChildRequestId()), response); 125 | } 126 | catch (Exception) 127 | { 128 | //ignored 129 | } 130 | } 131 | } 132 | return returnValue; 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Instrumentation/Microsoft.Diagnostics.Correlation.Instrumentation.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 10 | 7927cb35-6d2c-45d7-972a-10390cbc5cf8 11 | Microsoft.Diagnostics.Correlation.Instrumentation 12 | .\obj 13 | .\bin\ 14 | v4.6.1 15 | 16 | 17 | 18 | 2.0 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Instrumentation/ProfilerConfiguration.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System.Net; 7 | using Microsoft.Diagnostics.Context; 8 | using Microsoft.Diagnostics.Correlation.Common.Http; 9 | using Microsoft.Diagnostics.Correlation.Common.Instrumentation; 10 | 11 | namespace Microsoft.Diagnostics.Correlation.Instrumentation 12 | { 13 | /// 14 | /// Provides generic configuration for profiler instrumentation 15 | /// 16 | /// Type of correlation context 17 | public class ProfilerConfiguration : Configuration where TContext : ICorrelationContext 18 | { 19 | /// 20 | /// Constructs with default 21 | /// 22 | public ProfilerConfiguration() 23 | { 24 | EndpointFilter = new EndpointFilter(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Instrumentation/ProfilerCorrelationConfiguration.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System.Collections.Generic; 7 | using System.Net; 8 | using Microsoft.Diagnostics.Context; 9 | using Microsoft.Diagnostics.Correlation.Common; 10 | using Microsoft.Diagnostics.Correlation.Http; 11 | 12 | namespace Microsoft.Diagnostics.Correlation.Instrumentation 13 | { 14 | /// 15 | /// Provides default configuration for profiler instrumentation, configures to be used 16 | /// 17 | public class ProfilerCorrelationConfiguration : ProfilerConfiguration 18 | { 19 | /// 20 | /// constructor, sets up default and 21 | /// 22 | public ProfilerCorrelationConfiguration() 23 | { 24 | ContextInjectors = new List> 25 | { 26 | new WebRequestCorrelationContextInjector() 27 | }; 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Instrumentation/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | 4 | "dependencies": { 5 | "Microsoft.Diagnostics.Correlation": "1.0.0-*", 6 | "Microsoft.ApplicationInsights.Agent.Intercept": "2.0.1" 7 | }, 8 | 9 | "frameworks": { 10 | "net46": {}, 11 | "net45": {}, 12 | "net40": {} 13 | }, 14 | "packOptions": { 15 | "owners": [ "Microsoft" ], 16 | "summary": "Cross-service telemetry correlation library: profiler instrumentation", 17 | "tags": [ 18 | "Microsoft, Diagnostics, Correlation" 19 | ], 20 | "requireLicenseAcceptance": true, 21 | "licenseUrl": "https://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm" 22 | }, 23 | "buildOptions": { 24 | "keyFile": "../../PublicKey.snk", 25 | "delaySign": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Mvc/CorrelationTracingFilter.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System.Web; 7 | using System.Web.Mvc; 8 | using Microsoft.Diagnostics.Context; 9 | using Microsoft.Diagnostics.Correlation.Http; 10 | 11 | namespace Microsoft.Diagnostics.Correlation.Mvc 12 | { 13 | /// 14 | /// Provides MVC to extract from HttpContext.Current 15 | /// 16 | public class CorrelationTracingFilter : ActionFilterAttribute 17 | { 18 | private readonly CorrelationContextFactory contextFactory; 19 | 20 | /// 21 | /// CorrelationTracingFilter constructor 22 | /// 23 | public CorrelationTracingFilter() 24 | { 25 | contextFactory = new CorrelationContextFactory(); 26 | } 27 | 28 | /// 29 | /// Inherited from 30 | /// 31 | /// 32 | public override void OnActionExecuting(ActionExecutingContext filterContext) 33 | { 34 | var ctx = contextFactory.CreateContext(HttpContext.Current.Request); 35 | ContextResolver.SetContext(ctx); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Mvc/Microsoft.Diagnostics.Correlation.Mvc.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0.25420 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 3210c35e-73d1-44bd-abf9-1628ad75eeed 10 | Microsoft.Diagnostics.Correlation.Mvc 11 | .\obj 12 | .\bin\ 13 | 14 | 15 | 16 | 2.0 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Mvc/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "dependencies": { 4 | "Microsoft.AspNet.Mvc": "3.0.20105.1", 5 | "Microsoft.Diagnostics.Correlation": "1.0.0-*" 6 | }, 7 | "frameworks": { 8 | "net40": {}, 9 | "net45": {}, 10 | "net46": {} 11 | }, 12 | "packOptions": { 13 | "owners": [ "Microsoft" ], 14 | "summary": "Cross-service telemetry correlation library: ASP.NET MVC support", 15 | "tags": [ 16 | "Microsoft, Diagnostics, Correlation, MVC, ASP.NET" 17 | ], 18 | "requireLicenseAcceptance": true, 19 | "licenseUrl": "https://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm" 20 | }, 21 | "buildOptions": { 22 | "keyFile": "../../PublicKey.snk", 23 | "delaySign": true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.Signing/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.WebApi/CorrelationTracingFilter.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System.Web; 7 | using System.Web.Http.Controllers; 8 | using System.Web.Http.Filters; 9 | using Microsoft.Diagnostics.Context; 10 | using Microsoft.Diagnostics.Correlation.Http; 11 | 12 | namespace Microsoft.Diagnostics.Correlation.WebApi 13 | { 14 | /// 15 | /// Provides WebApi to extract from HttpContext.Current 16 | /// 17 | public class CorrelationTracingFilter : ActionFilterAttribute 18 | { 19 | private readonly CorrelationContextFactory contextFactory; 20 | 21 | /// 22 | /// CorrelationTracingFilter constructor 23 | /// 24 | public CorrelationTracingFilter() 25 | { 26 | contextFactory = new CorrelationContextFactory(); 27 | } 28 | 29 | /// 30 | /// Inherited from 31 | /// 32 | /// 33 | public override void OnActionExecuting(HttpActionContext filterContext) 34 | { 35 | var ctx = contextFactory.CreateContext(HttpContext.Current.Request); 36 | ContextResolver.SetContext(ctx); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.WebApi/Microsoft.Diagnostics.Correlation.WebApi.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0.25420 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 0a9ec44d-11fb-4f9c-8747-f7de81af8481 10 | Microsoft.Diagnostics.Correlation.WebApi 11 | .\obj 12 | .\bin\ 13 | 14 | 15 | 16 | 2.0 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation.WebApi/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "dependencies": { 4 | "Microsoft.AspNet.WebApi.Core": "4.0.20505", 5 | "Microsoft.Diagnostics.Correlation": "1.0.0-*" 6 | }, 7 | "frameworks": { 8 | "net40": {}, 9 | "net45": {}, 10 | "net46": {} 11 | }, 12 | "packOptions": { 13 | "owners": [ "Microsoft" ], 14 | "summary": "Cross-service telemetry correlation library: ASP.NET WebApi support", 15 | "tags": [ 16 | "Microsoft, Diagnostics, Correlation, WebApi, ASP.NET" 17 | ], 18 | "requireLicenseAcceptance": true, 19 | "licenseUrl": "https://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm" 20 | }, 21 | "buildOptions": { 22 | "keyFile": "../../PublicKey.snk", 23 | "delaySign": true 24 | } 25 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation/Http/CorrelationContextFactory.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | using System.Linq; 8 | using Microsoft.Diagnostics.Context; 9 | using Microsoft.Diagnostics.Correlation.Common; 10 | using System.Web; 11 | 12 | 13 | namespace Microsoft.Diagnostics.Correlation.Http 14 | { 15 | /// 16 | /// Implementation to extract from 17 | /// 18 | public class CorrelationContextFactory : IContextFactory 19 | { 20 | /// 21 | /// Extracts from 22 | /// 23 | /// Incoming 24 | /// Extracted context 25 | public CorrelationContext CreateContext(HttpRequest request) 26 | { 27 | if (request == null) 28 | throw new ArgumentNullException(nameof(request)); 29 | 30 | string correlationId = getHeaderValue(request, CorrelationHeaderInfo.CorrelationIdHeaderName) ?? 31 | newGuid(); 32 | string requestId = getHeaderValue(request, CorrelationHeaderInfo.RequestIdHeaderName) ?? 33 | getWorkerTraceIdentifier(request); 34 | 35 | return new CorrelationContext(correlationId, requestId ?? newGuid()); 36 | } 37 | 38 | private string getHeaderValue(HttpRequest request, string name) 39 | { 40 | var requestHeader = request.Headers.GetValues(name); 41 | return requestHeader?.First(); 42 | } 43 | 44 | private string getWorkerTraceIdentifier(HttpRequest request) 45 | { 46 | var httpWorkerRequest = (HttpWorkerRequest)request.RequestContext.HttpContext.GetService(typeof(HttpWorkerRequest)); 47 | return httpWorkerRequest?.RequestTraceIdentifier.ToString(); 48 | } 49 | 50 | private string newGuid() 51 | { 52 | return Guid.NewGuid().ToString(); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation/Http/CorrelationTracingHttpModule.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | using System.Web; 8 | using Microsoft.Diagnostics.Context; 9 | 10 | namespace Microsoft.Diagnostics.Correlation.Http 11 | { 12 | /// 13 | /// implementation for incoming request handling 14 | /// 15 | public sealed class CorrelationTracingHttpModule : IHttpModule 16 | { 17 | private readonly CorrelationContextFactory factory = new CorrelationContextFactory(); 18 | 19 | /// 20 | /// Inherited from 21 | /// 22 | /// 23 | public void Init(HttpApplication context) 24 | { 25 | context.BeginRequest += application_BeginRequest; 26 | } 27 | 28 | /// 29 | /// Inherited from 30 | /// 31 | public void Dispose() 32 | { 33 | 34 | } 35 | 36 | private void application_BeginRequest(object source, 37 | EventArgs e) 38 | { 39 | HttpApplication application = (HttpApplication)source; 40 | var ctx = factory.CreateContext(application.Context.Request); 41 | if (ctx != null) 42 | ContextResolver.SetContext(ctx); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation/Http/WebRequestCorrelationContextInjector.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System; 7 | using System.Net; 8 | using Microsoft.Diagnostics.Context; 9 | using Microsoft.Diagnostics.Correlation.Common; 10 | 11 | namespace Microsoft.Diagnostics.Correlation.Http 12 | { 13 | /// 14 | /// implementation specific to and 15 | /// 16 | public class WebRequestCorrelationContextInjector : IContextInjector 17 | { 18 | /// 19 | /// Injects context into outgoing request 20 | /// 21 | /// Context to inject 22 | /// Outgoing request instance 23 | public void UpdateRequest(CorrelationContext context, WebRequest request) 24 | { 25 | if (request == null) 26 | throw new ArgumentNullException(nameof(request)); 27 | 28 | if (context == null) 29 | throw new ArgumentNullException(nameof(context)); 30 | 31 | if (request.Headers.GetValues(CorrelationHeaderInfo.CorrelationIdHeaderName) != null) 32 | throw new ArgumentException(CorrelationHeaderInfo.CorrelationIdHeaderName + " header already exists"); 33 | 34 | request.Headers.Add(CorrelationHeaderInfo.CorrelationIdHeaderName, context.CorrelationId); 35 | request.Headers.Add(CorrelationHeaderInfo.RequestIdHeaderName, Guid.NewGuid().ToString()); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation/Http/WebRequestExtensions.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | using System.Linq; 7 | using System.Net; 8 | using Microsoft.Diagnostics.Correlation.Common; 9 | 10 | namespace Microsoft.Diagnostics.Correlation.Http 11 | { 12 | public static class WebRequestExtensions 13 | { 14 | /// 15 | /// Gets child request id from the 16 | /// 17 | /// containing child request id 18 | /// Child request id or null 19 | public static string GetChildRequestId(this WebRequest request) 20 | { 21 | var requestIdHeader = request.Headers.GetValues(CorrelationHeaderInfo.RequestIdHeaderName); 22 | return requestIdHeader?.First(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation/Microsoft.Diagnostics.Correlation.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 13520fb4-519d-4d3f-9ad9-4ed05f1f7bc4 10 | Microsoft.Diagnostics.Correlation 11 | .\obj 12 | .\bin\ 13 | v4.6.1 14 | 15 | 16 | 2.0 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation/Owin/ContextTracingMiddleware.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | #if !NET40 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Threading.Tasks; 10 | using Microsoft.Diagnostics.Context; 11 | using Microsoft.Diagnostics.Correlation.Common; 12 | using AppFunc = System.Func, System.Threading.Tasks.Task>; 13 | 14 | namespace Microsoft.Diagnostics.Correlation.Owin 15 | { 16 | /// 17 | /// Provides OWIN middleware to extract and retain generic correlation context from the incoming request 18 | /// 19 | /// Type of context 20 | public class ContextTracingMiddleware 21 | { 22 | private readonly AppFunc next; 23 | private readonly IContextFactory> contextFactory; 24 | 25 | /// 26 | /// Middleware constructor 27 | /// 28 | /// Next middleware 29 | /// Implementation of to be used for request parsing 30 | public ContextTracingMiddleware(AppFunc next, IContextFactory> contextFactory) 31 | { 32 | if (contextFactory == null) 33 | throw new ArgumentNullException(nameof(contextFactory)); 34 | 35 | this.next = next; 36 | this.contextFactory = contextFactory; 37 | } 38 | 39 | public async Task Invoke(IDictionary environment) 40 | { 41 | try 42 | { 43 | var ctx = contextFactory.CreateContext(environment); 44 | ContextResolver.SetContext(ctx); 45 | 46 | await next.Invoke(environment).ConfigureAwait(false); 47 | } 48 | finally 49 | { 50 | ContextResolver.ClearContext(); 51 | } 52 | } 53 | } 54 | } 55 | #endif -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation/Owin/CorrelationTracingMiddleware.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | #if !NET40 7 | using Microsoft.Diagnostics.Context; 8 | using AppFunc = System.Func, System.Threading.Tasks.Task>; 9 | 10 | namespace Microsoft.Diagnostics.Correlation.Owin 11 | { 12 | /// 13 | /// Provides OWIN middleware to extract and retain from the incoming request 14 | /// 15 | public class CorrelationContextTracingMiddleware : ContextTracingMiddleware 16 | { 17 | /// 18 | /// Middleware constructor 19 | /// 20 | /// Next middleware 21 | public CorrelationContextTracingMiddleware(AppFunc next) : base(next, new OwinCorrelationContextFactory()) 22 | { 23 | } 24 | } 25 | } 26 | #endif -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation/Owin/OwinCorrelationContextFactory.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. 4 | // ------------------------------------------------------------ 5 | 6 | #if !NET40 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using Microsoft.Diagnostics.Context; 11 | using Microsoft.Diagnostics.Correlation.Common; 12 | 13 | namespace Microsoft.Diagnostics.Correlation.Owin 14 | { 15 | /// 16 | /// OWIN-specific implementation of for 17 | /// 18 | public class OwinCorrelationContextFactory : IContextFactory> 19 | { 20 | /// 21 | /// Creates CorrelationContext from OWIN environment 22 | /// 23 | /// OWIN environment 24 | /// 25 | public CorrelationContext CreateContext(IDictionary environment) 26 | { 27 | if (environment == null) 28 | throw new ArgumentNullException(nameof(environment)); 29 | 30 | object headersObj; 31 | string correlationId = null; 32 | string requestId = null; 33 | if (environment.TryGetValue("owin.RequestHeaders", out headersObj)) 34 | { 35 | var requestHeaders = headersObj as IDictionary; 36 | if (requestHeaders != null) 37 | { 38 | correlationId = getHeaderValue(requestHeaders, CorrelationHeaderInfo.CorrelationIdHeaderName); 39 | requestId = getHeaderValue(requestHeaders, CorrelationHeaderInfo.RequestIdHeaderName); 40 | } 41 | } 42 | 43 | object requestIdObj; 44 | if (environment.TryGetValue("owin.RequestId", out requestIdObj)) 45 | { 46 | if (requestId == null) 47 | requestId = (string)requestIdObj; 48 | } 49 | else 50 | { 51 | requestId = Guid.NewGuid().ToString(); 52 | environment.Add("owin.RequestId", requestId); 53 | } 54 | 55 | return new CorrelationContext(correlationId ?? Guid.NewGuid().ToString(), requestId); 56 | } 57 | 58 | private string getHeaderValue(IDictionary requestHeaders, string name) 59 | { 60 | string[] header; 61 | return requestHeaders.TryGetValue(name, out header) ? header.First() : null; 62 | } 63 | } 64 | } 65 | #endif -------------------------------------------------------------------------------- /src/Microsoft.Diagnostics.Correlation/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "dependencies": { 4 | "Microsoft.Diagnostics.Correlation.Common": "1.0.0-*" 5 | }, 6 | "frameworks": { 7 | "net46": { 8 | "frameworkAssemblies": { 9 | "System.Web": "4.0.0.0" 10 | } 11 | }, 12 | "net45": { 13 | "frameworkAssemblies": { 14 | "System.Web": "4.0.0.0" 15 | } 16 | }, 17 | "net40": { 18 | "frameworkAssemblies": { 19 | "System.Web": "4.0.0.0" 20 | } 21 | } 22 | }, 23 | "packOptions": { 24 | "owners": [ "Microsoft" ], 25 | "summary": "Cross-service telemetry correlation library for web applications", 26 | "tags": [ 27 | "Microsoft, Diagnostics, Correlation" 28 | ], 29 | "requireLicenseAcceptance": true, 30 | "licenseUrl": "https://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm" 31 | }, 32 | "buildOptions": { 33 | "keyFile": "../../PublicKey.snk", 34 | "delaySign": true 35 | } 36 | } -------------------------------------------------------------------------------- /targets/DotNet.Web/Microsoft.DotNet.Web.targets: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | {8995EEE9-F6C2-4122-ACA7-19384033A7B1} 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | BrowseObject 23 | 24 | 25 | BrowseObject 26 | 27 | 28 | -------------------------------------------------------------------------------- /targets/DotNet.Web/en-US/web.general.browseobject.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /targets/DotNet/Microsoft.DotNet.Extensions.targets: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 16 | 17 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /targets/DotNet/Microsoft.DotNet.Tasks.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/diagnostics-correlation/91a6f7ae19d884f299e090844b9d1779f953ca59/targets/DotNet/Microsoft.DotNet.Tasks.dll -------------------------------------------------------------------------------- /targets/DotNet/Microsoft.DotNet.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | $(MSBuildThisFileDirectory) 6 | 7 | v4.5.1 8 | Client 9 | .NETFramework,Version=$(TargetFrameworkVersion) 10 | 11 | 12 | true 13 | 14 | $(MSBuildProjectName) 15 | $(Name) 16 | $(Name) 17 | Debug 18 | AnyCPU 19 | 20 | 21 | 22 | 23 | False 24 | 25 | 26 | -------------------------------------------------------------------------------- /targets/DotNet/Microsoft.DotNet.targets: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | {1FAF1D54-1A80-4E4F-9050-D6B7965CD433} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | BrowseObject 17 | 18 | 19 | BrowseObject 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /targets/DotNet/Microsoft.VisualStudio.ProjectSystem.DotNet.Runtime.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/diagnostics-correlation/91a6f7ae19d884f299e090844b9d1779f953ca59/targets/DotNet/Microsoft.VisualStudio.ProjectSystem.DotNet.Runtime.dll -------------------------------------------------------------------------------- /targets/DotNet/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/diagnostics-correlation/91a6f7ae19d884f299e090844b9d1779f953ca59/targets/DotNet/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /targets/DotNet/en-US/Content.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 13 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/EmbeddedResource.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 23 | 24 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/ProjectDebugger.xaml: -------------------------------------------------------------------------------- 1 |  2 | 14 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 0F86238E-77AC-4AD8-BFEB-0CE949BF11A1 29 | 0x100 30 | ActiveDebugProfile 31 | 32 | 33 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/ProjectItemsSchema.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 5 | 6 | 10 | 11 | 12 | 17 | 18 | 23 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/ResolvedDesignTimeHostReferences.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 22 | 23 | 24 | 30 | 31 | 32 | 38 | 39 | 40 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/csharp.browseobject.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/csharp.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/debugger_general.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/folder.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/general.browseobject.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/general_file.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/none.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/scc.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /targets/DotNet/en-US/typescript.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 11 | 12 | 13 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.AspNetCore.Test/ContextTracingInstumentationListenerTests.cs: -------------------------------------------------------------------------------- 1 | #if NETCOREAPP1_0 2 | using System; 3 | using System.Net.Http; 4 | using System.Threading.Tasks; 5 | using Microsoft.Diagnostics.Context; 6 | using Microsoft.Diagnostics.Correlation.Common; 7 | using Microsoft.Diagnostics.Correlation.Common.Http; 8 | using Microsoft.Diagnostics.Correlation.Common.Instrumentation; 9 | using Microsoft.Extensions.Configuration; 10 | using Xunit; 11 | 12 | namespace Microsoft.Diagnostics.Correlation.AspNetCore.Test 13 | { 14 | public class ContextTracingInstumentationListenerTests 15 | { 16 | [Fact] 17 | public void ConfigurationNull() 18 | { 19 | Assert.Throws( 20 | () => ContextTracingInstrumentation.Enable((AspNetCoreCorrelationConfiguration) null)); 21 | } 22 | 23 | [Fact] 24 | public void IConfigurationNull() 25 | { 26 | Assert.Throws(() => ContextTracingInstrumentation.Enable((IConfiguration) null)); 27 | } 28 | 29 | [Fact] 30 | public void ContextFactoryNull() 31 | { 32 | var config = new AspNetCoreCorrelationConfiguration() 33 | .WithContextFactory(null); 34 | 35 | Assert.Throws(() => ContextTracingInstrumentation.Enable(config)); 36 | } 37 | 38 | [Fact] 39 | public void ContextInjectorNull() 40 | { 41 | var config = new AspNetCoreConfiguration(); 42 | 43 | Assert.Throws(() => ContextTracingInstrumentation.Enable(config)); 44 | } 45 | 46 | [Fact] 47 | public async Task SuccessFlowCustomInjector() 48 | { 49 | var injector = new InjectorMock(); 50 | 51 | var config = new AspNetCoreCorrelationConfiguration() 52 | .WithContextInjectors(new[] {injector}); 53 | 54 | ContextTracingInstrumentation.Enable(config); 55 | 56 | var correlationId = Guid.NewGuid().ToString(); 57 | ContextResolver.SetContext(new CorrelationContext(correlationId)); 58 | 59 | var client = new HttpClient(); 60 | await client.GetAsync("http://bing.com"); 61 | Assert.True(injector.WasCalled); 62 | } 63 | 64 | [Fact] 65 | public async Task SuccessFlowCustomInjectorBlockedEndpoint() 66 | { 67 | var injector = new InjectorMock(); 68 | var validator = new EndpointFilter(); 69 | validator.AddEndpoint("google.com"); 70 | 71 | var config = new AspNetCoreCorrelationConfiguration() 72 | .WithEndpointValidator(validator); 73 | 74 | ContextTracingInstrumentation.Enable(config); 75 | 76 | var correlationId = Guid.NewGuid().ToString(); 77 | ContextResolver.SetContext(new CorrelationContext(correlationId)); 78 | 79 | var client = new HttpClient(); 80 | await client.GetAsync("http://google.com"); 81 | Assert.False(injector.WasCalled); 82 | } 83 | 84 | [Fact] 85 | public async Task SuccessFlowNotifier() 86 | { 87 | var notifier = new RequestNotifier(); 88 | var config = new AspNetCoreCorrelationConfiguration().WithOutgoingRequestNotifier(notifier); 89 | ContextTracingInstrumentation.Enable(config); 90 | 91 | var correlationId = Guid.NewGuid().ToString(); 92 | ContextResolver.SetContext(new CorrelationContext(correlationId)); 93 | 94 | var client = new HttpClient(); 95 | await client.GetAsync("http://google.com"); 96 | Assert.True(notifier.BeforeWasCalled); 97 | Assert.True(notifier.AfterWasCalled); 98 | } 99 | 100 | private class InjectorMock : IContextInjector 101 | { 102 | public bool WasCalled { get; private set; } 103 | 104 | public void UpdateRequest(CorrelationContext ctx, HttpRequestMessage request) 105 | { 106 | WasCalled = true; 107 | } 108 | } 109 | 110 | private class RequestNotifier : 111 | IOutgoingRequestNotifier 112 | { 113 | public bool BeforeWasCalled { get; private set; } 114 | public bool AfterWasCalled { get; private set; } 115 | 116 | public void OnBeforeRequest(CorrelationContext context, HttpRequestMessage request) 117 | { 118 | BeforeWasCalled = true; 119 | Assert.NotNull(context.ChildRequestId); 120 | Assert.NotNull(request); 121 | } 122 | 123 | public void OnAfterResponse(CorrelationContext context, HttpResponseMessage response) 124 | { 125 | AfterWasCalled = true; 126 | Assert.NotNull(context.ChildRequestId); 127 | Assert.NotNull(response); 128 | } 129 | } 130 | } 131 | } 132 | #endif -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.AspNetCore.Test/CorrelationContextFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Http; 3 | using Microsoft.Diagnostics.Correlation.Common; 4 | using Moq; 5 | using Xunit; 6 | 7 | namespace Microsoft.Diagnostics.Correlation.AspNetCore.Test 8 | { 9 | public class CorrelationContextFactoryTests 10 | { 11 | private readonly CorrelationContextFactory factory; 12 | 13 | public CorrelationContextFactoryTests() 14 | { 15 | factory = new CorrelationContextFactory(); 16 | } 17 | 18 | [Fact] 19 | public void CreateContextNull() 20 | { 21 | Assert.Throws(() => factory.CreateContext(null)); 22 | } 23 | 24 | [Fact] 25 | public void CreateContextNoHeader() 26 | { 27 | var ctx = factory.CreateContext(createEmptyRequest()); 28 | Assert.NotNull(ctx); 29 | 30 | Guid guid; 31 | Assert.True(Guid.TryParse(ctx.CorrelationId, out guid)); 32 | Assert.True(Guid.TryParse(ctx.RequestId, out guid)); 33 | } 34 | 35 | [Theory] 36 | [InlineData(null, null)] 37 | [InlineData("11111111-1111-1111-1111-111111111111", "22222222-2222-2222-2222-222222222222")] 38 | [InlineData(null, "22222222-2222-2222-2222-222222222222")] 39 | public void CreateContextFromHeader(string requestIdHeader, string requestIdWorker) 40 | { 41 | var correlationId = Guid.NewGuid().ToString(); 42 | var ctx = factory.CreateContext(createRequest(correlationId, requestIdHeader, requestIdWorker)); 43 | Assert.Equal(correlationId, ctx.CorrelationId); 44 | Assert.NotNull(ctx.RequestId); 45 | if (requestIdHeader != null) 46 | Assert.Equal(requestIdHeader, ctx.RequestId); 47 | else if (requestIdWorker != null) 48 | Assert.Equal(requestIdWorker, ctx.RequestId); 49 | } 50 | 51 | private HttpRequest createEmptyRequest() 52 | { 53 | var request = new Mock(); 54 | var context = new Mock(); 55 | request.SetupGet(r => r.Headers).Returns(new HeaderDictionary()); 56 | request.SetupGet(r => r.HttpContext).Returns(context.Object); 57 | return request.Object; 58 | } 59 | 60 | private HttpRequest createRequest(string correlationId, string requestIdHeader, string requestIdTrace) 61 | { 62 | var context = new Mock(); 63 | var request = new Mock(); 64 | var headers = new HeaderDictionary { { CorrelationHeaderInfo.CorrelationIdHeaderName, new[] { correlationId } } }; 65 | if (requestIdHeader != null) 66 | headers.Add(CorrelationHeaderInfo.RequestIdHeaderName, requestIdHeader); 67 | 68 | request.SetupGet(r => r.Headers).Returns(headers); 69 | 70 | if (requestIdTrace != null) 71 | context.SetupGet(r => r.TraceIdentifier).Returns(requestIdTrace); 72 | 73 | request.SetupGet(r => r.HttpContext).Returns(context.Object); 74 | 75 | return request.Object; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.AspNetCore.Test/DummyObserver.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using Microsoft.Diagnostics.Context; 3 | using Microsoft.Diagnostics.Correlation.Common.Instrumentation; 4 | 5 | namespace Microsoft.Diagnostics.Correlation.AspNetCore.Test 6 | { 7 | public class DummyObserver : IOutgoingRequestNotifier where TContext : ICorrelationContext 8 | { 9 | public void OnBeforeRequest(TContext context, HttpRequestMessage request) 10 | { 11 | } 12 | 13 | public void OnAfterResponse(TContext context, HttpResponseMessage response) 14 | { 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.AspNetCore.Test/Microsoft.Diagnostics.Correlation.AspNetCore.Test.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 379fcc4b-cf27-49d3-b96b-cddf65233692 10 | Microsoft.Diagnostics.Correlation.AspNetCore.Test 11 | .\obj 12 | .\bin\ 13 | v4.6.1 14 | 15 | 16 | 2.0 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.AspNetCore.Test/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "dependencies": { 4 | "dotnet-test-xunit": "2.2.0-preview2-build1029", 5 | "Microsoft.Diagnostics.Correlation.AspNetCore": { "target": "project" }, 6 | "Microsoft.Extensions.Configuration": "1.0.0", 7 | "Microsoft.Extensions.Configuration.Json": "1.0.0", 8 | "Moq": "4.6.38-alpha", 9 | "xunit": "2.2.0-beta2-build3300", 10 | "xunit.runner.console": "2.2.0-beta2-build3300", 11 | "xunit.runner.visualstudio": "2.2.0-beta2-build1149" 12 | }, 13 | "testRunner": "xunit", 14 | "frameworks": { 15 | "netcoreapp1.0": { 16 | "dependencies": { 17 | "Microsoft.NETCore.App": { 18 | "type": "platform", 19 | "version": "1.0.0" 20 | } 21 | }, 22 | "imports": [ 23 | "dotnet5.4", 24 | "portable-net451+win8" 25 | ] 26 | }, 27 | "net46": {}, 28 | "net451": {} 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Common.Test/ContextResolverTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Microsoft.Diagnostics.Context; 5 | using Xunit; 6 | 7 | namespace Microsoft.Diagnostics.Correlation.Test 8 | { 9 | public class ContextResolverTests 10 | { 11 | [Fact] 12 | public void ContextResolverEmpty() 13 | { 14 | Assert.Null(ContextResolver.GetContext()); 15 | } 16 | 17 | [Fact] 18 | public void ContextResolverSetGet() 19 | { 20 | var ctx = new TestContext {CorrelationId = "1", OtherId = "2"}; 21 | 22 | ContextResolver.SetContext(ctx); 23 | var gotCtx = ContextResolver.GetContext(); 24 | 25 | TestContextHelper.AssertAreEqual(ctx, gotCtx); 26 | } 27 | 28 | [Fact] 29 | public async Task ContextResolverSetGetAsyncTask() 30 | { 31 | var ctx = new TestContext { CorrelationId = "1", OtherId = "2" }; 32 | 33 | ContextResolver.SetContext(ctx); 34 | 35 | var t = Task.Run(() => ContextResolver.GetContext()); 36 | await t.ConfigureAwait(false); 37 | TestContextHelper.AssertAreEqual(ctx, t.Result); 38 | } 39 | 40 | [Fact] 41 | public void ContextResolverSetOtherThread() 42 | { 43 | var ctx = new TestContext { CorrelationId = "1", OtherId = "2" }; 44 | 45 | ContextResolver.SetContext(ctx); 46 | 47 | TestContext gotCtx = null; 48 | var t = new Thread(() => 49 | { 50 | gotCtx = ContextResolver.GetContext(); 51 | }); 52 | t.Start(); 53 | t.Join(); 54 | 55 | TestContextHelper.AssertAreEqual(ctx, gotCtx); 56 | } 57 | 58 | [Fact] 59 | public void ContextResolverSetClear() 60 | { 61 | var ctx = new TestContext { CorrelationId = "1", OtherId = "2" }; 62 | 63 | ContextResolver.SetContext(ctx); 64 | ContextResolver.ClearContext(); 65 | Assert.Null(ContextResolver.GetContext()); 66 | } 67 | 68 | [Fact] 69 | public void PutStringGetObject() 70 | { 71 | var guid = Guid.NewGuid().ToString(); 72 | ContextResolver.SetContext(guid); 73 | 74 | var got = ContextResolver.GetContext(); 75 | Assert.NotNull(got); 76 | Assert.Equal(guid, got.ToString()); 77 | } 78 | } 79 | 80 | public class TestContext 81 | { 82 | public string CorrelationId; 83 | public string OtherId; 84 | } 85 | 86 | public static class TestContextHelper 87 | { 88 | public static void AssertAreEqual(TestContext expected, TestContext actual) 89 | { 90 | if (expected == null && actual == null) return; 91 | 92 | Assert.NotNull(expected); 93 | Assert.NotNull(actual); 94 | Assert.Equal(expected.CorrelationId, actual.CorrelationId); 95 | Assert.Equal(expected.OtherId, actual.OtherId); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Common.Test/CorrelationContextTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net.Http; 4 | using Microsoft.Diagnostics.Context; 5 | using Microsoft.Diagnostics.Correlation.Common; 6 | using Microsoft.Diagnostics.Correlation.Common.Http; 7 | using Xunit; 8 | 9 | namespace Microsoft.Diagnostics.Correlation.Test 10 | { 11 | public class CorrelationContextTests 12 | { 13 | [Fact] 14 | public void CorrelationIdNull() 15 | { 16 | Assert.Throws(() => new CorrelationContext(null)); 17 | } 18 | 19 | [Fact] 20 | public void CorrelationIdValid() 21 | { 22 | var tId = Guid.NewGuid().ToString(); 23 | var ctx = new CorrelationContext(tId); 24 | Assert.Equal(tId, ctx.CorrelationId); 25 | Assert.Null(ctx.RequestId); 26 | Assert.Equal(2, ctx.Count); 27 | } 28 | 29 | [Fact] 30 | public void RequestIdValid() 31 | { 32 | var tId = Guid.NewGuid().ToString(); 33 | var rId = Guid.NewGuid().ToString(); 34 | var ctx = new CorrelationContext(tId, rId); 35 | Assert.Equal(rId, ctx.RequestId); 36 | } 37 | 38 | [Fact] 39 | public void AddCustomField() 40 | { 41 | var tId = Guid.NewGuid().ToString(); 42 | var ctx = new CorrelationContext(tId); 43 | Assert.Throws(() => ctx.Add("correlationId", "id")); 44 | Assert.Throws(() => ctx.Add("requestId", "id")); 45 | 46 | ctx.Add("custom", 123); 47 | Assert.Equal(123, ctx["custom"]); 48 | Assert.Equal(3, ctx.Count); 49 | } 50 | 51 | [Fact] 52 | public void KeysAndValues() 53 | { 54 | var tId = Guid.NewGuid().ToString(); 55 | var ctx = new CorrelationContext(tId) 56 | { 57 | { "custom1", 1}, 58 | { "custom2", 2} 59 | }; 60 | 61 | Assert.Contains("custom1", ctx.Keys); 62 | Assert.Contains("custom2", ctx.Keys); 63 | Assert.Contains("correlationId", ctx.Keys); 64 | Assert.Contains("requestId", ctx.Keys); 65 | 66 | Assert.Contains(1, ctx.Values); 67 | Assert.Contains(2, ctx.Values); 68 | Assert.Contains(tId, ctx.Values); 69 | 70 | Assert.Contains(new KeyValuePair("custom1", 1), ctx); 71 | Assert.Contains(new KeyValuePair("custom2", 2), ctx); 72 | Assert.Contains(new KeyValuePair("correlationId", tId), ctx); 73 | } 74 | 75 | public void ChildContext() 76 | { 77 | var ctx = new CorrelationContext(Guid.NewGuid().ToString()); 78 | 79 | var request = new HttpRequestMessage(); 80 | var childId = Guid.NewGuid().ToString(); 81 | request.Headers.Add(CorrelationHeaderInfo.RequestIdHeaderName, childId); 82 | var childCtx = ctx.GetChildRequestContext(request.GetChildRequestId()); 83 | Assert.NotEqual(childCtx, ctx); 84 | 85 | Assert.Null(ctx.ChildRequestId); 86 | Assert.Equal(childId, childCtx.ChildRequestId); 87 | Assert.Equal(3, childCtx.Count); 88 | 89 | ctx["some-id"] = "some-value"; 90 | Assert.Equal(3, childCtx.Count); 91 | } 92 | 93 | public void ChildContextNull() 94 | { 95 | var ctx = new CorrelationContext(Guid.NewGuid().ToString()); 96 | 97 | var request = new HttpRequestMessage(); 98 | var childCtx = ctx.GetChildRequestContext(request.GetChildRequestId()); 99 | Assert.Equal(2, childCtx.Count); 100 | } 101 | 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Common.Test/Http/ContextRequestHandlerTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using Microsoft.Diagnostics.Context; 9 | using Microsoft.Diagnostics.Correlation.Common; 10 | using Microsoft.Diagnostics.Correlation.Common.Http; 11 | using Moq; 12 | using Moq.Protected; 13 | using Xunit; 14 | 15 | namespace Microsoft.Diagnostics.Correlation.Test.Http 16 | { 17 | public class ContextRequestHandlerTests 18 | { 19 | [Fact] 20 | public void CtorInjectorNull() 21 | { 22 | Assert.Throws(() => new ContextRequestHandler(null)); 23 | } 24 | 25 | [Fact] 26 | public async Task SuccessFlow() 27 | { 28 | var correlationId = Guid.NewGuid().ToString(); 29 | ContextResolver.SetContext(new CorrelationContext(correlationId)); 30 | 31 | var innerHandler = setupMockHandler(createSuccessResponse); 32 | var corrHandler = new ContextRequestHandler(new [] {new CorrelationContextInjector()}, innerHandler.Object); 33 | var client = new HttpClient(corrHandler); 34 | 35 | await client.GetAsync("http://bing.com"); 36 | } 37 | 38 | private Task createSuccessResponse() 39 | { 40 | return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)); 41 | } 42 | 43 | private static void validateRequest(HttpRequestMessage request) 44 | { 45 | var ctx = ContextResolver.GetContext(); 46 | IEnumerable correlationIdHeader; 47 | Assert.True(request.Headers.TryGetValues(CorrelationHeaderInfo.CorrelationIdHeaderName, out correlationIdHeader)); 48 | Assert.Equal(1, correlationIdHeader.Count()); 49 | Assert.Equal(ctx.CorrelationId, correlationIdHeader.First()); 50 | 51 | IEnumerable requestIdHeader; 52 | Assert.True(request.Headers.TryGetValues(CorrelationHeaderInfo.RequestIdHeaderName, out requestIdHeader)); 53 | Assert.Equal(1, requestIdHeader.Count()); 54 | Assert.Equal(request.GetChildRequestId(), requestIdHeader.First()); 55 | 56 | } 57 | 58 | private static Mock setupMockHandler(Func> response) 59 | { 60 | var innerHandler = new Mock(); 61 | innerHandler.Protected() 62 | .Setup>("SendAsync", ItExpr.IsAny(), 63 | ItExpr.IsAny()) 64 | .Returns(response) 65 | .Callback((r, c) => { validateRequest(r); }); 66 | return innerHandler; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Common.Test/Http/CorrelationContextInjectorTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.Http; 5 | using Microsoft.Diagnostics.Context; 6 | using Microsoft.Diagnostics.Correlation.Common; 7 | using Microsoft.Diagnostics.Correlation.Common.Http; 8 | using Xunit; 9 | 10 | namespace Microsoft.Diagnostics.Correlation.Test.Http 11 | { 12 | public class CorrelationContextInjectorTests 13 | { 14 | private readonly CorrelationContextInjector injector; 15 | 16 | public CorrelationContextInjectorTests() 17 | { 18 | injector = new CorrelationContextInjector(); 19 | } 20 | 21 | [Fact] 22 | public void RequestNull() 23 | { 24 | Assert.Throws(() => injector.UpdateRequest(new CorrelationContext(""), null)); 25 | } 26 | 27 | [Fact] 28 | public void CorrelationIdNull() 29 | { 30 | Assert.Throws(() => injector.UpdateRequest(null, new HttpRequestMessage())); 31 | } 32 | 33 | [Fact] 34 | public void ValidUpdateRequest() 35 | { 36 | var request = new HttpRequestMessage(); 37 | var correlationId = Guid.NewGuid().ToString(); 38 | injector.UpdateRequest(new CorrelationContext(correlationId), request); 39 | 40 | IEnumerable correlationIdHeader; 41 | Assert.True(request.Headers.TryGetValues(CorrelationHeaderInfo.CorrelationIdHeaderName, out correlationIdHeader)); 42 | Assert.Equal(1, correlationIdHeader.Count()); 43 | Assert.Equal(correlationId, correlationIdHeader.First()); 44 | 45 | IEnumerable requestIdHeader; 46 | Assert.True(request.Headers.TryGetValues(CorrelationHeaderInfo.RequestIdHeaderName, out requestIdHeader)); 47 | Assert.Equal(1, requestIdHeader.Count()); 48 | Assert.Equal(request.GetChildRequestId(), requestIdHeader.First()); 49 | 50 | } 51 | 52 | [Fact] 53 | public void HeaderAlreadyExists() 54 | { 55 | var correlationId = Guid.NewGuid().ToString(); 56 | var request = new HttpRequestMessage(); 57 | request.Headers.Add(CorrelationHeaderInfo.CorrelationIdHeaderName, correlationId); 58 | 59 | Assert.Throws(() => injector.UpdateRequest(new CorrelationContext(correlationId), request)); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Common.Test/Http/EndpointValidatorTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Diagnostics.Correlation.Common.Http; 3 | using Xunit; 4 | 5 | namespace Microsoft.Diagnostics.Correlation.Test.Http 6 | { 7 | public class EndpointValidatorTest 8 | { 9 | [Fact] 10 | public void EndpointValidatorEmpty() 11 | { 12 | var validator = new EndpointFilter(new string[0]); 13 | Assert.True(validator.Validate(new Uri("http://google.com"))); 14 | } 15 | 16 | [Fact] 17 | public void EndpointValidatorDefault() 18 | { 19 | var validator = new EndpointFilter(); 20 | Assert.True(validator.Validate(new Uri("http://google.com"))); 21 | Assert.False(validator.Validate(new Uri("https://storagesample.blob.core.windows.net"))); 22 | } 23 | 24 | [Fact] 25 | public void EndpointValidatorWhitelist() 26 | { 27 | var validator = new EndpointFilter(new [] {"bing", "microsoft", "visualstudio"} ); 28 | Assert.False(validator.Validate(new Uri("http://google.com"))); 29 | Assert.True(validator.Validate(new Uri("http://bing.com"))); 30 | Assert.True(validator.Validate(new Uri("http://microsoft.com"))); 31 | Assert.True(validator.Validate(new Uri("http://visualstudio.com"))); 32 | } 33 | 34 | [Fact] 35 | public void EndpointValidatorBlacklist() 36 | { 37 | var validator = new EndpointFilter(new[] {"google"}, false); 38 | Assert.False(validator.Validate(new Uri("http://google.com"))); 39 | Assert.True(validator.Validate(new Uri("http://bing.com"))); 40 | Assert.True(validator.Validate(new Uri("http://microsoft.com"))); 41 | Assert.True(validator.Validate(new Uri("http://visualstudio.com"))); 42 | } 43 | 44 | 45 | [Fact] 46 | public void EndpointValidatorRegexp() 47 | { 48 | var validator = new EndpointFilter(new[] { "[a-z]+.com" }); 49 | Assert.True(validator.Validate(new Uri("http://bing.com"))); 50 | Assert.False(validator.Validate(new Uri("http://bing123.com"))); 51 | } 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Common.Test/Http/HttpClientBuilderTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using Microsoft.Diagnostics.Context; 9 | using Microsoft.Diagnostics.Correlation.Common; 10 | using Microsoft.Diagnostics.Correlation.Common.Http; 11 | using Moq; 12 | using Moq.Protected; 13 | using Xunit; 14 | 15 | namespace Microsoft.Diagnostics.Correlation.Test.Http 16 | { 17 | public class HttpClientBuilderTests 18 | { 19 | [Fact] 20 | public async Task SuccessFlow() 21 | { 22 | var correlationId = Guid.NewGuid().ToString(); 23 | ContextResolver.SetContext(new CorrelationContext(correlationId)); 24 | 25 | var innerHandler = setupMockHandler(validateHeader); 26 | var client = HttpClientBuilder.CreateClient(innerHandler.Object, new[] {new CorrelationContextInjector()}); 27 | await client.GetAsync("http://bing.com"); 28 | } 29 | 30 | [Fact] 31 | public async Task SuccessFlowCustomHandlers() 32 | { 33 | var correlationId = Guid.NewGuid().ToString(); 34 | ContextResolver.SetContext(new CorrelationContext(correlationId)); 35 | 36 | var innerHandler = setupMockHandler(validateHeader); 37 | var client = HttpClientBuilder.CreateClient(innerHandler.Object, new[] {new CorrelationContextInjector()}, 38 | new TestHandler()); 39 | await client.GetAsync("http://bing.com"); 40 | } 41 | 42 | [Fact] 43 | public async Task NoInjectors() 44 | { 45 | var correlationId = Guid.NewGuid().ToString(); 46 | ContextResolver.SetContext(correlationId); 47 | 48 | var innerHandler = setupMockHandler(validateNoHeader); 49 | var client = HttpClientBuilder.CreateClient(innerHandler.Object, new List>()); 50 | 51 | await client.GetAsync("http://bing.com"); 52 | } 53 | 54 | [Fact] 55 | public async Task ValidateMultipleInjectors() 56 | { 57 | var correlationId = Guid.NewGuid().ToString(); 58 | ContextResolver.SetContext(new CorrelationContext(correlationId)); 59 | 60 | var testInjector = new TestInjector(); 61 | var innerHandler = setupMockHandler(r => 62 | { 63 | validateHeader(r); 64 | testInjector.ValidateHeader(r); 65 | }); 66 | 67 | var client = HttpClientBuilder.CreateClient(innerHandler.Object, new List> {new CorrelationContextInjector(), testInjector}); 68 | 69 | await client.GetAsync("http://bing.com"); 70 | } 71 | 72 | private static void validateHeader(HttpRequestMessage request) 73 | { 74 | IEnumerable actualHeader; 75 | Assert.True(request.Headers.TryGetValues(CorrelationHeaderInfo.CorrelationIdHeaderName, out actualHeader)); 76 | Assert.Equal(1, actualHeader.Count()); 77 | Assert.Equal(ContextResolver.GetContext().CorrelationId, actualHeader.First()); 78 | } 79 | private static void validateNoHeader(HttpRequestMessage request) 80 | { 81 | IEnumerable actualHeader; 82 | Assert.False(request.Headers.TryGetValues(CorrelationHeaderInfo.CorrelationIdHeaderName, out actualHeader)); 83 | } 84 | 85 | private static Mock setupMockHandler(Action callback) 86 | { 87 | var innerHandler = new Mock(); 88 | innerHandler.Protected() 89 | .Setup>("SendAsync", ItExpr.IsAny(), 90 | ItExpr.IsAny()) 91 | .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)) 92 | .Callback((r, c) => { callback(r); }); 93 | return innerHandler; 94 | } 95 | 96 | private class TestInjector : IContextInjector 97 | { 98 | private readonly string id; 99 | 100 | public TestInjector() 101 | { 102 | id = Guid.NewGuid().ToString(); 103 | } 104 | 105 | public void UpdateRequest(CorrelationContext ctx, HttpRequestMessage request) 106 | { 107 | request.Headers.Add(id, id); 108 | } 109 | 110 | public void ValidateHeader(HttpRequestMessage request) 111 | { 112 | IEnumerable actualHeader; 113 | Assert.True(request.Headers.TryGetValues(id, out actualHeader)); 114 | Assert.Equal(1, actualHeader.Count()); 115 | Assert.Equal(id, actualHeader.First()); 116 | } 117 | } 118 | 119 | private class TestHandler : DelegatingHandler 120 | { 121 | protected override Task SendAsync(HttpRequestMessage request, 122 | CancellationToken cancellationToken) 123 | { 124 | validateHeader(request); 125 | return base.SendAsync(request, cancellationToken); 126 | } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Common.Test/Http/HttpRequestExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using Microsoft.Diagnostics.Correlation.Common; 4 | using Microsoft.Diagnostics.Correlation.Common.Http; 5 | using Xunit; 6 | 7 | namespace Microsoft.Diagnostics.Correlation.Test.Http 8 | { 9 | public class HttpRequestExtensionsTest 10 | { 11 | [Fact] 12 | public void HeaderExists() 13 | { 14 | var request = new HttpRequestMessage(); 15 | 16 | var requestId = Guid.NewGuid().ToString(); 17 | request.Headers.Add(CorrelationHeaderInfo.RequestIdHeaderName, requestId); 18 | Assert.Equal(requestId, request.GetChildRequestId()); 19 | } 20 | 21 | [Fact] 22 | public void HeaderDoesNotExists() 23 | { 24 | var request = new HttpRequestMessage(); 25 | Assert.Null(request.GetChildRequestId()); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Common.Test/Microsoft.Diagnostics.Correlation.Common.Test.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0.25420 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 5eda8fea-72c3-46db-8d01-632943d77cb1 10 | Microsoft.Diagnostics.Correlation.Test 11 | .\obj 12 | .\bin\ 13 | 14 | 15 | 2.0 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Common.Test/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "dependencies": { 4 | "dotnet-test-xunit": "2.2.0-preview2-build1029", 5 | "Microsoft.Diagnostics.Correlation.Common": { "target": "project" }, 6 | "Moq": "4.6.38-alpha", 7 | "xunit": "2.2.0-beta2-build3300", 8 | "xunit.runner.console": "2.2.0-beta2-build3300", 9 | "xunit.runner.visualstudio": "2.2.0-beta2-build1149" 10 | }, 11 | "testRunner": "xunit", 12 | "frameworks": { 13 | "netcoreapp1.0": { 14 | "dependencies": { 15 | "Microsoft.NETCore.App": { 16 | "type": "platform", 17 | "version": "1.0.0" 18 | } 19 | }, 20 | "imports": [ 21 | "dotnet5.4", 22 | "portable-net451+win8" 23 | ] 24 | }, 25 | "net46": {}, 26 | "net451": {} 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Instrumentation.Test/ContextTracingInsrumentationProfilerTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Http; 4 | using System.Threading.Tasks; 5 | using Microsoft.Diagnostics.Context; 6 | using Microsoft.Diagnostics.Correlation.Common; 7 | using Microsoft.Diagnostics.Correlation.Common.Instrumentation; 8 | using Microsoft.Diagnostics.Correlation.Http; 9 | using Xunit; 10 | 11 | namespace Microsoft.Diagnostics.Correlation.Instrumentation.Tests 12 | { 13 | public class ProfilerFixture : IDisposable 14 | { 15 | public readonly InjectorMock Injector; 16 | public readonly RequestNotifier Notifier; 17 | public ProfilerFixture() 18 | { 19 | Injector = new InjectorMock(); 20 | Notifier = new RequestNotifier(); 21 | 22 | var profilerConfig = new ProfilerCorrelationConfiguration() 23 | .WithContextInjectors(new[] {Injector}) 24 | .WithOutgoingRequestNotifier(Notifier); 25 | 26 | ContextTracingInstrumentation.Enable(profilerConfig); 27 | } 28 | 29 | public void Dispose() 30 | { 31 | } 32 | } 33 | 34 | public class ContextTracingInsrumentationProfilerTests : IClassFixture, IDisposable 35 | { 36 | private readonly ProfilerFixture fixture; 37 | 38 | public ContextTracingInsrumentationProfilerTests(ProfilerFixture fixture) 39 | { 40 | this.fixture = fixture; 41 | } 42 | 43 | [Fact(Skip = "profiler is not configured in VSO Build")] 44 | public void ContextInjectorNull() 45 | { 46 | var profilerConfig = new Configuration(); 47 | 48 | Assert.Throws(() => ContextTracingInstrumentation.Enable(profilerConfig)); 49 | } 50 | 51 | [Fact(Skip = "profiler is not configured in VSO Build")] 52 | public async Task SuccessFlowHttpClient() 53 | { 54 | fixture.Notifier.BeforeWasCalled = false; 55 | fixture.Notifier.AfterWasCalled = false; 56 | fixture.Injector.WasCalled = false; 57 | 58 | var correlationId = Guid.NewGuid().ToString(); 59 | ContextResolver.SetContext(new CorrelationContext(correlationId)); 60 | 61 | var client = new HttpClient(); 62 | await client.GetAsync("http://bing.com"); 63 | Assert.True(fixture.Injector.WasCalled); 64 | Assert.True(fixture.Notifier.BeforeWasCalled); 65 | Assert.True(fixture.Notifier.AfterWasCalled); 66 | } 67 | 68 | [Fact(Skip = "profiler is not configured in VSO Build")] 69 | public async Task SuccessFlowWebRequest() 70 | { 71 | fixture.Notifier.BeforeWasCalled = false; 72 | fixture.Notifier.AfterWasCalled = false; 73 | fixture.Injector.WasCalled = false; 74 | 75 | var correlationId = Guid.NewGuid().ToString(); 76 | ContextResolver.SetContext(new CorrelationContext(correlationId)); 77 | 78 | var request = WebRequest.CreateHttp("http://bing.com"); 79 | try 80 | { 81 | await request.GetResponseAsync(); 82 | } 83 | catch 84 | { 85 | // ignored 86 | } 87 | 88 | Assert.True(fixture.Injector.WasCalled); 89 | Assert.True(fixture.Notifier.BeforeWasCalled); 90 | Assert.True(fixture.Notifier.AfterWasCalled); 91 | } 92 | 93 | public void Dispose() 94 | { 95 | } 96 | } 97 | 98 | public class RequestNotifier : IOutgoingRequestNotifier 99 | { 100 | public bool BeforeWasCalled { get; set; } 101 | public bool AfterWasCalled { get; set; } 102 | 103 | public void OnBeforeRequest(CorrelationContext context, WebRequest request) 104 | { 105 | BeforeWasCalled = true; 106 | Assert.NotNull(context.ChildRequestId); 107 | Assert.NotNull(request); 108 | } 109 | 110 | public void OnAfterResponse(CorrelationContext context, WebResponse response) 111 | { 112 | AfterWasCalled = true; 113 | Assert.NotNull(context.ChildRequestId); 114 | Assert.NotNull(response); 115 | } 116 | } 117 | 118 | public class InjectorMock : IContextInjector 119 | { 120 | private readonly WebRequestCorrelationContextInjector injector = new WebRequestCorrelationContextInjector(); 121 | public bool WasCalled { get; set; } 122 | 123 | public void UpdateRequest(CorrelationContext ctx, WebRequest request) 124 | { 125 | WasCalled = true; 126 | injector.UpdateRequest(ctx, request); 127 | } 128 | } 129 | 130 | } -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Instrumentation.Test/Microsoft.Diagnostics.Correlation.Instrumentation.Test.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 461d69d9-258c-4935-8ac9-88bb666775bd 10 | Microsoft.Diagnostics.Correlation.Instrumentation.Tests 11 | .\obj 12 | .\bin\ 13 | v4.6.1 14 | 15 | 16 | 2.0 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Instrumentation.Test/ProfilerConfigurationTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Microsoft.Diagnostics.Correlation.Http; 3 | using Xunit; 4 | 5 | namespace Microsoft.Diagnostics.Correlation.Instrumentation.Tests 6 | { 7 | public class ProfilerConfigurationTests 8 | { 9 | [Fact] 10 | public void DefaultConfiguration() 11 | { 12 | var config = new ProfilerCorrelationConfiguration(); 13 | Assert.NotNull(config.ContextInjectors); 14 | Assert.True(config.ContextInjectors.First() is WebRequestCorrelationContextInjector); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Instrumentation.Test/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | 4 | "dependencies": { 5 | "dotnet-test-xunit": "2.2.0-preview2-build1029", 6 | "xunit": "2.2.0-beta2-build3300", 7 | "xunit.runner.visualstudio": "2.2.0-beta2-build1149", 8 | "Microsoft.Diagnostics.Correlation.Instrumentation": { "target": "project" }, 9 | "xunit.runner.console": "2.2.0-beta2-build3300", 10 | "Moq": "4.6.38-alpha" 11 | }, 12 | "testRunner": "xunit", 13 | 14 | "frameworks": { 15 | "net46": {}, 16 | "net451": {} 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Middleware.Test/ContextTracingMiddlewareTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using Microsoft.Diagnostics.Context; 5 | using Microsoft.Diagnostics.Correlation.Common; 6 | using Microsoft.Diagnostics.Correlation.Owin; 7 | using Xunit; 8 | 9 | namespace Microsoft.Diagnostics.Correlation.Middleware.Test 10 | { 11 | public class ContextTracingMiddlewareTests 12 | { 13 | private readonly string correlationId = Guid.NewGuid().ToString(); 14 | 15 | [Fact] 16 | public void NullFactory() 17 | { 18 | Assert.Throws(() => new ContextTracingMiddleware(assertEmptyContext, null)); 19 | } 20 | 21 | [Fact] 22 | public async Task NoHeader() 23 | { 24 | var middleware = new ContextTracingMiddleware(assertEmptyContext, new OwinCorrelationContextFactory()); 25 | await middleware.Invoke(createEmptyRequest()); 26 | } 27 | 28 | [Fact] 29 | public async Task FromHeader() 30 | { 31 | var middleware = new ContextTracingMiddleware(AssertContext, new OwinCorrelationContextFactory()); 32 | await middleware.Invoke(createRequest(correlationId)); 33 | } 34 | 35 | private Task assertEmptyContext(IDictionary environment) 36 | { 37 | var ctx = ContextResolver.GetContext(); 38 | Assert.NotNull(ctx); 39 | return Task.FromResult(1); 40 | } 41 | 42 | private Task AssertContext(IDictionary environment) 43 | { 44 | var ctx = ContextResolver.GetContext(); 45 | Assert.NotNull(ctx); 46 | Assert.Equal(correlationId, ctx.CorrelationId); 47 | return Task.FromResult(1); 48 | } 49 | 50 | private IDictionary createEmptyRequest() 51 | { 52 | return new Dictionary 53 | { 54 | {"owin.RequestHeaders", new Dictionary()} 55 | }; 56 | } 57 | 58 | private IDictionary createRequest(string header) 59 | { 60 | var headerDict = new Dictionary 61 | { 62 | {CorrelationHeaderInfo.CorrelationIdHeaderName, new[] {header}} 63 | }; 64 | 65 | return new Dictionary 66 | { 67 | {"owin.RequestHeaders", headerDict } 68 | }; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Middleware.Test/Microsoft.Diagnostics.Correlation.Owin.Test.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0.25420 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 9080c505-f4b7-4afc-8f4f-97a8be1015e3 10 | Microsoft.Diagnostics.Correlation.Middleware.Test 11 | .\obj 12 | .\bin\ 13 | 14 | 15 | 2.0 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Middleware.Test/OwinCorrelationContextFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.Diagnostics.Correlation.Common; 4 | using Microsoft.Diagnostics.Correlation.Owin; 5 | using Xunit; 6 | 7 | namespace Microsoft.Diagnostics.Correlation.Middleware.Test 8 | { 9 | public class OwinCorrelationContextFactoryTests 10 | { 11 | private readonly OwinCorrelationContextFactory factory; 12 | 13 | public OwinCorrelationContextFactoryTests() 14 | { 15 | factory = new OwinCorrelationContextFactory(); 16 | } 17 | 18 | [Fact] 19 | public void CreateContextNull() 20 | { 21 | Assert.Throws(() => factory.CreateContext(null)); 22 | } 23 | 24 | [Fact] 25 | public void CreateContextNoHeader() 26 | { 27 | var ctx = factory.CreateContext(createEmptyRequest()); 28 | Assert.NotNull(ctx); 29 | 30 | Guid guid; 31 | Assert.True(Guid.TryParse(ctx.CorrelationId, out guid)); 32 | Assert.True(Guid.TryParse(ctx.RequestId, out guid)); 33 | } 34 | 35 | [Theory] 36 | [InlineData(null, null)] 37 | [InlineData("11111111-1111-1111-1111-111111111111", "22222222-2222-2222-2222-222222222222")] 38 | [InlineData(null, "22222222-2222-2222-2222-222222222222")] 39 | public void CreateContextFromHeader(string requestIdHeader, string requestIdWorker) 40 | { 41 | var correlationId = Guid.NewGuid().ToString(); 42 | var ctx = factory.CreateContext(createRequest(correlationId, requestIdHeader, requestIdWorker)); 43 | Assert.Equal(correlationId, ctx.CorrelationId); 44 | Assert.NotNull(ctx.RequestId); 45 | if (requestIdHeader != null) 46 | Assert.Equal(requestIdHeader, ctx.RequestId); 47 | else if (requestIdWorker != null) 48 | Assert.Equal(requestIdWorker, ctx.RequestId); 49 | } 50 | 51 | private IDictionary createEmptyRequest() 52 | { 53 | return new Dictionary(); 54 | } 55 | 56 | private IDictionary createRequest(string correlationId, string requestIdHeader, string requestIdWorker) 57 | { 58 | var headers = new Dictionary 59 | { 60 | {CorrelationHeaderInfo.CorrelationIdHeaderName, new[] {correlationId}} 61 | }; 62 | if (requestIdHeader != null) 63 | headers.Add(CorrelationHeaderInfo.RequestIdHeaderName, new [] {requestIdHeader}); 64 | 65 | var environment = new Dictionary 66 | { 67 | {"owin.RequestHeaders", headers} 68 | }; 69 | 70 | if (requestIdWorker != null) 71 | environment.Add("owin.RequestId", requestIdWorker); 72 | 73 | return environment; 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Middleware.Test/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "testRunner": "xunit", 4 | "dependencies": { 5 | "dotnet-test-xunit": "2.2.0-preview2-build1029", 6 | "xunit": "2.2.0-beta2-build3300", 7 | "xunit.runner.visualstudio": "2.2.0-beta2-build1149", 8 | "xunit.runner.console": "2.2.0-beta2-build3300", 9 | "Moq": "4.6.38-alpha", 10 | "Microsoft.Diagnostics.Correlation": { "target": "project" } 11 | }, 12 | "frameworks": { 13 | "net46": {}, 14 | "net451": {} 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Test/CorrelationContextFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Web; 4 | using System.Web.Routing; 5 | using Microsoft.Diagnostics.Correlation.Common; 6 | using Microsoft.Diagnostics.Correlation.Http; 7 | using Moq; 8 | using Xunit; 9 | 10 | namespace Microsoft.Diagnostics.Correlation.Test 11 | { 12 | public class CorrelationContextFactoryTests 13 | { 14 | private readonly CorrelationContextFactory factory; 15 | 16 | public CorrelationContextFactoryTests() 17 | { 18 | factory = new CorrelationContextFactory(); 19 | } 20 | 21 | [Fact] 22 | public void CreateContextNull() 23 | { 24 | Assert.Throws(() => factory.CreateContext(null)); 25 | } 26 | 27 | [Fact] 28 | public void CreateContextNoHeader() 29 | { 30 | var ctx = factory.CreateContext(createEmptyRequest()); 31 | Assert.NotNull(ctx); 32 | 33 | Guid guid; 34 | Assert.True(Guid.TryParse(ctx.CorrelationId, out guid)); 35 | Assert.True(Guid.TryParse(ctx.RequestId, out guid)); 36 | } 37 | 38 | [Theory] 39 | [InlineData(null, null)] 40 | [InlineData("11111111-1111-1111-1111-111111111111", "22222222-2222-2222-2222-222222222222")] 41 | [InlineData(null, "22222222-2222-2222-2222-222222222222")] 42 | public void CreateContextFromHeader(string requestIdHeader, string requestIdWorker) 43 | { 44 | var correlationId = Guid.NewGuid().ToString(); 45 | var ctx = factory.CreateContext(createRequest(correlationId, requestIdHeader, requestIdWorker)); 46 | Assert.Equal(correlationId, ctx.CorrelationId); 47 | Assert.NotNull(ctx.RequestId); 48 | if (requestIdHeader != null) 49 | Assert.Equal(requestIdHeader, ctx.RequestId); 50 | else if (requestIdWorker != null) 51 | Assert.Equal(requestIdWorker, ctx.RequestId); 52 | } 53 | 54 | private HttpRequest createEmptyRequest() 55 | { 56 | var mock = new Mock(); 57 | Mock requestContext = new Mock(); 58 | Mock httpContextBase = new Mock(); 59 | httpContextBase.Setup(c => c.GetService(It.Is(v => v == typeof(HttpWorkerRequest)))).Returns(mock.Object); 60 | requestContext.SetupGet(rc => rc.HttpContext).Returns(httpContextBase.Object); 61 | var request = new HttpRequest("", "http://bing.com", "") {RequestContext = requestContext.Object}; 62 | 63 | return request; 64 | } 65 | 66 | private HttpRequest createRequest(string correlationId, string requestIdHeader, string requestIdWorker) 67 | { 68 | var mock = new Mock(); 69 | 70 | bool setupRequestIdHeader = requestIdHeader != null; 71 | var unknownHeaders = new string[setupRequestIdHeader ? 2 : 1][]; 72 | unknownHeaders[0] = new string[2]; 73 | unknownHeaders[0][0] = CorrelationHeaderInfo.CorrelationIdHeaderName; 74 | unknownHeaders[0][1] = correlationId; 75 | if (setupRequestIdHeader) 76 | { 77 | unknownHeaders[1] = new string[2]; 78 | unknownHeaders[1][0] = CorrelationHeaderInfo.RequestIdHeaderName; 79 | unknownHeaders[1][1] = requestIdHeader; 80 | } 81 | 82 | mock.Setup(r => r.GetUnknownRequestHeaders()).Returns(unknownHeaders); 83 | if (requestIdWorker != null) 84 | mock.SetupGet(r => r.RequestTraceIdentifier).Returns(Guid.Parse(requestIdWorker)); 85 | 86 | Mock requestContext = new Mock(); 87 | Mock httpContextBase = new Mock(); 88 | httpContextBase.Setup(c => c.GetService(It.Is(v => v == typeof(HttpWorkerRequest)))).Returns(mock.Object); 89 | requestContext.SetupGet(rc => rc.HttpContext).Returns(httpContextBase.Object); 90 | 91 | var paramTypes = new Type[] { typeof(HttpWorkerRequest), typeof(HttpContext) }; 92 | var constructor = typeof(HttpRequest).GetConstructor(BindingFlags.NonPublic|BindingFlags.Instance, null, paramTypes, null); 93 | var paramValues = new object[] { mock.Object, null }; 94 | var request = (HttpRequest)constructor.Invoke(paramValues); 95 | request.RequestContext = requestContext.Object; 96 | 97 | return request; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Test/Microsoft.Diagnostics.Correlation.Test.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | d5879cd6-7578-4fe3-94de-9a04bf849543 10 | Microsoft.Diagnostics.Correlation.Test 11 | .\obj 12 | .\bin\ 13 | v4.6.1 14 | 15 | 16 | 2.0 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Test/WebRequestCorrelationContextInjectorTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using Microsoft.Diagnostics.Context; 6 | using Microsoft.Diagnostics.Correlation.Common; 7 | using Microsoft.Diagnostics.Correlation.Http; 8 | using Xunit; 9 | 10 | namespace Microsoft.Diagnostics.Correlation.Test 11 | { 12 | public class WebRequestCorrelationContextInjectorTests 13 | { 14 | private readonly WebRequestCorrelationContextInjector injector; 15 | 16 | public WebRequestCorrelationContextInjectorTests() 17 | { 18 | injector = new WebRequestCorrelationContextInjector(); 19 | } 20 | 21 | [Fact] 22 | public void RequestNull() 23 | { 24 | Assert.Throws(() => injector.UpdateRequest(new CorrelationContext(""), null)); 25 | } 26 | 27 | [Fact] 28 | public void CorrelationIdNull() 29 | { 30 | Assert.Throws(() => injector.UpdateRequest(null, WebRequest.Create("http://bing.com"))); 31 | } 32 | 33 | [Fact] 34 | public void ValidUpdateRequest() 35 | { 36 | var request = WebRequest.Create("http://bing.com"); 37 | var correlationId = Guid.NewGuid().ToString(); 38 | injector.UpdateRequest(new CorrelationContext(correlationId), request); 39 | 40 | IEnumerable actualHeader = request.Headers.GetValues(CorrelationHeaderInfo.CorrelationIdHeaderName); 41 | Assert.NotNull(actualHeader); 42 | Assert.Equal(1, actualHeader.Count()); 43 | Assert.Equal(correlationId, actualHeader.First()); 44 | } 45 | 46 | [Fact] 47 | public void HeaderAlreadyExists() 48 | { 49 | var correlationId = Guid.NewGuid().ToString(); 50 | var request = WebRequest.Create("http://bing.com"); 51 | request.Headers.Add(CorrelationHeaderInfo.CorrelationIdHeaderName, correlationId); 52 | 53 | Assert.Throws(() => injector.UpdateRequest(new CorrelationContext(correlationId), request)); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /test/Microsoft.Diagnostics.Correlation.Test/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "dependencies": { 4 | "dotnet-test-xunit": "2.2.0-preview2-build1029", 5 | "Microsoft.Diagnostics.Correlation": { "target": "project" }, 6 | "Moq": "4.6.38-alpha", 7 | "xunit": "2.2.0-beta2-build3300", 8 | "xunit.runner.console": "2.2.0-beta2-build3300", 9 | "xunit.runner.visualstudio": "2.2.0-beta2-build1149" 10 | }, 11 | "testRunner": "xunit", 12 | "frameworks": { 13 | "net46": {}, 14 | "net451": {} 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tools/InstallCoreSDK.ps1: -------------------------------------------------------------------------------- 1 | $ErrorActionPreference = "Stop" 2 | $installerName = "installer.exe" 3 | 4 | Write-Host "Downloading .Net Core SDK" 5 | Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/?LinkID=809122" -OutFile $installerName 6 | 7 | Write-Host "Installing .Net Core SDK" 8 | Start-Process $installerName -ArgumentList "/quiet" -Wait 9 | 10 | Write-Host ".Net Core installation finished" 11 | Remove-Item $installerName -------------------------------------------------------------------------------- /tools/createNugetPackages.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | pushd "%~dp0.." 3 | SET parentDir=%cd% 4 | popd 5 | 6 | SET SUFFIX=%1 7 | IF '%SUFFIX%' == '' GOTO NOSUFFIX 8 | for /f %%a in ('findstr /sm packOptions %parentDir%\src\project.json') do dotnet pack %%a --no-build -c Release -o "%parentDir%\nugets" --version-suffix %SUFFIX% 9 | "%~dp0\nuget.exe" pack "%parentDir%\nuspecs\AspNetSuite\Microsoft.Diagnostics.Correlation.AspNet.nuspec" -OutputDirectory "%parentDir%\nugets" -Suffix %SUFFIX% 10 | GOTO END 11 | 12 | :NOSUFFIX 13 | for /f %%a in ('findstr /sm packOptions %parentDir%\src\project.json') do dotnet pack %%a --no-build -c Release -o "%parentDir%\nugets" 14 | "%~dp0\nuget.exe" pack "%parentDir%\nuspecs\AspNetSuite\Microsoft.Diagnostics.Correlation.AspNet.nuspec" -OutputDirectory "%parentDir%\nugets" 15 | GOTO END 16 | 17 | :END -------------------------------------------------------------------------------- /tools/nuget.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/diagnostics-correlation/91a6f7ae19d884f299e090844b9d1779f953ca59/tools/nuget.exe -------------------------------------------------------------------------------- /tools/restore.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | dotnet restore %~dp0..\ 3 | pushd %~dp0.. 4 | tools\nuget.exe restore "src\Microsoft.Diagnostics.Correlation.Signing\Microsoft.Diagnostics.Correlation.Signing.csproj" -PackagesDirectory packages 5 | popd -------------------------------------------------------------------------------- /tools/runtest.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | SET failed=0 3 | for /f %%a in ('dir %~dp0..\test\project.json /b /s ^| find /i "Test"') do dotnet test %%a || set failed=1 4 | EXIT /B %failed% -------------------------------------------------------------------------------- /tools/setEnv.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | pushd %~dp0 3 | 4 | where dotnet >NUL 2>NUL 5 | IF %ERRORLEVEL% NEQ 0 powershell.exe -File InstallCoreSDK.ps1 6 | 7 | ECHO %PATH% | findstr /I /C:"C:\Program Files\dotnet" >NUL 2>NUL 8 | IF %ERRORLEVEL% NEQ 0 SET PATH=%PATH%;C:\Program Files\dotnet\ 9 | 10 | popd --------------------------------------------------------------------------------