AspNet request collector (#543)

* Added a collector for incoming ASP.NET requests.

* Unit tests.

* Code review.

* Attempting to get windows build working.

* Attempting to fix build.

* Attempting to get the build working.

* Attempting to get the build working.

* Attempting to fix the build.

* Attempting to get Linux build working.

* Attempting to get linux build working.

* Attempting to get linux build working.

* Attempting to get build working.

* Attempting to get all tests running on windows.

* Attempting to get tests running on windows.

* Attempting to get the myget build working.

* Indention fix in myget yml.

* Code review.

* Code review.

* Code review.

* Code review.

* Code review.
This commit is contained in:
Mikel Blanchard 2020-03-20 19:59:45 -07:00 committed by GitHub
parent 3dbecfd167
commit f93df2bbea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 1442 additions and 66 deletions

View File

@ -1,7 +1,7 @@
# CI build. No publioshing of artifacts # CI build. No publishing of artifacts.
variables: variables:
DotNetVersion: "3.1.100" DotNetVersion: "3.1.101"
# A pipeline with no CI trigger # A pipeline with no CI trigger
trigger: none trigger: none
@ -11,34 +11,39 @@ pr: [ 'master' ]
jobs: jobs:
- job: Windows - job: Windows
pool: Hosted VS2017 pool:
vmImage: 'windows-latest'
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: force use of desired dotnet version displayName: force use of desired dotnet version
inputs: inputs:
version: $(DotNetVersion) version: $(DotNetVersion)
# "restore" is run automatically by "build" # "restore" is run automatically by "build"
- task: DotNetCoreCLI@2 - task: VSBuild@1
displayName: build solution (Release) displayName: build solution using VS (Release)
inputs: inputs:
command: "build" solution: OpenTelemetry.proj
projects: OpenTelemetry.proj vsVersion: "latest"
arguments: "--configuration Release" platform: "AnyCPU"
configuration: "Release"
msbuildArgs: "/p:OS=$(Agent.OS)"
# consider switch to https://docs.microsoft.com/vsts/pipelines/tasks/test/vstest?view=vsts # consider switch to https://docs.microsoft.com/vsts/pipelines/tasks/test/vstest?view=vsts
- task: DotNetCoreCLI@2 - task: DotNetCoreCLI@2
displayName: test displayName: test using CLI
inputs: inputs:
command: "test" command: "test"
projects: "test/**/*.Tests.csproj" projects: |
test/**/*.Tests.csproj
test/**/*.Tests.Win.csproj
arguments: "--configuration Release" arguments: "--configuration Release"
- task: PublishTestResults@2 - task: PublishTestResults@2
- job: Linux - job: Linux
pool: Hosted Ubuntu 1604 pool:
vmImage: 'ubuntu-latest'
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: force use of desired dotnet version displayName: force use of desired dotnet version
@ -47,14 +52,14 @@ jobs:
# "restore" is run automatically by "build" # "restore" is run automatically by "build"
- task: DotNetCoreCLI@2 - task: DotNetCoreCLI@2
displayName: build displayName: build solution using CLI (Release)
inputs: inputs:
command: "build" command: "build"
projects: OpenTelemetry.proj projects: OpenTelemetry.proj
arguments: "--configuration Release" arguments: "-p:OS=$(Agent.OS) --configuration Release"
- task: DotNetCoreCLI@2 - task: DotNetCoreCLI@2
displayName: test displayName: test using CLI
inputs: inputs:
command: "test" command: "test"
projects: "test/**/*.Tests.csproj" projects: "test/**/*.Tests.csproj"

View File

@ -1,7 +1,7 @@
# CI build with the upload to MyGet # CI build with the upload to MyGet
variables: variables:
DotNetVersion: "3.1.100" DotNetVersion: "3.1.101"
trigger: trigger:
branches: branches:
@ -11,7 +11,8 @@ trigger:
# no PR builds # no PR builds
pr: none pr: none
queue: Hosted VS2017 queue:
vmImage: 'windows-latest'
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
@ -19,24 +20,36 @@ steps:
inputs: inputs:
version: $(DotNetVersion) version: $(DotNetVersion)
# "build" and "restore" are run by "pack". # "restore" is run automatically by "build"
- task: VSBuild@1
displayName: build solution using VS (Release)
inputs:
solution: OpenTelemetry.proj
vsVersion: "latest"
platform: "AnyCPU"
configuration: "Release"
msbuildArgs: "/p:OS=$(Agent.OS)"
- task: DotNetCoreCLI@2
displayName: test using CLI
inputs:
command: "test"
projects: |
test/**/*.Tests.csproj
test/**/*.Tests.Win.csproj
arguments: "--configuration Release"
- task: PublishTestResults@2
- task: DotNetCoreCLI@2 - task: DotNetCoreCLI@2
displayName: pack solution with symbols (Release) displayName: pack solution with symbols (Release)
inputs: inputs:
command: "pack" command: "pack"
projects: OpenTelemetry.proj projects: OpenTelemetry.proj
configuration: 'Release' configurationToPack: 'Release'
packDirectory: '$(build.artifactStagingDirectory)' packDirectory: '$(build.artifactStagingDirectory)'
buildProperties: "SymbolPackageFormat=snupkg" buildProperties: "SymbolPackageFormat=snupkg"
arguments: "-p:OS=$(Agent.OS)"
- task: DotNetCoreCLI@2
displayName: test
inputs:
command: "test"
projects: "test/**/*.Tests.csproj"
arguments: "--configuration Release"
- task: PublishTestResults@2
- task: NuGetCommand@2 - task: NuGetCommand@2
displayName: 'Publish nugets to MyGet' displayName: 'Publish nugets to MyGet'

View File

@ -2,17 +2,18 @@
<Project ToolsVersion="16.4" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="16.4" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Solution Include="OpenTelemetry.sln" /> <SolutionProjects Include="**\*.csproj" />
<SolutionProjects Remove="**\*.Win.csproj" Condition="'$(OS)' != 'Windows_NT'" />
</ItemGroup> </ItemGroup>
<!-- The only need for this file is to synchronize the PreReleaseVersion --> <!-- The only need for this file is to synchronize the PreReleaseVersion -->
<Target Name="Build"> <Target Name="Build">
<MSBuild Projects="@(Solution)" Targets="Restore;Build" ContinueOnError="ErrorAndStop" Properties="PreReleaseVersion=$(PreReleaseVersion)"/> <MSBuild Projects="@(SolutionProjects)" Targets="Restore;Build" ContinueOnError="ErrorAndStop" Properties="PreReleaseVersion=$(PreReleaseVersion)"/>
</Target> </Target>
<Target Name="Pack"> <Target Name="Pack">
<MSBuild Projects="@(Solution)" Targets="Restore;Build;Pack" ContinueOnError="ErrorAndStop" Properties="PreReleaseVersion=$(PreReleaseVersion)"/> <MSBuild Projects="@(SolutionProjects)" Targets="Pack" ContinueOnError="ErrorAndStop" Properties="PreReleaseVersion=$(PreReleaseVersion)"/>
</Target> </Target>
</Project> </Project>

View File

@ -12,7 +12,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.editorconfig = .editorconfig .editorconfig = .editorconfig
CHANGELOG.md = CHANGELOG.md CHANGELOG.md = CHANGELOG.md
CONTRIBUTING.md = CONTRIBUTING.md CONTRIBUTING.md = CONTRIBUTING.md
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
NuGet.config = NuGet.config NuGet.config = NuGet.config
OpenTelemetry.proj = OpenTelemetry.proj
README.md = README.md README.md = README.md
EndProjectSection EndProjectSection
EndProject EndProject
@ -111,6 +114,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Web"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Zipkin.Tests", "test\OpenTelemetry.Exporter.Zipkin.Tests\OpenTelemetry.Exporter.Zipkin.Tests.csproj", "{1D778D2E-9523-450E-A6E0-A36897C7E78E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Zipkin.Tests", "test\OpenTelemetry.Exporter.Zipkin.Tests\OpenTelemetry.Exporter.Zipkin.Tests.csproj", "{1D778D2E-9523-450E-A6E0-A36897C7E78E}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.Exporter.AspNet.Win", "samples\Exporters\AspNet\OpenTelemetry.Exporter.AspNet.Win.csproj", "{9A4E3A68-904B-4835-A3C8-F664B73098DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Collector.AspNet.Win", "src\OpenTelemetry.Collector.AspNet\OpenTelemetry.Collector.AspNet.Win.csproj", "{B9EEACDD-CAFA-4B75-A18D-898E7DE21B17}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Collector.AspNet.Tests.Win", "test\OpenTelemetry.Collector.AspNet.Tests\OpenTelemetry.Collector.AspNet.Tests.Win.csproj", "{55CBAADE-7040-46D6-A845-F207B4F0E281}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -257,6 +266,18 @@ Global
{1D778D2E-9523-450E-A6E0-A36897C7E78E}.Debug|Any CPU.Build.0 = Debug|Any CPU {1D778D2E-9523-450E-A6E0-A36897C7E78E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D778D2E-9523-450E-A6E0-A36897C7E78E}.Release|Any CPU.ActiveCfg = Release|Any CPU {1D778D2E-9523-450E-A6E0-A36897C7E78E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D778D2E-9523-450E-A6E0-A36897C7E78E}.Release|Any CPU.Build.0 = Release|Any CPU {1D778D2E-9523-450E-A6E0-A36897C7E78E}.Release|Any CPU.Build.0 = Release|Any CPU
{9A4E3A68-904B-4835-A3C8-F664B73098DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9A4E3A68-904B-4835-A3C8-F664B73098DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9A4E3A68-904B-4835-A3C8-F664B73098DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9A4E3A68-904B-4835-A3C8-F664B73098DB}.Release|Any CPU.Build.0 = Release|Any CPU
{B9EEACDD-CAFA-4B75-A18D-898E7DE21B17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B9EEACDD-CAFA-4B75-A18D-898E7DE21B17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9EEACDD-CAFA-4B75-A18D-898E7DE21B17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9EEACDD-CAFA-4B75-A18D-898E7DE21B17}.Release|Any CPU.Build.0 = Release|Any CPU
{55CBAADE-7040-46D6-A845-F207B4F0E281}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55CBAADE-7040-46D6-A845-F207B4F0E281}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55CBAADE-7040-46D6-A845-F207B4F0E281}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55CBAADE-7040-46D6-A845-F207B4F0E281}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -270,6 +291,7 @@ Global
{CEB7F146-81DC-41DB-8015-140EC6A64E6C} = {0169B149-FB8B-46F4-9EF7-8A0E69F8FAAF} {CEB7F146-81DC-41DB-8015-140EC6A64E6C} = {0169B149-FB8B-46F4-9EF7-8A0E69F8FAAF}
{47318988-CA8B-4C81-B55D-2FA11D295A49} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E} {47318988-CA8B-4C81-B55D-2FA11D295A49} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E}
{25C06046-C7D0-46B4-AAAC-90C50C43DE7A} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E} {25C06046-C7D0-46B4-AAAC-90C50C43DE7A} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E}
{9A4E3A68-904B-4835-A3C8-F664B73098DB} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521} SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521}

View File

@ -57,6 +57,7 @@ Myget feeds:
| Package | MyGet (CI) | NuGet (releases) | | Package | MyGet (CI) | NuGet (releases) |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| ASP.NET Core | [![MyGet Nightly][OpenTelemetry-collect-aspnetcore-myget-image]][OpenTelemetry-collect-aspnetcore-myget-url] | [![NuGet Release][OpenTelemetry-collect-aspnetcore-nuget-image]][OpenTelemetry-collect-aspnetcore-nuget-url] | | ASP.NET Core | [![MyGet Nightly][OpenTelemetry-collect-aspnetcore-myget-image]][OpenTelemetry-collect-aspnetcore-myget-url] | [![NuGet Release][OpenTelemetry-collect-aspnetcore-nuget-image]][OpenTelemetry-collect-aspnetcore-nuget-url] |
| ASP.NET (WebForms, MVC, & WebAPI) | [![MyGet Nightly][OpenTelemetry-collect-aspnet-myget-image]][OpenTelemetry-collect-aspnet-myget-url] | [![NuGet Release][OpenTelemetry-collect-aspnet-nuget-image]][OpenTelemetry-collect-aspnet-nuget-url] |
| .NET Core HttpClient, Microsoft.Data.SqlClient, System.Data.SqlClient, & Azure SDKs | [![MyGet Nightly][OpenTelemetry-collect-deps-myget-image]][OpenTelemetry-collect-deps-myget-url] | [![NuGet Release][OpenTelemetry-collect-deps-nuget-image]][OpenTelemetry-collect-deps-nuget-url] | | .NET Core HttpClient, Microsoft.Data.SqlClient, System.Data.SqlClient, & Azure SDKs | [![MyGet Nightly][OpenTelemetry-collect-deps-myget-image]][OpenTelemetry-collect-deps-myget-url] | [![NuGet Release][OpenTelemetry-collect-deps-nuget-image]][OpenTelemetry-collect-deps-nuget-url] |
| StackExchange.Redis | [![MyGet Nightly][OpenTelemetry-collect-stackexchange-redis-myget-image]][OpenTelemetry-collect-stackexchange-redis-myget-url] | [![NuGet Release][OpenTelemetry-collect-stackexchange-redis-nuget-image]][OpenTelemetry-collect-stackexchange-redis-nuget-url] | | StackExchange.Redis | [![MyGet Nightly][OpenTelemetry-collect-stackexchange-redis-myget-image]][OpenTelemetry-collect-stackexchange-redis-myget-url] | [![NuGet Release][OpenTelemetry-collect-stackexchange-redis-nuget-image]][OpenTelemetry-collect-stackexchange-redis-nuget-url] |
@ -278,6 +279,47 @@ Configuration is done by user application: it should configure exporter and may
}); });
``` ```
### Configuration with ASP.NET (Full .NET Framework) running in IIS or IIS Express (if supported)
1. Add a reference to the `OpenTelemetry.Collector.AspNet` package. Add any other collectors & exporters you will need.
2. Add the Microsoft telemetry module in your `Web.config`:
```xml
<system.webServer>
<modules>
<add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" preCondition="integratedMode,managedHandler"/>
</modules>
</system.webServer>
```
3. Configure OpenTelemetry in your application startup:
```csharp
public class WebApiApplication : HttpApplication
{
private TracerFactory tracerFactory;
protected void Application_Start()
{
this.tracerFactory = TracerFactory.Create(builder =>
{
builder
.UseJaeger(c =>
{
c.AgentHost = "localhost";
c.AgentPort = 6831;
})
.AddRequestCollector()
.AddDependencyCollector();
});
}
protected void Application_End()
{
this.tracerFactory?.Dispose();
}
}
```
### Using StackExchange.Redis collector ### Using StackExchange.Redis collector
Outgoing http calls to Redis made using StackExchange.Redis library can be automatically tracked. Outgoing http calls to Redis made using StackExchange.Redis library can be automatically tracked.
@ -657,6 +699,8 @@ deprecate it for 18 months before removing it, if possible.
[OpenTelemetry-exporter-console-myget-url]: https://www.myget.org/feed/opentelemetry/package/nuget/OpenTelemetry.Exporter.Console [OpenTelemetry-exporter-console-myget-url]: https://www.myget.org/feed/opentelemetry/package/nuget/OpenTelemetry.Exporter.Console
[OpenTelemetry-collect-aspnetcore-myget-image]:https://img.shields.io/myget/opentelemetry/vpre/OpenTelemetry.Collector.AspNetCore.svg [OpenTelemetry-collect-aspnetcore-myget-image]:https://img.shields.io/myget/opentelemetry/vpre/OpenTelemetry.Collector.AspNetCore.svg
[OpenTelemetry-collect-aspnetcore-myget-url]: https://www.myget.org/feed/opentelemetry/package/nuget/OpenTelemetry.Collector.AspNetCore [OpenTelemetry-collect-aspnetcore-myget-url]: https://www.myget.org/feed/opentelemetry/package/nuget/OpenTelemetry.Collector.AspNetCore
[OpenTelemetry-collect-aspnet-myget-image]:https://img.shields.io/myget/opentelemetry/vpre/OpenTelemetry.Collector.AspNet.svg
[OpenTelemetry-collect-aspnet-myget-url]: https://www.myget.org/feed/opentelemetry/package/nuget/OpenTelemetry.Collector.AspNet
[OpenTelemetry-collect-deps-myget-image]:https://img.shields.io/myget/opentelemetry/vpre/OpenTelemetry.Collector.Dependencies.svg [OpenTelemetry-collect-deps-myget-image]:https://img.shields.io/myget/opentelemetry/vpre/OpenTelemetry.Collector.Dependencies.svg
[OpenTelemetry-collect-deps-myget-url]: https://www.myget.org/feed/opentelemetry/package/nuget/OpenTelemetry.Collector.Dependencies [OpenTelemetry-collect-deps-myget-url]: https://www.myget.org/feed/opentelemetry/package/nuget/OpenTelemetry.Collector.Dependencies
[OpenTelemetry-collect-stackexchange-redis-myget-image]:https://img.shields.io/myget/opentelemetry/vpre/OpenTelemetry.Collector.StackExchangeRedis.svg [OpenTelemetry-collect-stackexchange-redis-myget-image]:https://img.shields.io/myget/opentelemetry/vpre/OpenTelemetry.Collector.StackExchangeRedis.svg
@ -685,6 +729,8 @@ deprecate it for 18 months before removing it, if possible.
[OpenTelemetry-exporter-newrelic-nuget-url]: https://www.nuget.org/packages/OpenTelemetry.Exporter.NewRelic [OpenTelemetry-exporter-newrelic-nuget-url]: https://www.nuget.org/packages/OpenTelemetry.Exporter.NewRelic
[OpenTelemetry-collect-aspnetcore-nuget-image]:https://img.shields.io/nuget/vpre/OpenTelemetry.Collector.AspNetCore.svg [OpenTelemetry-collect-aspnetcore-nuget-image]:https://img.shields.io/nuget/vpre/OpenTelemetry.Collector.AspNetCore.svg
[OpenTelemetry-collect-aspnetcore-nuget-url]: https://www.nuget.org/packages/OpenTelemetry.Collector.AspNetCore [OpenTelemetry-collect-aspnetcore-nuget-url]: https://www.nuget.org/packages/OpenTelemetry.Collector.AspNetCore
[OpenTelemetry-collect-aspnet-nuget-image]:https://img.shields.io/nuget/vpre/OpenTelemetry.Collector.AspNet.svg
[OpenTelemetry-collect-aspnet-nuget-url]: https://www.nuget.org/packages/OpenTelemetry.Collector.AspNet
[OpenTelemetry-collect-deps-nuget-image]:https://img.shields.io/nuget/vpre/OpenTelemetry.Collector.Dependencies.svg [OpenTelemetry-collect-deps-nuget-image]:https://img.shields.io/nuget/vpre/OpenTelemetry.Collector.Dependencies.svg
[OpenTelemetry-collect-deps-nuget-url]: https://www.nuget.org/packages/OpenTelemetry.Collector.Dependencies [OpenTelemetry-collect-deps-nuget-url]: https://www.nuget.org/packages/OpenTelemetry.Collector.Dependencies
[OpenTelemetry-collect-stackexchange-redis-nuget-image]:https://img.shields.io/nuget/vpre/OpenTelemetry.Collector.StackExchangeRedis.svg [OpenTelemetry-collect-stackexchange-redis-nuget-image]:https://img.shields.io/nuget/vpre/OpenTelemetry.Collector.StackExchangeRedis.svg

View File

@ -0,0 +1,21 @@
using System.Web.Mvc;
using System.Web.Routing;
namespace OpenTelemetry.Exporter.AspNet
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}

View File

@ -0,0 +1,25 @@
using System.Net.Http.Formatting;
using System.Web.Http;
namespace OpenTelemetry.Exporter.AspNet
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
}
}
}

View File

@ -0,0 +1,21 @@
using System.Web.Mvc;
namespace OpenTelemetry.Exporter.AspNet.Controllers
{
public class HomeController : Controller
{
// For testing traditional routing. Ex: https://localhost:XXXX/
public ActionResult Index()
{
return this.View();
}
[Route("about_attr_route/{customerId}")] // For testing attribute routing. Ex: https://localhost:XXXX/about_attr_route
public ActionResult About(int? customerId)
{
this.ViewBag.Message = $"Your application description page for customer {customerId}.";
return this.View();
}
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using OpenTelemetry.Exporter.AspNet.Models;
namespace OpenTelemetry.Exporter.AspNet.Controllers
{
public class WeatherForecastController : ApiController
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
[HttpGet] // For testing traditional routing. Ex: https://localhost:XXXX/api/weatherforecast
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
[Route("subroute/{customerId}")] // For testing attribute routing. Ex: https://localhost:XXXX/subroute/10
[HttpGet]
public IEnumerable<WeatherForecast> Get(int customerId)
{
if (customerId < 0)
{
throw new ArgumentException();
}
return this.Get();
}
}
}

View File

@ -0,0 +1 @@
<%@ Application Codebehind="Global.asax.cs" Inherits="OpenTelemetry.Exporter.AspNet.WebApiApplication" Language="C#" %>

View File

@ -0,0 +1,38 @@
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
using OpenTelemetry.Trace.Configuration;
namespace OpenTelemetry.Exporter.AspNet
{
public class WebApiApplication : HttpApplication
{
private TracerFactory tracerFactory;
protected void Application_Start()
{
this.tracerFactory = TracerFactory.Create(builder =>
{
builder
.UseJaeger(c =>
{
c.AgentHost = "localhost";
c.AgentPort = 6831;
})
.AddRequestCollector()
.AddDependencyCollector();
});
GlobalConfiguration.Configure(WebApiConfig.Register);
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
protected void Application_End()
{
this.tracerFactory?.Dispose();
}
}
}

View File

@ -0,0 +1,15 @@
using System;
namespace OpenTelemetry.Exporter.AspNet.Models
{
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(this.TemperatureC / 0.5556);
public string Summary { get; set; }
}
}

View File

@ -0,0 +1,132 @@
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{9A4E3A68-904B-4835-A3C8-F664B73098DB}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenTelemetry.Exporter.AspNet</RootNamespace>
<AssemblyName>OpenTelemetry.Exporter.AspNet</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<UseIISExpress>true</UseIISExpress>
<Use64BitIISExpress />
<IISExpressSSLPort>
</IISExpressSSLPort>
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Web" />
</ItemGroup>
<ItemGroup>
<Content Include="Global.asax" />
<Content Include="Web.config" />
</ItemGroup>
<ItemGroup>
<Compile Include="App_Start\RouteConfig.cs" />
<Compile Include="App_Start\WebApiConfig.cs" />
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Controllers\WeatherForecastController.cs" />
<Compile Include="Global.asax.cs">
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="Models\WeatherForecast.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\_ViewStart.cshtml" />
<Content Include="Views\Home\Index.cshtml" />
<Content Include="Views\Shared\_Layout.cshtml" />
<Content Include="Views\Web.config" />
<Content Include="Views\Home\About.cshtml" />
<None Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon>
</None>
<None Include="Web.Release.config">
<DependentUpon>Web.config</DependentUpon>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNet.WebApi.WebHost" Version="5.2.7" />
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.7" />
<PackageReference Include="Microsoft.AspNet.WebPages" Version="3.2.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\OpenTelemetry.Api\OpenTelemetry.Api.csproj">
<Project>{99f8a331-05e9-45a5-89ba-4c54e825e5b2}</Project>
<Name>OpenTelemetry.Api</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\OpenTelemetry.Collector.AspNet\OpenTelemetry.Collector.AspNet.Win.csproj">
<Project>{b9eeacdd-cafa-4b75-a18d-898e7de21b17}</Project>
<Name>OpenTelemetry.Collector.AspNet.Win</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\OpenTelemetry.Collector.Dependencies\OpenTelemetry.Collector.Dependencies.csproj">
<Project>{d3ffbc59-2486-4f8f-bff1-fa95c84929e1}</Project>
<Name>OpenTelemetry.Collector.Dependencies</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj">
<Project>{8d47e3cf-9ae3-42fe-9084-feb72d9ad769}</Project>
<Name>OpenTelemetry.Exporter.Jaeger</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\OpenTelemetry\OpenTelemetry.csproj">
<Project>{ae3e3df5-4083-4c6e-a840-8271b0acde7e}</Project>
<Name>OpenTelemetry</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>0</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:56171/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenTelemetry.Exporter.AspNet")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OpenTelemetry.Exporter.AspNet")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("9a4e3a68-904b-4835-a3c8-f664b73098db")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,7 @@
@{
ViewBag.Title = "About";
}
<h2>@ViewBag.Title.</h2>
<h3>@ViewBag.Message</h3>
<p>Use this area to provide additional information.</p>

View File

@ -0,0 +1,31 @@
@{
ViewBag.Title = "Home Page";
}
<div class="jumbotron">
<h1>ASP.NET</h1>
<p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
<p><a href="https://asp.net" class="btn btn-primary btn-lg">Learn more &raquo;</a></p>
</div>
<div class="row">
<div class="col-md-4">
<h2>Getting started</h2>
<p>
ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that
enables a clean separation of concerns and gives you full control over markup
for enjoyable, agile development.
</p>
<p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301865">Learn more &raquo;</a></p>
</div>
<div class="col-md-4">
<h2>Get more libraries</h2>
<p>NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.</p>
<p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301866">Learn more &raquo;</a></p>
</div>
<div class="col-md-4">
<h2>Web Hosting</h2>
<p>You can easily find a web hosting company that offers the right mix of features and price for your applications.</p>
<p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301867">Learn more &raquo;</a></p>
</div>
</div>

View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
@RenderSection("scripts", required: false)
</body>
</html>

View File

@ -0,0 +1,42 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.webServer>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
<system.web>
<compilation>
<assemblies>
<add assembly="System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
</assemblies>
</compilation>
</system.web>
</configuration>

View File

@ -0,0 +1,3 @@
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- For more information on using web.config transformation visit https://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!--
In the example below, the "SetAttributes" transform will change the value of
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
finds an attribute "name" that has a value of "MyDB".
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<system.web>
<!--
In the example below, the "Replace" transform will replace the entire
<customErrors> section of your web.config file.
Note that because there is only one customErrors section under the
<system.web> node, there is no need to use the "xdt:Locator" attribute.
<customErrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
-->
</system.web>
</configuration>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- For more information on using web.config transformation visit https://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!--
In the example below, the "SetAttributes" transform will change the value of
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
finds an attribute "name" that has a value of "MyDB".
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
<!--
In the example below, the "Replace" transform will replace the entire
<customErrors> section of your web.config file.
Note that because there is only one customErrors section under the
<system.web> node, there is no need to use the "xdt:Locator" attribute.
<customErrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
-->
</system.web>
</configuration>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="webpages:Version" value="3.0.0.0"/>
<add key="webpages:Enabled" value="false"/>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.8"/>
<httpRuntime targetFramework="4.8"/>
</system.web>
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
<remove name="OPTIONSVerbHandler"/>
<remove name="TRACEVerbHandler"/>
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
</handlers>
<modules>
<add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" preCondition="integratedMode,managedHandler"/>
</modules>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -4,6 +4,7 @@
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn> <NoWarn>$(NoWarn);1591</NoWarn>
<IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -0,0 +1,60 @@
// <copyright file="AspNetCollector.cs" company="OpenTelemetry Authors">
// Copyright 2018, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System;
using OpenTelemetry.Collector.AspNet.Implementation;
using OpenTelemetry.Trace;
namespace OpenTelemetry.Collector.AspNet
{
/// <summary>
/// Requests collector.
/// </summary>
public class AspNetCollector : IDisposable
{
internal const string AspNetDiagnosticListenerName = "Microsoft.AspNet.TelemetryCorrelation";
private readonly DiagnosticSourceSubscriber diagnosticSourceSubscriber;
/// <summary>
/// Initializes a new instance of the <see cref="AspNetCollector"/> class.
/// </summary>
/// <param name="tracer">Tracer to record traced with.</param>
public AspNetCollector(Tracer tracer)
: this(tracer, new AspNetCollectorOptions())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="AspNetCollector"/> class.
/// </summary>
/// <param name="tracer">Tracer to record traced with.</param>
/// <param name="options">Configuration options for ASP.NET collector.</param>
public AspNetCollector(Tracer tracer, AspNetCollectorOptions options)
{
this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(
name => new HttpInListener(name, tracer, options),
listener => listener.Name == AspNetDiagnosticListenerName,
null);
this.diagnosticSourceSubscriber.Subscribe();
}
/// <inheritdoc/>
public void Dispose()
{
this.diagnosticSourceSubscriber?.Dispose();
}
}
}

View File

@ -0,0 +1,43 @@
// <copyright file="AspNetCollectorOptions.cs" company="OpenTelemetry Authors">
// Copyright 2018, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System;
using System.Web;
using OpenTelemetry.Context.Propagation;
namespace OpenTelemetry.Collector.AspNet
{
/// <summary>
/// Options for requests collector.
/// </summary>
public class AspNetCollectorOptions
{
/// <summary>
/// Gets or sets <see cref="ITextFormat"/> for context propagation.
/// </summary>
public ITextFormat TextFormat { get; set; } = new TraceContextFormat();
/// <summary>
/// Gets or sets a hook to exclude calls based on domain or other per-request criterion.
/// </summary>
internal Predicate<HttpContext> RequestFilter { get; set; } = DefaultFilter;
private static bool DefaultFilter(HttpContext httpContext)
{
return true;
}
}
}

View File

@ -0,0 +1,22 @@
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
// Copyright 2018, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System.Runtime.CompilerServices;
#if SIGNED
[assembly: InternalsVisibleTo("OpenTelemetry.Collector.AspNet.Tests.Win, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")]
#else
[assembly: InternalsVisibleTo("OpenTelemetry.Collector.AspNet.Tests.Win")]
#endif

View File

@ -0,0 +1,144 @@
// <copyright file="HttpInListener.cs" company="OpenTelemetry Authors">
// Copyright 2018, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System;
using System.Diagnostics;
using System.Web;
using System.Web.Routing;
using OpenTelemetry.Context.Propagation;
using OpenTelemetry.Trace;
namespace OpenTelemetry.Collector.AspNet.Implementation
{
internal class HttpInListener : ListenerHandler
{
private readonly PropertyFetcher routeFetcher = new PropertyFetcher("Route");
private readonly PropertyFetcher routeTemplateFetcher = new PropertyFetcher("RouteTemplate");
private readonly AspNetCollectorOptions options;
public HttpInListener(string name, Tracer tracer, AspNetCollectorOptions options)
: base(name, tracer)
{
this.options = options ?? throw new ArgumentNullException(nameof(options));
}
public override void OnStartActivity(Activity activity, object payload)
{
const string EventNameSuffix = ".OnStartActivity";
var context = HttpContext.Current;
if (context == null)
{
CollectorEventSource.Log.NullPayload(nameof(HttpInListener) + EventNameSuffix);
return;
}
if (this.options.RequestFilter != null && !this.options.RequestFilter(context))
{
CollectorEventSource.Log.RequestIsFilteredOut(activity.OperationName);
return;
}
var request = context.Request;
var requestValues = request.Unvalidated;
// see the spec https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
var path = requestValues.Path;
TelemetrySpan span;
if (this.options.TextFormat is TraceContextFormat)
{
this.Tracer.StartActiveSpanFromActivity(path, Activity.Current, SpanKind.Server, out span);
}
else
{
var ctx = this.options.TextFormat.Extract<HttpRequest>(
request,
(r, name) => requestValues.Headers.GetValues(name));
this.Tracer.StartActiveSpan(path, ctx, SpanKind.Server, out span);
}
if (span.IsRecording)
{
span.PutHttpHostAttribute(request.Url.Host, request.Url.Port);
span.PutHttpMethodAttribute(request.HttpMethod);
span.PutHttpPathAttribute(path);
span.PutHttpUserAgentAttribute(request.UserAgent);
span.PutHttpRawUrlAttribute(request.Url.ToString());
}
}
public override void OnStopActivity(Activity activity, object payload)
{
const string EventNameSuffix = ".OnStopActivity";
var span = this.Tracer.CurrentSpan;
if (span == null || !span.Context.IsValid)
{
CollectorEventSource.Log.NullOrBlankSpan(nameof(HttpInListener) + EventNameSuffix);
return;
}
if (span.IsRecording)
{
var context = HttpContext.Current;
if (context == null)
{
CollectorEventSource.Log.NullPayload(nameof(HttpInListener) + EventNameSuffix);
return;
}
var response = context.Response;
span.PutHttpStatusCode(response.StatusCode, response.StatusDescription);
var routeData = context.Request.RequestContext.RouteData;
string template = null;
if (routeData.Values.TryGetValue("MS_SubRoutes", out object msSubRoutes))
{
// WebAPI attribute routing flows here. Use reflection to not take a dependency on microsoft.aspnet.webapi.core\[version]\lib\[framework]\System.Web.Http.
if (msSubRoutes is Array attributeRouting && attributeRouting.Length == 1)
{
var subRouteData = attributeRouting.GetValue(0);
var route = this.routeFetcher.Fetch(subRouteData);
template = this.routeTemplateFetcher.Fetch(route) as string;
}
}
else if (routeData.Route is Route route)
{
// MVC + WebAPI traditional routing & MVC attribute routing flow here.
template = route.Url;
}
if (!string.IsNullOrEmpty(template))
{
// Override the span name that was previously set to the path part of URL.
span.UpdateName(template);
span.PutHttpRouteAttribute(template);
}
}
span.End();
}
}
}

View File

@ -0,0 +1,94 @@
// <copyright file="PropertyFetcher.cs" company="OpenTelemetry Authors">
// Copyright 2018, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System;
using System.Linq;
using System.Reflection;
namespace OpenTelemetry.Collector.AspNet.Implementation
{
internal class PropertyFetcher
{
private readonly string propertyName;
private PropertyFetch innerFetcher;
public PropertyFetcher(string propertyName)
{
this.propertyName = propertyName;
}
public object Fetch(object obj)
{
if (this.innerFetcher == null)
{
var type = obj.GetType().GetTypeInfo();
var property = type.DeclaredProperties.FirstOrDefault(p => string.Equals(p.Name, this.propertyName, StringComparison.InvariantCultureIgnoreCase));
if (property == null)
{
property = type.GetProperty(this.propertyName);
}
this.innerFetcher = PropertyFetch.FetcherForProperty(property);
}
return this.innerFetcher?.Fetch(obj);
}
// see https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs
private class PropertyFetch
{
/// <summary>
/// Create a property fetcher from a .NET Reflection PropertyInfo class that
/// represents a property of a particular type.
/// </summary>
public static PropertyFetch FetcherForProperty(PropertyInfo propertyInfo)
{
if (propertyInfo == null)
{
// returns null on any fetch.
return new PropertyFetch();
}
var typedPropertyFetcher = typeof(TypedFetchProperty<,>);
var instantiatedTypedPropertyFetcher = typedPropertyFetcher.GetTypeInfo().MakeGenericType(
propertyInfo.DeclaringType, propertyInfo.PropertyType);
return (PropertyFetch)Activator.CreateInstance(instantiatedTypedPropertyFetcher, propertyInfo);
}
/// <summary>
/// Given an object, fetch the property that this propertyFetch represents.
/// </summary>
public virtual object Fetch(object obj)
{
return null;
}
private class TypedFetchProperty<TObject, TProperty> : PropertyFetch
{
private readonly Func<TObject, TProperty> propertyFetch;
public TypedFetchProperty(PropertyInfo property)
{
this.propertyFetch = (Func<TObject, TProperty>)property.GetMethod.CreateDelegate(typeof(Func<TObject, TProperty>));
}
public override object Fetch(object obj)
{
return this.propertyFetch((TObject)obj);
}
}
}
}
}

View File

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net46</TargetFrameworks>
<Description>OpenTelemetry collector for ASP.NET requests</Description>
<AssemblyName>OpenTelemetry.Collector.AspNet</AssemblyName>
<PackageTags>$(PackageTags);distributed-tracing;AspNet;MVC;WebAPI</PackageTags>
</PropertyGroup>
<ItemGroup>
<Reference Include="System.Web" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNet.TelemetryCorrelation" Version="1.0.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,66 @@
// <copyright file="TracerBuilderExtensions.cs" company="OpenTelemetry Authors">
// Copyright 2018, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System;
using OpenTelemetry.Collector.AspNet;
namespace OpenTelemetry.Trace.Configuration
{
/// <summary>
/// Extension methods to simplify registering of data collection.
/// </summary>
public static class TracerBuilderExtensions
{
/// <summary>
/// Enables the incoming requests automatic data collection.
/// </summary>
/// <param name="builder">Trace builder to use.</param>
/// <returns>The instance of <see cref="TracerBuilder"/> to chain the calls.</returns>
public static TracerBuilder AddRequestCollector(this TracerBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
return builder.AddCollector(t => new AspNetCollector(t));
}
/// <summary>
/// Enables the incoming requests automatic data collection.
/// </summary>
/// <param name="builder">Trace builder to use.</param>
/// <param name="configure">Configuration options.</param>
/// <returns>The instance of <see cref="TracerBuilder"/> to chain the calls.</returns>
public static TracerBuilder AddRequestCollector(this TracerBuilder builder, Action<AspNetCollectorOptions> configure)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}
var options = new AspNetCollectorOptions();
configure(options);
return builder.AddCollector(t => new AspNetCollector(t, options));
}
}
}

View File

@ -15,7 +15,6 @@
// </copyright> // </copyright>
using System; using System;
using OpenTelemetry.Collector.AspNetCore.Implementation; using OpenTelemetry.Collector.AspNetCore.Implementation;
using OpenTelemetry.Context.Propagation;
using OpenTelemetry.Trace; using OpenTelemetry.Trace;
namespace OpenTelemetry.Collector.AspNetCore namespace OpenTelemetry.Collector.AspNetCore
@ -40,7 +39,7 @@ namespace OpenTelemetry.Collector.AspNetCore
/// Initializes a new instance of the <see cref="AspNetCoreCollector"/> class. /// Initializes a new instance of the <see cref="AspNetCoreCollector"/> class.
/// </summary> /// </summary>
/// <param name="tracer">Tracer to record traced with.</param> /// <param name="tracer">Tracer to record traced with.</param>
/// <param name="options">Configuration options for dependencies collector.</param> /// <param name="options">Configuration options for ASP.NET Core collector.</param>
public AspNetCoreCollector(Tracer tracer, AspNetCoreCollectorOptions options) public AspNetCoreCollector(Tracer tracer, AspNetCoreCollectorOptions options)
{ {
this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpInListener("Microsoft.AspNetCore", tracer, options), null); this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpInListener("Microsoft.AspNetCore", tracer, options), null);

View File

@ -11,10 +11,4 @@
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="2.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Update="MinVer" Version="2.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project> </Project>

View File

@ -9,8 +9,4 @@
<ProjectReference Include="..\OpenTelemetry\OpenTelemetry.csproj" /> <ProjectReference Include="..\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net46'">
<Reference Include="System.Net.Http" />
</ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,33 @@
// <copyright file="BasicTests.cs" company="OpenTelemetry Authors">
// Copyright 2018, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using OpenTelemetry.Trace.Configuration;
using Xunit;
using System;
namespace OpenTelemetry.Collector.AspNet.Tests
{
public class BasicTests
{
[Fact]
public void AddRequestCollector_BadArgs()
{
TracerBuilder builder = null;
Assert.Throws<ArgumentNullException>(() => builder.AddRequestCollector());
Assert.Throws<ArgumentNullException>(() => TracerFactory.Create(b => b.AddRequestCollector(null)));
}
}
}

View File

@ -0,0 +1,225 @@
// <copyright file="HttpInListenerTests.cs" company="OpenTelemetry Authors">
// Copyright 2018, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Routing;
using Moq;
using OpenTelemetry.Trace;
using OpenTelemetry.Trace.Configuration;
using OpenTelemetry.Trace.Export;
using Xunit;
namespace OpenTelemetry.Collector.AspNet.Tests
{
public class HttpInListenerTests : IDisposable
{
private readonly FakeAspNetDiagnosticSource fakeAspNetDiagnosticSource;
public HttpInListenerTests()
{
this.fakeAspNetDiagnosticSource = new FakeAspNetDiagnosticSource();
}
public void Dispose()
{
this.fakeAspNetDiagnosticSource.Dispose();
}
[Theory]
[InlineData("http://localhost/", 0, null)]
[InlineData("https://localhost/", 0, null)]
[InlineData("http://localhost:443/", 0, null)] // Test http over 443
[InlineData("https://localhost:80/", 0, null)] // Test https over 80
[InlineData("http://localhost:80/Index", 1, "{controller}/{action}/{id}")]
[InlineData("https://localhost:443/about_attr_route/10", 2, "about_attr_route/{customerId}")]
[InlineData("http://localhost:1880/api/weatherforecast", 3, "api/{controller}/{id}")]
[InlineData("https://localhost:1843/subroute/10", 4, "subroute/{customerId}")]
[InlineData("http://localhost/api/value", 0, null, "/api/value")] // Request will be filtered
[InlineData("http://localhost/api/value/2", 0, null, "/api/value")] // Request will not be filtered
[InlineData("http://localhost/api/value", 0, null, "{ThrowException}")] // Filter user code will throw an exception
public void AspNetRequestsAreCollectedSuccessfully(string url, int routeType, string routeTemplate, string filter = null)
{
RouteData routeData;
switch (routeType)
{
case 0: // WebForm, no route data.
routeData = new RouteData();
break;
case 1: // Traditional MVC.
case 2: // Attribute routing MVC.
case 3: // Traditional WebAPI.
routeData = new RouteData()
{
Route = new Route(routeTemplate, null),
};
break;
case 4: // Attribute routing WebAPI.
routeData = new RouteData();
routeData.Values.Add("MS_SubRoutes", new[] {
new
{
Route = new
{
RouteTemplate = routeTemplate,
},
},
});
break;
default:
throw new NotSupportedException();
}
var workerRequest = new Mock<HttpWorkerRequest>();
workerRequest.Setup(wr => wr.GetKnownRequestHeader(It.IsAny<int>())).Returns<int>(i =>
{
return i switch
{
39 => "Test", // User-Agent
_ => null,
};
});
HttpContext.Current = new HttpContext(
new HttpRequest("", url, "")
{
RequestContext = new RequestContext()
{
RouteData = routeData,
},
},
new HttpResponse(new StringWriter()));
typeof(HttpRequest).GetField("_wr", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(HttpContext.Current.Request, workerRequest.Object);
var activity = new Activity("Current").AddBaggage("Stuff", "123");
activity.Start();
try
{
var spanProcessor = new Mock<SpanProcessor>();
var tracer = TracerFactory.Create(b => b
.AddProcessorPipeline(p => p.AddProcessor(_ => spanProcessor.Object)))
.GetTracer(null);
using (new AspNetCollector(
tracer,
new AspNetCollectorOptions
{
RequestFilter = httpContext =>
{
if (string.IsNullOrEmpty(filter))
return true;
if (filter == "{ThrowException}")
throw new InvalidOperationException();
return httpContext.Request.Path != filter;
},
}))
{
this.fakeAspNetDiagnosticSource.Write(
"Start",
null);
this.fakeAspNetDiagnosticSource.Write(
"Stop",
null);
}
if (HttpContext.Current.Request.Path == filter || filter == "{ThrowException}")
{
Assert.Equal(0, spanProcessor.Invocations.Count); // Nothing was called because request was filtered.
return;
}
Assert.Equal(2, spanProcessor.Invocations.Count);
var span = (SpanData)spanProcessor.Invocations[1].Arguments[0];
Assert.Equal(routeTemplate ?? HttpContext.Current.Request.Path, span.Name);
Assert.Equal(SpanKind.Server, span.Kind);
Assert.Equal(CanonicalCode.Ok, span.Status.CanonicalCode);
Assert.Equal("OK", span.Status.Description);
var expectedUri = new Uri(url);
var actualUrl = (string)span.Attributes.FirstOrDefault(i => i.Key == SpanAttributeConstants.HttpUrlKey).Value;
Assert.Equal(expectedUri.ToString(), actualUrl);
// Url strips 80 or 443 if the scheme matches.
if ((expectedUri.Port == 80 && expectedUri.Scheme == "http") || (expectedUri.Port == 443 && expectedUri.Scheme == "https"))
{
Assert.DoesNotContain($":{expectedUri.Port}", actualUrl);
}
else
{
Assert.Contains($":{expectedUri.Port}", actualUrl);
}
// Host includes port if it isn't 80 or 443.
if (expectedUri.Port == 80 || expectedUri.Port == 443)
{
Assert.Equal(
expectedUri.Host,
span.Attributes.FirstOrDefault(i => i.Key == SpanAttributeConstants.HttpHostKey).Value as string);
}
else
{
Assert.Equal(
$"{expectedUri.Host}:{expectedUri.Port}",
span.Attributes.FirstOrDefault(i => i.Key == SpanAttributeConstants.HttpHostKey).Value as string);
}
Assert.Equal(
HttpContext.Current.Request.HttpMethod,
span.Attributes.FirstOrDefault(i => i.Key == SpanAttributeConstants.HttpMethodKey).Value as string);
Assert.Equal(
HttpContext.Current.Request.Path,
span.Attributes.FirstOrDefault(i => i.Key == SpanAttributeConstants.HttpPathKey).Value as string);
Assert.Equal(
HttpContext.Current.Request.UserAgent,
span.Attributes.FirstOrDefault(i => i.Key == SpanAttributeConstants.HttpUserAgentKey).Value as string);
}
finally
{
activity.Stop();
}
}
private class FakeAspNetDiagnosticSource : IDisposable
{
private readonly DiagnosticListener listener;
public FakeAspNetDiagnosticSource()
{
this.listener = new DiagnosticListener(AspNetCollector.AspNetDiagnosticListenerName);
}
public void Write(string name, object value)
{
this.listener.Write(name, value);
}
public void Dispose()
{
this.listener.Dispose();
}
}
}
}

View File

@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Unit test project for OpenTelemetry ASP.NET collector</Description>
<TargetFrameworks>net46</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<None Remove="xunit.runner.json" />
</ItemGroup>
<ItemGroup>
<Content Include="xunit.runner.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="Moq" Version="4.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\OpenTelemetry.Collector.AspNet\OpenTelemetry.Collector.AspNet.Win.csproj" />
<ProjectReference Include="..\..\src\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Web" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,4 @@
{
"maxParallelThreads": 1,
"parallelizeTestCollections": false
}

View File

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>Unit test project for OpenTelemetry</Description> <Description>Unit test project for OpenTelemetry ASP.NET Core collector</Description>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks> <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
</PropertyGroup> </PropertyGroup>

View File

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>Unit test project for OpenTelemetry</Description> <Description>Unit test project for OpenTelemetry dependency collectors</Description>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks> <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
</PropertyGroup> </PropertyGroup>

View File

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>Unit test project for ApplicationInsights Exporter for OpenTelemetry</Description> <Description>Unit test project for OpenTelemetry StackExchangeRedis collector</Description>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks> <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net461</TargetFrameworks> <TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net461</TargetFrameworks>
</PropertyGroup> </PropertyGroup>

View File

@ -1,25 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <Description>Unit test project for LightStep Exporter for OpenTelemetry</Description>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<IsPackable>false</IsPackable> <ItemGroup>
</PropertyGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Moq" Version="4.11.0" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" /> <ProjectReference Include="..\..\src\OpenTelemetry.Api\OpenTelemetry.Api.csproj" />
<PackageReference Include="xunit" Version="2.4.1" /> <ProjectReference Include="..\..\src\OpenTelemetry.Exporter.LightStep\OpenTelemetry.Exporter.LightStep.csproj" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1"> <ProjectReference Include="..\..\src\OpenTelemetry\OpenTelemetry.csproj" />
<PrivateAssets>all</PrivateAssets> </ItemGroup>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Moq" Version="4.11.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\OpenTelemetry.Api\OpenTelemetry.Api.csproj" />
<ProjectReference Include="..\..\src\OpenTelemetry.Exporter.LightStep\OpenTelemetry.Exporter.LightStep.csproj" />
<ProjectReference Include="..\..\src\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup>
</Project> </Project>

View File

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>Unit test project for Prometheus Exporter for OpenTelemetry</Description>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>

View File

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>Unit test project for ApplicationInsights Exporter for OpenTelemetry</Description> <Description>Unit test project for OpenTelemetry .NET Core hosting library</Description>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks> <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net461</TargetFrameworks> <TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net461</TargetFrameworks>
</PropertyGroup> </PropertyGroup>