1
0
Форкнуть 0

Enable ServerTelemetryChannel in .net core by the default (#530)

* Update versions

* Switch to Server channel + port bond schemas

* Change order

* Fix remaining tests

* Remaining test for performance counters

* Add explicit DisableTestParallelization assembly attribute

* Update changelog

* Bring back initial condition for one of the tests

* Disable tests with listener parallelization

* lock object should be static...

* Missed two tests to wrap in lock
This commit is contained in:
YuliaSafarova 2017-09-25 10:37:09 -07:00 коммит произвёл GitHub
Родитель 3acf9bbe15
Коммит c7b0358424
49 изменённых файлов: 1506 добавлений и 255 удалений

Просмотреть файл

@ -40,11 +40,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionalTestUtils20", "te
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVCFramework.FunctionalTests", "test\MVCFramework.FunctionalTests\MVCFramework.FunctionalTests.csproj", "{1D5825CC-2EC9-43A1-BE32-778EFF5EAC80}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MVCFramework20.FunctionalTests", "test\MVCFramework20.FunctionalTests\MVCFramework20.FunctionalTests.csproj", "{51198C41-CD4A-4006-84D4-DE20A0A44363}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVCFramework20.FunctionalTests", "test\MVCFramework20.FunctionalTests\MVCFramework20.FunctionalTests.csproj", "{51198C41-CD4A-4006-84D4-DE20A0A44363}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApi.FunctionalTests", "test\WebApi.FunctionalTests\WebApi.FunctionalTests.csproj", "{325C4ECE-BD4A-4CF2-BC80-FBD1024B5935}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi20.FunctionalTests", "test\WebApi20.FunctionalTests\WebApi20.FunctionalTests.csproj", "{C3B3F515-0305-4809-A9A8-37FD80428F74}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApi20.FunctionalTests", "test\WebApi20.FunctionalTests\WebApi20.FunctionalTests.csproj", "{C3B3F515-0305-4809-A9A8-37FD80428F74}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApplicationInsightsTypes", "test\ApplicationInsightsTypes\ApplicationInsightsTypes.csproj", "{9DA7024F-216F-4FA5-9B6D-CE4216C2DD72}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -92,6 +94,10 @@ Global
{C3B3F515-0305-4809-A9A8-37FD80428F74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3B3F515-0305-4809-A9A8-37FD80428F74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3B3F515-0305-4809-A9A8-37FD80428F74}.Release|Any CPU.Build.0 = Release|Any CPU
{9DA7024F-216F-4FA5-9B6D-CE4216C2DD72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9DA7024F-216F-4FA5-9B6D-CE4216C2DD72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9DA7024F-216F-4FA5-9B6D-CE4216C2DD72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9DA7024F-216F-4FA5-9B6D-CE4216C2DD72}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -108,6 +114,7 @@ Global
{51198C41-CD4A-4006-84D4-DE20A0A44363} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
{325C4ECE-BD4A-4CF2-BC80-FBD1024B5935} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
{C3B3F515-0305-4809-A9A8-37FD80428F74} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
{9DA7024F-216F-4FA5-9B6D-CE4216C2DD72} = {8B5230E5-8138-44D6-839F-DF9248F195EE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {047855A4-470F-43B1-8B74-69651DD6B8A6}

Просмотреть файл

@ -4,6 +4,7 @@
- Project is upgraded to work with Visual Studio 2017. Also projects are modified to use csproj instead of project.json.
- Adaptive sampling enabled for both - full framework and .NET Core applications.
- ServerTelemetryChannel is enabled and set as default channel for both - full framework and .NET Core applications.
## Version 2.1.1

Просмотреть файл

@ -0,0 +1,47 @@
import "Domain.bond"
namespace AI
[Description("Instances of AvailabilityData represent the result of executing an availability test.")]
struct AvailabilityData
: Domain
{
[Description("Schema version")]
10: required int32 ver = 2;
[MaxStringLength("64")]
[Description("Identifier of a test run. Use it to correlate steps of test run and telemetry generated by the service.")]
[ActAsRequired("Renaming testRunId to id.")]
21: required string id;
[MaxStringLength("1024")]
[Description("Name of the test that these availability results represents.")]
[ActAsRequired("Renaming testName to name.")]
41: required string name;
[Description("Duration in TimeSpan 'G' (general long) format: d:hh:mm:ss.fffffff")]
[CSType("TimeSpan")]
50: required string duration;
[ActAsRequired("Renaming result to success.")]
[Description("Success flag.")]
61: required bool success;
[MaxStringLength("1024")]
[Description("Name of the location where the test was run from.")]
70: string runLocation;
[MaxStringLength("8192")]
[Description("Diagnostic message for the result.")]
80: string message;
[Description("Collection of custom properties.")]
[MaxKeyLength("150")]
[MaxValueLength("8192")]
100: map<string, string> properties;
[Description("Collection of custom measurements.")]
[MaxKeyLength("150")]
200: map<string, double> measurements;
}

Просмотреть файл

@ -0,0 +1,11 @@
namespace AI
[Description("Data struct to contain only C section with custom fields.")]
struct Base
{
[Name("ItemTypeName")]
[Description("Name of item (B section) if any. If telemetry data is derived straight from this, this should be null.")]
10: string baseType;
}

Просмотреть файл

@ -0,0 +1,101 @@
namespace AI
[ContextContract("Emit")]
[PseudoType("JSMap")]
struct ContextTagKeys
{
[Description("Application version. Information in the application context fields is always about the application that is sending the telemetry.")]
[MaxStringLength("1024")]
10: string ApplicationVersion = "ai.application.ver";
[Description("Unique client device id. Computer name in most cases.")]
[MaxStringLength("1024")]
100: string DeviceId = "ai.device.id";
[Description("Device locale using <language>-<REGION> pattern, following RFC 5646. Example 'en-US'.")]
[MaxStringLength("64")]
115: string DeviceLocale = "ai.device.locale";
[Description("Model of the device the end user of the application is using. Used for client scenarios. If this field is empty then it is derived from the user agent.")]
[MaxStringLength("256")]
120: string DeviceModel = "ai.device.model";
[Description("Client device OEM name taken from the browser.")]
[MaxStringLength("256")]
130: string DeviceOEMName = "ai.device.oemName";
[Description("Operating system name and version of the device the end user of the application is using. If this field is empty then it is derived from the user agent. Example 'Windows 10 Pro 10.0.10586.0'")]
[MaxStringLength("256")]
140: string DeviceOSVersion = "ai.device.osVersion";
[Description("The type of the device the end user of the application is using. Used primarily to distinguish JavaScript telemetry from server side telemetry. Examples: 'PC', 'Phone', 'Browser'. 'PC' is the default value.")]
[MaxStringLength("64")]
160: string DeviceType = "ai.device.type";
[Description("The IPv4 IP address of the client device. IPv6 is not currently supported. Information in the location context fields is always about the end user. When telemetry is sent from a service, the location context is about the user that initiated the operation in the service.")]
[MaxStringLength("45")]
200: string LocationIp = "ai.location.ip";
[Description("A unique identifier for the operation instance. The operation.id is created by either a request or a page view. All other telemetry sets this to the value for the containing request or page view. Operation.id is used for finding all the telemetry items for a specific operation instance.")]
[MaxStringLength("128")]
300: string OperationId = "ai.operation.id";
[Description("The name (group) of the operation. The operation.name is created by either a request or a page view. All other telemetry items set this to the value for the containing request or page view. Operation.name is used for finding all the telemetry items for a group of operations (i.e. 'GET Home/Index').")]
[MaxStringLength("1024")]
305: string OperationName = "ai.operation.name";
[Description("The unique identifier of the telemetry item's immediate parent.")]
[MaxStringLength("128")]
310: string OperationParentId = "ai.operation.parentId";
[Description("Name of synthetic source. Some telemetry from the application may represent a synthetic traffic. It may be web crawler indexing the web site, site availability tests or traces from diagnostic libraries like Application Insights SDK itself.")]
[MaxStringLength("1024")]
320: string OperationSyntheticSource = "ai.operation.syntheticSource";
[Description("The correlation vector is a light weight vector clock which can be used to identify and order related events across clients and services.")]
[MaxStringLength("64")]
330: string OperationCorrelationVector = "ai.operation.correlationVector";
[Description("Session ID - the instance of the user's interaction with the app. Information in the session context fields is always about the end user. When telemetry is sent from a service, the session context is about the user that initiated the operation in the service.")]
[MaxStringLength("64")]
400: string SessionId = "ai.session.id";
[Description("Boolean value indicating whether the session identified by ai.session.id is first for the user or not.")]
[MaxStringLength("5")]
[Question("Should it be marked as JSType-bool for breeze?")]
405: string SessionIsFirst = "ai.session.isFirst";
[Description("In multi-tenant applications this is the account ID or name which the user is acting with. Examples may be subscription ID for Azure portal or blog name blogging platform.")]
[MaxStringLength("1024")]
505: string UserAccountId = "ai.user.accountId";
[Description("The browser's user agent string as reported by the browser. This property will be used to extract informaiton regarding the customer's browser but will not be stored. Use custom properties to store the original user agent.")]
[MaxStringLength("2048")]
510: string UserAgent = "ai.user.userAgent";
[Description("Anonymous user id. Represents the end user of the application. When telemetry is sent from a service, the user context is about the user that initiated the operation in the service.")]
[MaxStringLength("128")]
515: string UserId = "ai.user.id";
[Description("Authenticated user id. The opposite of ai.user.id, this represents the user with a friendly name. Since it's PII information it is not collected by default by most SDKs.")]
[MaxStringLength("1024")]
525: string UserAuthUserId = "ai.user.authUserId";
[Description("Name of the role the application is a part of. Maps directly to the role name in azure.")]
[MaxStringLength("256")]
705: string CloudRole = "ai.cloud.role";
[Description("Name of the instance where the application is running. Computer name for on-premisis, instance name for Azure.")]
[MaxStringLength("256")]
715: string CloudRoleInstance = "ai.cloud.roleInstance";
[Description("SDK version. See https://github.com/Microsoft/ApplicationInsights-Home/blob/master/SDK-AUTHORING.md#sdk-version-specification for information.")]
[MaxStringLength("64")]
1000: string InternalSdkVersion = "ai.internal.sdkVersion";
[Description("Agent version. Used to indicate the version of StatusMonitor installed on the computer if it is used for data collection.")]
[MaxStringLength("64")]
1001: string InternalAgentVersion = "ai.internal.agentVersion";
}

Просмотреть файл

@ -0,0 +1,13 @@
import "Base.bond"
namespace AI
[Description("Data struct to contain both B and C sections.")]
struct Data<TDomain>
: Base
{
[Name("Item")]
[Description("Container for data item (B section).")]
20: required TDomain baseData;
}

Просмотреть файл

@ -0,0 +1,30 @@
import "DataPointType.bond"
namespace AI
[Description("Metric data single measurement.")]
struct DataPoint
{
[Description("Name of the metric.")]
[MaxStringLength("1024")]
10: required string name;
[Description("Metric type.")]
20: AI.DataPointType kind = Measurement;
[Description("Metric calculated value.")]
30: required double value;
[Description("Metric weight of the aggregated metric. Should not be set for a measurement.")]
40: nullable<int32> count;
[Description("Minimum value of the aggregated metric. Should not be set for a measurement.")]
50: nullable<double> min;
[Description("Maximum value of the aggregated metric. Should not be set for a measurement.")]
60: nullable<double> max;
[Description("Standard deviation of the aggregated metric. Should not be set for a measurement.")]
70: nullable<double> stdDev;
}

Просмотреть файл

@ -0,0 +1,8 @@
namespace AI
[Description("Type of the metric data measurement.")]
enum DataPointType
{
Measurement,
Aggregation,
}

Просмотреть файл

@ -0,0 +1,7 @@
namespace AI
[Description("The abstract common base of all domains.")]
struct Domain
{
}

Просмотреть файл

@ -0,0 +1,49 @@
import "Base.bond"
namespace AI
[Description("System variables for a telemetry item.")]
struct Envelope
{
[Description("Envelope version. For internal use only. By assigning this the default, it will not be serialized within the payload unless changed to a value other than #1.")]
[Name("SchemaVersion")]
10: int32 ver = 1;
[Description("Type name of telemetry data item.")]
[Name("DataTypeName")]
[MaxStringLength("1024")]
20: required string name;
[Description("Event date time when telemetry item was created. This is the wall clock time on the client when the event was generated. There is no guarantee that the client's time is accurate. This field must be formatted in UTC ISO 8601 format, with a trailing 'Z' character, as described publicly on https://en.wikipedia.org/wiki/ISO_8601#UTC. Note: the number of decimal seconds digits provided are variable (and unspecified). Consumers should handle this, i.e. managed code consumers should not use format 'O' for parsing as it specifies a fixed length. Example: 2009-06-15T13:45:30.0000000Z.")]
[Name("DateTime")]
[CSType("DateTimeOffset")]
[JSType("Date")]
[HockeyAppMinDateOffsetFromNow("2592000000")]
[MinDateOffsetFromNow("172800000")]
[MaxDateOffsetFromNow("7200000")]
30: required string time;
[Name("SamplingRate")]
[Description("Sampling rate used in application. This telemetry item represents 1 / sampleRate actual telemetry items.")]
40: double sampleRate = 100.0;
[Description("Sequence field used to track absolute order of uploaded events.")]
[Name("SequenceNumber")]
[MaxStringLength("64")]
50: string seq;
[Description("The application's instrumentation key.")]
[Name("InstrumentationKey")]
[MaxStringLength("40")]
60: string iKey;
[Name("Tags")]
[TypeAlias("ContextTagKeys")]
[Description("Key/value collection of context properties. See ContextTagKeys for information on available properties.")]
500: map<string, string> tags;
[Name("TelemetryData")]
[Description("Telemetry data item.")]
999: Base data;
}

Просмотреть файл

@ -0,0 +1,26 @@
import "Domain.bond"
namespace AI
[Description("Instances of Event represent structured event records that can be grouped and searched by their properties. Event data item also creates a metric of event count by name.")]
struct EventData
: Domain
{
[Description("Schema version")]
10: required int32 ver = 2;
[MaxStringLength("512")]
[Description("Event name. Keep it low cardinality to allow proper grouping and useful metrics.")]
[Question("Why Custom Event name is shorter than Request name or dependency name?")]
20: required string name;
[Description("Collection of custom properties.")]
[MaxKeyLength("150")]
[MaxValueLength("8192")]
100: map<string, string> properties;
[Description("Collection of custom measurements.")]
[MaxKeyLength("150")]
200: map<string, double> measurements;
}

Просмотреть файл

@ -0,0 +1,33 @@
import "Domain.bond"
import "ExceptionDetails.bond"
import "SeverityLevel.bond"
namespace AI
[Description("An instance of Exception represents a handled or unhandled exception that occurred during execution of the monitored application.")]
struct ExceptionData
: Domain
{
[Description("Schema version")]
10: required int32 ver = 2;
[Description("Exception chain - list of inner exceptions.")]
50: required vector<ExceptionDetails> exceptions;
[Description("Severity level. Mostly used to indicate exception severity level when it is reported by logging library.")]
60: nullable<AI.SeverityLevel> severityLevel;
[Description("Identifier of where the exception was thrown in code. Used for exceptions grouping. Typically a combination of exception type and a function from the call stack.")]
[MaxStringLength("1024")]
80: string problemId;
[Description("Collection of custom properties.")]
[MaxKeyLength("150")]
[MaxValueLength("8192")]
100: map<string, string> properties;
[Description("Collection of custom measurements.")]
[MaxKeyLength("150")]
200: map<string, double> measurements;
}

Просмотреть файл

@ -0,0 +1,32 @@
import "StackFrame.bond"
namespace AI
[Description("Exception details of the exception in a chain.")]
struct ExceptionDetails
{
[Description("In case exception is nested (outer exception contains inner one), the id and outerId properties are used to represent the nesting.")]
10: int32 id;
[Description("The value of outerId is a reference to an element in ExceptionDetails that represents the outer exception")]
20: int32 outerId;
[Description("Exception type name.")]
[MaxStringLength("1024")]
30: required string typeName;
[Description("Exception message.")]
[MaxStringLength("1024")]
40: required string message;
[Description("Indicates if full exception stack is provided in the exception. The stack may be trimmed, such as in the case of a StackOverflow exception.")]
50: bool hasFullStack = true;
[Description("Text describing the stack. Either stack or parsedStack should have a value.")]
[MaxStringLength("32768")]
60: string stack;
[Description("List of stack frames. Either stack or parsedStack should have a value.")]
70: vector<StackFrame> parsedStack;
}

Просмотреть файл

@ -0,0 +1,25 @@
import "Domain.bond"
import "SeverityLevel.bond"
namespace AI
[Description("Instances of Message represent printf-like trace statements that are text-searched. Log4Net, NLog and other text-based log file entries are translated into intances of this type. The message does not have measurements.")]
struct MessageData
: Domain
{
[Description("Schema version")]
10: required int32 ver = 2;
[MaxStringLength("32768")]
[Description("Trace message")]
20: required string message;
[Description("Trace severity level.")]
30: nullable<AI.SeverityLevel> severityLevel;
[Description("Collection of custom properties.")]
[MaxKeyLength("150")]
[MaxValueLength("8192")]
100: map<string, string> properties;
}

Просмотреть файл

@ -0,0 +1,21 @@
import "Domain.bond"
import "DataPoint.bond"
namespace AI
[Description("An instance of the Metric item is a list of measurements (single data points) and/or aggregations.")]
struct MetricData
: Domain
{
[Description("Schema version")]
10: required int32 ver = 2;
[Description("List of metrics.")]
20: required vector<DataPoint> metrics;
[Description("Collection of custom properties.")]
[MaxKeyLength("150")]
[MaxValueLength("8192")]
100: map<string, string> properties;
}

Просмотреть файл

@ -0,0 +1,18 @@
import "EventData.bond"
namespace AI
[Description("An instance of PageView represents a generic action on a page like a button click. It is also the base type for PageView.")]
[Alias("PageviewData;PageEventData")]
struct PageViewData
: EventData
{
[MaxStringLength("2048")]
[Description("Request URL with all query string parameters")]
10: string url;
[CSType("TimeSpan")]
[Description("Request duration in TimeSpan 'G' (general long) format: d:hh:mm:ss.fffffff. For a page view (PageViewData), this is the duration. For a page view with performance information (PageViewPerfData), this is the page load time.")]
20: string duration;
}

Просмотреть файл

@ -0,0 +1,30 @@
import "PageViewData.bond"
namespace AI
[Description("An instance of PageViewPerf represents: a page view with no performance data, a page view with performance data, or just the performance data of an earlier page request.")]
[Alias("PageViewPerformanceData;PageviewPerformanceData")]
struct PageViewPerfData
: PageViewData
{
[Description("Performance total in TimeSpan 'G' (general long) format: d:hh:mm:ss.fffffff")]
[CSType("TimeSpan")]
10: string perfTotal;
[Description("Network connection time in TimeSpan 'G' (general long) format: d:hh:mm:ss.fffffff")]
[CSType("TimeSpan")]
20: string networkConnect;
[Description("Sent request time in TimeSpan 'G' (general long) format: d:hh:mm:ss.fffffff")]
[CSType("TimeSpan")]
30: string sentRequest;
[Description("Received response time in TimeSpan 'G' (general long) format: d:hh:mm:ss.fffffff")]
[CSType("TimeSpan")]
40: string receivedResponse;
[Description("DOM processing time in TimeSpan 'G' (general long) format: d:hh:mm:ss.fffffff")]
[CSType("TimeSpan")]
50: string domProcessing;
}

Просмотреть файл

@ -0,0 +1,53 @@
import "Domain.bond"
namespace AI
[Description("An instance of Remote Dependency represents an interaction of the monitored component with a remote component/service like SQL or an HTTP endpoint.")]
struct RemoteDependencyData
: Domain
{
[Description("Schema version")]
10: required int32 ver = 2;
[MaxStringLength("1024")]
[Description("Name of the command initiated with this dependency call. Low cardinality value. Examples are stored procedure name and URL path template.")]
20: required string name;
[MaxStringLength("128")]
[Description("Identifier of a dependency call instance. Used for correlation with the request telemetry item corresponding to this dependency call.")]
30: string id;
[MaxStringLength("1024")]
[Description("Result code of a dependency call. Examples are SQL error code and HTTP status code.")]
40: string resultCode;
[CSType("TimeSpan")]
[Description("Request duration in TimeSpan 'G' (general long) format: d:hh:mm:ss.fffffff.")]
[ActAsRequired("Renaming value to duration.")]
61: required string duration;
[Description("Indication of successfull or unsuccessfull call.")]
120: bool success = true;
[MaxStringLength("8192")]
[Description("Command initiated by this dependency call. Examples are SQL statement and HTTP URL's with all query parameters.")]
151: string data;
[MaxStringLength("1024")]
[Description("Dependency type name. Very low cardinality value for logical grouping of dependencies and interpretation of other fields like commandName and resultCode. Examples are SQL, Azure table, and HTTP.")]
162: string type;
[MaxStringLength("1024")]
[Description("Target site of a dependency call. Examples are server name, host address.")]
161: string target;
[Description("Collection of custom properties.")]
[MaxKeyLength("150")]
[MaxValueLength("8192")]
200: map<string, string> properties;
[Description("Collection of custom measurements.")]
[MaxKeyLength("150")]
300: map<string, double> measurements;
}

Просмотреть файл

@ -0,0 +1,44 @@
import "Domain.bond"
namespace AI
[Description("An instance of Request represents completion of an external request to the application to do work and contains a summary of that request execution and the results.")]
struct RequestData
: Domain
{
[Description("Schema version")]
10: required int32 ver = 2;
[MaxStringLength("128")]
[Description("Identifier of a request call instance. Used for correlation between request and other telemetry items.")]
20: required string id;
[CSType("TimeSpan")]
[Description("Request duration in TimeSpan 'G' (general long) format: d:hh:mm:ss.fffffff.")]
50: required string duration;
[MaxStringLength("1024")]
[Description("Result of a request execution. HTTP status code for HTTP requests.")]
60: required string responseCode;
[Description("Indication of successfull or unsuccessfull call.")]
70: required bool success;
[MaxStringLength("1024")]
[Description("Name of the request. Represents code path taken to process request. Low cardinality value to allow better grouping of requests. For HTTP requests it represents the HTTP method and URL path template like 'GET /values/{id}'.")]
30: string name;
[MaxStringLength("2048")]
[Description("Request URL with all query string parameters.")]
90: string url;
[Description("Collection of custom properties.")]
[MaxKeyLength("150")]
[MaxValueLength("8192")]
100: map<string, string> properties;
[Description("Collection of custom measurements.")]
[MaxKeyLength("150")]
200: map<string, double> measurements;
}

Просмотреть файл

@ -0,0 +1,11 @@
namespace AI
[Description("Defines the level of severity for the event.")]
enum SeverityLevel
{
Verbose,
Information,
Warning,
Error,
Critical,
}

Просмотреть файл

@ -0,0 +1,25 @@
namespace AI
[Description("Stack frame information.")]
struct StackFrame
{
[Description("Level in the call stack. For the long stacks SDK may not report every function in a call stack.")]
10: required int32 level;
[Description("Method name.")]
[MaxStringLength("1024")]
20: required string method;
[Description("Name of the assembly (dll, jar, etc.) containing this function.")]
[MaxStringLength("1024")]
30: string assembly;
[Description("File name or URL of the method implementation.")]
[MaxStringLength("1024")]
50: string fileName;
[Description("Line number of the code implementation.")]
60: int32 line;
}

126
Schema/generateSchema.ps1 Normal file
Просмотреть файл

@ -0,0 +1,126 @@
$generatorPath = "C:\src\mseng\AppInsights-Common"
$schemasPath = "C:\src\mseng\DataCollectionSchemas"
$publicSchemaLocation = "https://raw.githubusercontent.com/Microsoft/ApplicationInsights-Home/master/EndpointSpecs/Schemas/Bond"
$localPublicSchema = $false
$currentDir = $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
#fix path
$generatorPath = "$generatorPath\..\bin\Debug\BondSchemaGenerator\BondSchemaGenerator"
$schemasPath = "$schemasPath\v2\Bond\"
function RegExReplace([string]$fileName, [string]$regex, [string]$replacement="")
{
$content = Get-Content $fileName
$content = $content -creplace $regex,$replacement
$content | Set-Content $fileName
}
#####################################################################
## PUBLIC SCHEMA
#####################################################################
mkdir -Force $currentDir\PublicSchema
del "$currentDir\PublicSchema\*.bond"
if ($localPublicSchema) {
# Generate public schema using bond generator
& "$generatorPath\BondSchemaGenerator.exe" -v -i "$schemasPath\AppInsightsTypes.bond" -i "$schemasPath\PerformanceCounterData.bond" -i "$schemasPath\SessionStateData.bond" -i "$schemasPath\ContextTagKeys.bond" -o "$currentDir\PublicSchema\" -e BondLanguage -t BondLayout -n test --flatten false
} else {
# Download public schema from the github
@(
"AvailabilityData.bond",
"Base.bond",
"ContextTagKeys.bond",
"Data.bond",
"DataPoint.bond",
"DataPointType.bond",
"Domain.bond",
"Envelope.bond",
"EventData.bond",
"ExceptionData.bond",
"ExceptionDetails.bond",
"MessageData.bond",
"MetricData.bond",
"PageViewData.bond",
"PageViewPerfData.bond",
"RemoteDependencyData.bond",
"RequestData.bond",
"SeverityLevel.bond",
"StackFrame.bond"
) | ForEach-Object {
$fileName = $_
& Invoke-WebRequest -o "$currentDir\PublicSchema\$fileName" "$publicSchemaLocation/$fileName"
RegExReplace "$currentDir\PublicSchema\$fileName" "`n" "`r`n"
}
}
#####################################################################
## BOND-GENERATED CODE
#####################################################################
mkdir -Force $currentDir\obj
Invoke-WebRequest -o "$currentDir\obj\nuget.exe" https://api.nuget.org/downloads/nuget.exe
del $currentDir\obj\gbc\*
& "$currentDir\obj\nuget" install Bond.CSharp -Version 4.2.1 -OutputDirectory "$currentDir\obj\packages"
dir "$currentDir\PublicSchema" | ForEach-Object {
& "$currentDir\obj\packages\Bond.CSharp.4.2.1\tools\gbc.exe" c# --collection-interfaces --using="DateTimeOffset=System.DateTimeOffset" --using="TimeSpan=System.TimeSpan" --using="Guid=System.Guid" -o "$currentDir\obj\gbc" $_.FullName
}
del "$currentDir\obj\gbc\*_interfaces.cs"
del "$currentDir\obj\gbc\*_services.cs"
del "$currentDir\obj\gbc\*_proxies.cs"
#####################################################################
## CLEAR BOND-GENERATED CODE OUT OF BOND REFERENCES
#####################################################################
dir "$currentDir\obj\gbc" | ForEach-Object {
# Rename namespace from AI to Microsoft.ApplicationInsights.Extensibility.Implementation.External
RegExReplace $_.FullName "(namespace AI)" "namespace Microsoft.ApplicationInsights.Extensibility.Implementation.External"
RegExReplace $_.FullName "new Dictionary" "new ConcurrentDictionary"
# Remove "using Bond" statements
RegExReplace $_.FullName "using Bond.*"
RegExReplace $_.FullName "using System.Collections.Generic;" "using System.Collections.Concurrent;`r`n using System.Collections.Generic;"
# Remove all Bond attributes
RegExReplace $_.FullName "\[global::Bond\..*\]"
# Remove derivations from Microsoft.Telemetry.Domain
RegExReplace $_.FullName ":\s*global::Microsoft\.Telemetry\.Domain"
# Replace IBonded field definition with plain type field definition
RegExReplace $_.FullName "global::Bond\.IBonded<([A-Za-z0-9_]+)>" '$1'
# Remove the baseData field initializer
RegExReplace $_.FullName "baseData\s*=.*;"
# Remove the data field initializer
RegExReplace $_.FullName "data\s*=.*;"
# Make all public classes internal
RegExReplace $_.FullName "(public partial class)" "internal partial class"
# Make all public enums internal
RegExReplace $_.FullName "(public enum)" "internal enum"
# Change "= nothing" to "= null"
RegExReplace $_.FullName "= nothing;" "= null;"
}
#####################################################################
## COPY GENERATED FILES TO THE REPOSITORY
#####################################################################
del "$currentDir\..\src\Core\Managed\Shared\Extensibility\Implementation\External\*_types.cs"
dir "$currentDir\obj\gbc\*_types.cs" | ForEach-Object {
$fileName = $_
copy $fileName "$currentDir\..\src\Core\Managed\Shared\Extensibility\Implementation\External\"
}

Просмотреть файл

@ -7,9 +7,9 @@ namespace Microsoft.Extensions.DependencyInjection
using Microsoft.ApplicationInsights.AspNetCore.Extensions;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
#if NET451 || NET46
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse;
using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel;
#if NET451 || NET46
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse;
#endif
using Microsoft.Extensions.Options;
@ -99,9 +99,9 @@ namespace Microsoft.Extensions.DependencyInjection
private void AddTelemetryChannelAndProcessors(TelemetryConfiguration configuration)
{
#if NET451 || NET46
configuration.TelemetryChannel = this.telemetryChannel ?? new ServerTelemetryChannel();
#if NET451 || NET46
if (configuration.TelemetryChannel is ServerTelemetryChannel)
{
// Enabling Quick Pulse Metric Stream
@ -120,6 +120,7 @@ namespace Microsoft.Extensions.DependencyInjection
}
}
#endif
if (this.applicationInsightsServiceOptions.EnableAdaptiveSampling)
{
configuration.TelemetryProcessorChainBuilder.UseAdaptiveSampling();

Просмотреть файл

@ -65,14 +65,14 @@
<PackageReference Include="System.Threading.Tasks.Analyzers" Version="1.2.0-beta2">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.5.0-beta1-build13120" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.0-beta1-build01033" />
<PackageReference Include="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel" Version="2.5.0-beta1-build13120" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.5.0-beta1-build19420" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.5.0-beta1-build07359" />
<PackageReference Include="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel" Version="2.5.0-beta1-build19420" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' OR '$(TargetFramework)' == 'net46' ">
<PackageReference Include="System.Net.Http" Version="4.3.1" />
<PackageReference Include="Microsoft.ApplicationInsights.PerfCounterCollector" Version="2.5.0-beta1-build01033" />
<PackageReference Include="Microsoft.ApplicationInsights.PerfCounterCollector" Version="2.5.0-beta1-build07359" />
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>

Просмотреть файл

@ -0,0 +1,92 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<VersionPrefix>1.0.2</VersionPrefix>
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks>
<DelaySign>true</DelaySign>
<PreserveCompilationContext>true</PreserveCompilationContext>
<AssemblyName>ApplicationInsightsTypes</AssemblyName>
<AssemblyOriginatorKeyFile>../../keys/35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageId>ApplicationInsightsTypes</PackageId>
<NetStandardImplicitPackageVersion>2.0.0</NetStandardImplicitPackageVersion>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\test\$(MSBuildProjectName)</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Bond.Core.CSharp" Version="6.0.0" />
<PackageReference Include="Bond.CSharp" Version="6.0.0" />
<PackageReference Include="NETStandard.Library" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<BondCodegen Include="..\..\Schema\PublicSchema\AvailabilityData.bond">
<Link>StackFrame.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\Base.bond">
<Link>Base.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\ContextTagKeys.bond">
<Link>ContextTagKeys.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\Data.bond">
<Link>Data.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\DataPoint.bond">
<Link>DataPoint.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\DataPointType.bond">
<Link>DataPointType.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\Domain.bond">
<Link>Domain.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\Envelope.bond">
<Link>Envelope.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\EventData.bond">
<Link>EventData.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\ExceptionData.bond">
<Link>ExceptionData.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\ExceptionDetails.bond">
<Link>ExceptionDetails.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\MessageData.bond">
<Link>MessageData.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\MetricData.bond">
<Link>MetricData.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\PageViewData.bond">
<Link>PageViewData.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\PageViewPerfData.bond">
<Link>PageViewPerfData.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\RemoteDependencyData.bond">
<Link>RemoteDependencyData.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\RequestData.bond">
<Link>RequestData.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\SeverityLevel.bond">
<Link>SeverityLevel.bond</Link>
</BondCodegen>
<BondCodegen Include="..\..\Schema\PublicSchema\StackFrame.bond">
<Link>StackFrame.bond</Link>
</BondCodegen>
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,21 @@
namespace AI
{
public class ItemType
{
public const string Metric = "Microsoft.ApplicationInsights.Metric";
public const string Request = "Microsoft.ApplicationInsights.Request";
public const string Exception = "Microsoft.ApplicationInsights.Exception";
public const string Message = "Microsoft.ApplicationInsights.Message";
public const string Event = "Microsoft.ApplicationInsights.Event";
public const string PageView = "Microsoft.ApplicationInsights.PageView";
public const string PageViewPerformance = "Microsoft.ApplicationInsights.PageViewPerformance";
public const string RemoteDependency = "Microsoft.ApplicationInsights.RemoteDependency";
}
}

Просмотреть файл

@ -0,0 +1,14 @@
namespace AI
{
/// <summary>
/// Provides access to a complete telemetry item.
/// </summary>
/// <typeparam name="T">The part B telemetry item type.</typeparam>
public class TelemetryItem<T> : Envelope
{
/// <summary>
/// Gets the telemetry data.
/// </summary>
public new Data<T> data { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,15 @@
namespace AI
{
public enum TelemetryItemType
{
Event,
Exception,
Message,
Metric,
PageView,
PageViewPerformance,
RemoteDependency,
Request,
Availability
}
}

Просмотреть файл

@ -2,7 +2,7 @@
<PropertyGroup>
<VersionPrefix>2.0.0</VersionPrefix>
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
<RuntimeIdentifier Condition=" '$(TargetFramework)' == 'net461' ">win7-x86</RuntimeIdentifier>
<DelaySign>true</DelaySign>
<PreserveCompilationContext>true</PreserveCompilationContext>
@ -10,7 +10,7 @@
<AssemblyOriginatorKeyFile>../../keys/35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageId>EmptyApp.FunctionalTests</PackageId>
<PackageId>EmptyApp20.FunctionalTests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">2.0.0</RuntimeFrameworkVersion>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\test\$(MSBuildProjectName)</OutputPath>
@ -24,10 +24,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.0.0" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
@ -46,5 +46,4 @@
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
</Project>

Просмотреть файл

@ -2,10 +2,11 @@
{
using System.Linq;
using System.Net.Http;
using AI;
using FunctionalTestUtils;
using Microsoft.ApplicationInsights.DataContracts;
using Xunit;
using Xunit.Abstractions;
using Xunit.Abstractions;
public class RequestTelemetryEmptyAppTests : TelemetryTestsBase
{
@ -60,18 +61,25 @@
var task = httpClient.GetAsync(server.BaseHost + "/Mixed");
task.Wait(TestTimeoutMs);
}
var telemetries = server.Execute<Envelope>(() => server.Listener.ReceiveItems(5, TestListenerTimeoutInMs));
Assert.True(telemetries.Length >= 5);
Assert.Contains(telemetries.OfType<TelemetryItem<RemoteDependencyData>>(),
t => ((TelemetryItem<RemoteDependencyData>)t).data.baseData.name == "GET /Mixed");
Assert.Contains(telemetries.OfType<TelemetryItem<RequestData>>(),
t => ((TelemetryItem<RequestData>)t).data.baseData.name == "GET /Mixed");
Assert.Contains(telemetries.OfType<TelemetryItem<EventData>>(),
t => ((TelemetryItem<EventData>)t).data.baseData.name == "GetContact");
Assert.Contains(telemetries.OfType<TelemetryItem<MetricData>>(),
t => ((TelemetryItem<MetricData>)t).data.baseData.metrics[0].name == "ContactFile" && ((TelemetryItem<MetricData>)t).data.baseData.metrics[0].value == 1);
Assert.Contains(telemetries.OfType<TelemetryItem<MessageData>>(),
t => ((TelemetryItem<MessageData>)t).data.baseData.message == "Fetched contact details." && ((TelemetryItem<MessageData>)t).data.baseData.severityLevel == AI.SeverityLevel.Information);
}
var telemetries = server.BackChannel.Buffer;
Assert.Contains(telemetries.OfType<DependencyTelemetry>(), t => t.Name == "GET /Mixed");
Assert.True(telemetries.Count >= 4);
Assert.Contains(telemetries.OfType<RequestTelemetry>(), t => t.Name == "GET /Mixed");
Assert.Contains(telemetries.OfType<EventTelemetry>(), t => t.Name == "GetContact");
Assert.Contains(telemetries.OfType<MetricTelemetry>(),
t => t.Name == "ContactFile" && t.Value == 1);
Assert.Contains(telemetries.OfType<TraceTelemetry>(),
t => t.Message == "Fetched contact details." && t.SeverityLevel == SeverityLevel.Information);
}
}
}

Просмотреть файл

@ -1,6 +1,7 @@
namespace EmptyApp20.FunctionalTests.FunctionalTest
{
using FunctionalTestUtils;
using Microsoft.ApplicationInsights.DataContracts;
using Xunit;
using Xunit.Abstractions;
@ -16,7 +17,18 @@
[Fact]
public void TestBasicDependencyPropertiesAfterRequestingBasicPage()
{
this.ValidateBasicDependency(assemblyName, "/");
const string RequestPath = "/";
using (var server = new InProcessServer(assemblyName))
{
DependencyTelemetry expected = new DependencyTelemetry();
expected.ResultCode = "200";
expected.Success = true;
expected.Name = "GET /";
expected.Data = server.BaseHost + RequestPath;
this.ValidateBasicDependency(server, RequestPath, expected);
}
}
[Fact]

Просмотреть файл

@ -7,19 +7,17 @@
using Microsoft.ApplicationInsights.AspNetCore.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.ApplicationInsights.Channel;
using FunctionalTestUtils;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel;
public class Startup
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITelemetryChannel>(new BackTelemetryChannel());
var builder = new ConfigurationBuilder();
builder.AddApplicationInsightsSettings(instrumentationKey: "Foo");
builder.AddApplicationInsightsSettings(instrumentationKey: "Foo", endpointAddress: "http://localhost:4001/v2/track/", developerMode: true);
services.AddApplicationInsightsTelemetry(builder.Build());
}

Просмотреть файл

@ -16,12 +16,14 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.ApplicationInsights.AspNetCore\Microsoft.ApplicationInsights.AspNetCore.csproj" />
<ProjectReference Include="..\ApplicationInsightsTypes\ApplicationInsightsTypes.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.0.0" />
<PackageReference Include="NETStandard.Library" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.0.0" />
<PackageReference Include="NETStandard.Library" Version="2.0.0" />
<PackageReference Include="System.Reactive.Linq" Version="3.1.1" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
</ItemGroup>

Просмотреть файл

@ -0,0 +1,87 @@
namespace FunctionalTestUtils
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Threading.Tasks;
public abstract class HttpListenerObservableBase<T> : IObservable<T>, IDisposable
{
private readonly HttpListener listener;
private IObservable<T> stream;
public HttpListenerObservableBase(string url)
{
this.listener = new HttpListener();
this.listener.Prefixes.Add(url);
}
public void Start()
{
OnStart();
if (this.stream != null)
{
this.Stop();
}
if (!this.listener.IsListening)
{
this.listener.Start();
}
this.stream = this.CreateStream();
}
protected virtual void OnStart()
{ }
public void Stop()
{
this.Dispose();
}
public IDisposable Subscribe(IObserver<T> observer)
{
if (this.stream == null)
{
throw new InvalidOperationException("Call HttpListenerObservable.Start before subscribing to the stream");
}
return this.stream
.Subscribe(observer);
}
public void Dispose()
{
if (listener != null && listener.IsListening)
{
listener.Stop();
listener.Close();
this.stream = null;
}
}
private IObservable<T> CreateStream()
{
return Observable
.Create<T>
(obs =>
Task.Factory.FromAsync(
(a, c) => this.listener.BeginGetContext(a, c),
ar => this.listener.EndGetContext(ar),
null)
.ToObservable()
.SelectMany(this.CreateNewItemsFromContext)
.Subscribe(obs)
)
.Repeat()
.Publish()
.RefCount();
}
protected abstract IEnumerable<T> CreateNewItemsFromContext(HttpListenerContext context);
}
}

Просмотреть файл

@ -2,14 +2,16 @@
{
using System;
using System.IO;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using AI;
// a variant of aspnet/Hosting/test/Microsoft.AspNetCore.Hosting.Tests/HostingEngineTests.cs
public class InProcessServer : IDisposable
{
private const string httpListenerConnectionString = "http://localhost:4001/v2/track/";
private static Random random = new Random();
private static object noParallelism = new object();
public static Func<IWebHostBuilder, IWebHostBuilder> UseApplicationInsights =
builder => builder.UseApplicationInsights();
@ -18,22 +20,25 @@
private IWebHost hostingEngine;
private string url;
private readonly BackTelemetryChannel backChannel;
public BackTelemetryChannel BackChannel
{
get
{
return this.backChannel;
}
}
private TelemetryHttpListenerObservable listener;
public InProcessServer(string assemblyName, Func<IWebHostBuilder, IWebHostBuilder> configureHost = null)
{
this.configureHost = configureHost;
var machineName = Environment.GetEnvironmentVariable("COMPUTERNAME");
this.url = "http://" + machineName + ":" + random.Next(5000, 14000).ToString();
this.backChannel = this.Start(assemblyName);
this.url = "http://" + machineName + ":" + random.Next(5000, 14000).ToString();
this.Start(assemblyName);
}
public TelemetryHttpListenerObservable Listener
{
get
{
return this.listener;
}
}
public string BaseHost
@ -44,9 +49,35 @@
}
}
public T[] Execute<T>(Func<T[]> receiveItemsMethod)
{
lock (noParallelism)
{
try
{
this.listener = new TelemetryHttpListenerObservable(httpListenerConnectionString);
this.listener.Start();
if (receiveItemsMethod != null)
{
return receiveItemsMethod();
}
}
finally
{
if (this.listener != null)
{
this.listener.Stop();
}
}
}
return null;
}
public IServiceProvider ApplicationServices { get; private set; }
private BackTelemetryChannel Start(string assemblyName)
private void Start(string assemblyName)
{
var builder = new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
@ -64,7 +95,6 @@
this.hostingEngine.Start();
this.ApplicationServices = this.hostingEngine.Services;
return (BackTelemetryChannel)this.hostingEngine.Services.GetService<ITelemetryChannel>();
}
public void Dispose()

Просмотреть файл

@ -0,0 +1,94 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TelemetryExtensions.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace FunctionalTestUtils
{
using System;
using System.IO;
using System.Linq;
using System.Reactive.Linq;
using AI;
public static class TelemetryExtensions
{
public static Envelope[] ReceiveItems(
this TelemetryHttpListenerObservable listener,
int timeOut)
{
if (null == listener)
{
throw new ArgumentNullException("listener");
}
var result = listener
.TakeUntil(DateTimeOffset.UtcNow.AddMilliseconds(timeOut))
.ToEnumerable()
.ToArray();
return result;
}
public static Envelope[] ReceiveItems(
this TelemetryHttpListenerObservable listener,
int count,
int timeOut)
{
if (null == listener)
{
throw new ArgumentNullException("listener");
}
var result = listener
.TakeUntil(DateTimeOffset.UtcNow.AddMilliseconds(timeOut))
.Take(count)
.ToEnumerable()
.ToArray();
if (result.Length != count)
{
throw new InvalidDataException("Incorrect number of items. Expected: " + count + " Received: " + result.Length);
}
return result;
}
public static T[] ReceiveItemsOfType<T>(
this TelemetryHttpListenerObservable listener,
int timeOut)
{
var result = listener
.Where(item => (item is TelemetryItem<T>))
.Select(item => ((TelemetryItem<T>)item).data.baseData)
.TakeUntil(DateTimeOffset.UtcNow.AddMilliseconds(timeOut))
.ToEnumerable()
.ToArray();
return result;
}
public static T[] ReceiveItemsOfType<T>(
this TelemetryHttpListenerObservable listener,
int count,
int timeOut)
{
var result = listener
.Where(item => (item is TelemetryItem<T>))
.Select(item => ((TelemetryItem<T>)item).data.baseData)
.TakeUntil(DateTimeOffset.UtcNow.AddMilliseconds(timeOut))
.Take(count)
.ToEnumerable()
.ToArray();
if (result.Length != count)
{
throw new InvalidDataException("Incorrect number of items. Expected: " + count + " Received: " + result.Length);
}
return result;
}
}
}

Просмотреть файл

@ -0,0 +1,63 @@
namespace FunctionalTestUtils
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using AI;
public class TelemetryHttpListenerObservable : HttpListenerObservableBase<Envelope>
{
public bool FailureDetected { get; set; }
public TelemetryHttpListenerObservable(string url) : base(url)
{
}
protected override IEnumerable<Envelope> CreateNewItemsFromContext(HttpListenerContext context)
{
try
{
var request = context.Request;
string content = string.Empty;
if (!string.IsNullOrWhiteSpace(request.Headers["Content-Encoding"]) &&
string.Equals("gzip", request.Headers["Content-Encoding"],
StringComparison.InvariantCultureIgnoreCase))
{
content = Decompress(request);
}
Trace.WriteLine("=>");
Trace.WriteLine("Item received: " + content);
Trace.WriteLine("<=");
return TelemetryItemFactory.GetTelemetryItems(content);
}
finally
{
context.Response.Close();
}
}
/// <summary>
/// Decompresses content in gzip and returns decompressed string
/// </summary>
/// <param name="content"></param>
/// <returns></returns>
private static string Decompress(HttpListenerRequest request)
{
var gzipStream = new GZipStream(request.InputStream, CompressionMode.Decompress);
using (var streamReader = new StreamReader(gzipStream, request.ContentEncoding))
{
return streamReader.ReadToEnd();
}
}
}
}

Просмотреть файл

@ -0,0 +1,99 @@
namespace FunctionalTestUtils
{
using System;
using System.Collections.Generic;
using System.IO;
using AI;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
internal static class TelemetryItemFactory
{
public static IList<Envelope> GetTelemetryItems(string content)
{
var items = new List<Envelope>();
if (string.IsNullOrWhiteSpace(content))
{
return items;
}
var newLines = new [] { "\r\n", "\n" };
string[] lines = content.Split(newLines, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
JsonReader reader = new JsonTextReader(new StringReader(line));
reader.DateParseHandling = DateParseHandling.None;
JObject obj = JObject.Load(reader);
var envelope = obj.ToObject<Envelope>();
var item = CreateTelemetryItem(envelope, line);
items.Add(item);
}
return items;
}
private static Envelope CreateTelemetryItem(
Envelope envelope,
string content)
{
Envelope result;
TelemetryItemType type;
if (Enum.TryParse<TelemetryItemType>(envelope.data.baseType.Replace("Data", ""), out type))
{
switch (type)
{
case TelemetryItemType.Exception:
{
result = JsonConvert.DeserializeObject<TelemetryItem<ExceptionData>>(content);
break;
}
case TelemetryItemType.Request:
{
result = JsonConvert.DeserializeObject<TelemetryItem<RequestData>>(content);
break;
}
case TelemetryItemType.Metric:
{
result = JsonConvert.DeserializeObject<TelemetryItem<MetricData>>(content);
break;
}
case TelemetryItemType.RemoteDependency:
{
result = JsonConvert.DeserializeObject<TelemetryItem<RemoteDependencyData>>(content);
break;
}
case TelemetryItemType.Message:
{
result = JsonConvert.DeserializeObject<TelemetryItem<MessageData>>(content);
break;
}
case TelemetryItemType.Event:
{
result = JsonConvert.DeserializeObject<TelemetryItem<EventData>>(content);
break;
}
default:
{
throw new InvalidDataException("Unsupported telemetry type");
}
}
}
else
{
throw new InvalidDataException("Unsupported telemetry type");
}
return result;
}
}
}

Просмотреть файл

@ -2,13 +2,13 @@
{
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using AI;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.AspNetCore.Hosting;
using Microsoft.ApplicationInsights.Channel;
@ -16,18 +16,16 @@
using Xunit;
using Xunit.Abstractions;
#if NET451 || NET461
using System.Net;
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector;
using Microsoft.ApplicationInsights.Extensibility;
#endif
public abstract class TelemetryTestsBase
{
public const int TestListenerTimeoutInMs = 5000;
protected const int TestTimeoutMs = 10000;
private object noParallelism = new object();
protected readonly ITestOutputHelper output;
public TelemetryTestsBase(ITestOutputHelper output)
{
this.output = output;
@ -36,41 +34,31 @@
[MethodImpl(MethodImplOptions.NoOptimization)]
public void ValidateBasicRequest(InProcessServer server, string requestPath, RequestTelemetry expected)
{
lock (noParallelism)
// Subtract 50 milliseconds to hack around strange behavior on build server where the RequestTelemetry.Timestamp is somehow sometimes earlier than now by a few milliseconds.
expected.Timestamp = DateTimeOffset.Now.Subtract(TimeSpan.FromMilliseconds(50));
Stopwatch timer = Stopwatch.StartNew();
var httpClientHandler = new HttpClientHandler();
httpClientHandler.UseDefaultCredentials = true;
Task<HttpResponseMessage> task;
using (HttpClient httpClient = new HttpClient(httpClientHandler, true))
{
// Subtract 50 milliseconds to hack around strange behavior on build server where the RequestTelemetry.Timestamp is somehow sometimes earlier than now by a few milliseconds.
expected.Timestamp = DateTimeOffset.Now.Subtract(TimeSpan.FromMilliseconds(50));
server.BackChannel.Buffer.Clear();
Stopwatch timer = Stopwatch.StartNew();
var httpClientHandler = new HttpClientHandler();
httpClientHandler.UseDefaultCredentials = true;
Task<HttpResponseMessage> task;
using (HttpClient httpClient = new HttpClient(httpClientHandler, true))
{
task = httpClient.GetAsync(server.BaseHost + requestPath);
task.Wait(TestTimeoutMs);
}
timer.Stop();
server.Dispose();
PrintBufferInfo(server.BackChannel.Buffer);
RequestTelemetry actual = server.BackChannel.Buffer.OfType<RequestTelemetry>().Where(t => t.Name == expected.Name).Single();
server.BackChannel.Buffer.Clear();
Assert.Equal(expected.ResponseCode, actual.ResponseCode);
Assert.Equal(expected.Name, actual.Name);
Assert.Equal(expected.Success, actual.Success);
Assert.Equal(expected.Url, actual.Url);
InRange(actual.Timestamp, expected.Timestamp, DateTimeOffset.Now);
output.WriteLine("actual.Timestamp: " + actual.Timestamp);
output.WriteLine("actual.Duration: " + actual.Duration);
output.WriteLine("timer.Elapsed: " + timer.Elapsed);
Assert.True(actual.Duration < timer.Elapsed.Add(TimeSpan.FromMilliseconds(20)), "duration");
task = httpClient.GetAsync(server.BaseHost + requestPath);
task.Wait(TestTimeoutMs);
}
timer.Stop();
var actual = server.Execute<RequestData>(() => server.Listener.ReceiveItemsOfType<RequestData>(1, TestListenerTimeoutInMs))[0];
Assert.Equal(expected.ResponseCode, actual.responseCode);
Assert.Equal(expected.Name, actual.name);
Assert.Equal(expected.Success, actual.success);
Assert.Equal(expected.Url, new Uri(actual.url));
output.WriteLine("actual.Duration: " + actual.duration);
output.WriteLine("timer.Elapsed: " + timer.Elapsed);
Assert.True(TimeSpan.Parse(actual.duration) < timer.Elapsed.Add(TimeSpan.FromMilliseconds(20)), "duration");
}
public void ValidateBasicException(InProcessServer server, string requestPath, ExceptionTelemetry expected)
@ -85,53 +73,41 @@
task.Wait(TestTimeoutMs);
}
var result = task.Result;
server.Dispose();
PrintBufferInfo(server.BackChannel.Buffer);
var actual = server.BackChannel.Buffer.OfType<ExceptionTelemetry>().Single();
Assert.Equal(expected.Exception.GetType(), actual.Exception.GetType());
Assert.NotEmpty(actual.Exception.StackTrace);
Assert.NotEmpty(actual.Context.Operation.Name);
Assert.NotEmpty(actual.Context.Operation.Id);
var actual = server.Execute<ExceptionData>(() => server.Listener.ReceiveItemsOfType<ExceptionData>(1, TestListenerTimeoutInMs))[0];
Assert.Equal(expected.Exception.GetType().ToString(), actual.exceptions[0].typeName);
Assert.NotEmpty(actual.exceptions[0].parsedStack);
}
public void ValidateBasicDependency(string assemblyName, string requestPath, Func<IWebHostBuilder, IWebHostBuilder> configureHost = null)
public void ValidateBasicDependency(InProcessServer server, string requestPath, DependencyTelemetry expected)
{
DependencyTelemetry expected = new DependencyTelemetry();
expected.ResultCode = "200";
expected.Success = true;
expected.Name = "GET " + requestPath;
var httpClientHandler = new HttpClientHandler();
httpClientHandler.UseDefaultCredentials = true;
InProcessServer server;
using (server = new InProcessServer(assemblyName, configureHost))
Task<HttpResponseMessage> task;
using (var httpClient = new HttpClient(httpClientHandler, true))
{
expected.Data = server.BaseHost + requestPath;
var timer = Stopwatch.StartNew();
Task<HttpResponseMessage> task;
using (var httpClient = new HttpClient())
{
task = httpClient.GetAsync(server.BaseHost + requestPath);
task.Wait(TestTimeoutMs);
}
var result = task.Result;
timer.Stop();
task = httpClient.GetAsync(server.BaseHost + requestPath);
task.Wait(TestTimeoutMs);
}
var result = task.Result;
PrintBufferInfo(server.BackChannel.Buffer);
IEnumerable<DependencyTelemetry> dependencies = server.BackChannel.Buffer.OfType<DependencyTelemetry>();
Assert.NotNull(dependencies);
Assert.NotEmpty(dependencies);
var actual = server.Execute<Envelope>(() => server.Listener.ReceiveItems(2, TestListenerTimeoutInMs));
var dependencyTelemetry = dependencies.FirstOrDefault(d => d.Name == expected.Name
&& d.Data == expected.Data
&& d.Success == expected.Success
&& d.ResultCode == expected.ResultCode);
var dependencyTelemetry = actual.OfType<TelemetryItem<RemoteDependencyData>>().FirstOrDefault();
Assert.NotNull(dependencyTelemetry);
var dependencyData = ((TelemetryItem<RemoteDependencyData>)dependencyTelemetry).data.baseData;
Assert.Equal(expected.Data, dependencyData.data);
Assert.Equal(expected.ResultCode, dependencyData.resultCode);
Assert.Equal(expected.Success, dependencyData.success);
#if !NET461
var requestTelemetry = server.BackChannel.Buffer.OfType<RequestTelemetry>().Single();
Assert.Equal(requestTelemetry.Context.Operation.ParentId, dependencyTelemetry.Id);
var requestTelemetry = actual.OfType<TelemetryItem<RequestData>>().FirstOrDefault();
Assert.NotNull(requestTelemetry);
Assert.Contains(dependencyTelemetry.tags["ai.operation.id"], requestTelemetry.tags["ai.operation.parentId"]);
Assert.Equal(requestTelemetry.tags["ai.operation.id"], dependencyTelemetry.tags["ai.operation.id"]);
#endif
}
@ -147,38 +123,10 @@
var timer = timerField.GetValue(perfModule);
timerField.FieldType.InvokeMember("ScheduleNextTick", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, timer, new object[] { TimeSpan.FromMilliseconds(10) });
DateTime timeout = DateTime.UtcNow.AddMilliseconds(TestTimeoutMs);
int numberOfCountersSent = 0;
do
{
Thread.Sleep(1000);
numberOfCountersSent += server.BackChannel.Buffer.OfType<MetricTelemetry>().Distinct().Count();
} while (numberOfCountersSent == 0 && DateTime.UtcNow < timeout);
Assert.True(numberOfCountersSent > 0);
var actual = server.Execute<Envelope>(() => server.Listener.ReceiveItems(TestListenerTimeoutInMs));
Assert.True(actual.Length > 0);
}
}
#endif
/// <summary>
/// Tests if a DateTimeOffset is in a specified range and prints a more detailed error message if it is not.
/// </summary>
/// <param name="actual">The actual value to test.</param>
/// <param name="low">The minimum of the range.</param>
/// <param name="high">The maximum of the range.</param>
private void InRange(DateTimeOffset actual, DateTimeOffset low, DateTimeOffset high)
{
string dateFormat = "yyyy-MM-dd HH:mm:ss.ffffzzz";
Assert.True(low <= actual && actual <= high, $"Range: ({low.ToString(dateFormat)} - {high.ToString(dateFormat)})\nActual: {actual.ToString(dateFormat)}");
}
private void PrintBufferInfo(IList<ITelemetry> buffer)
{
output.WriteLine(string.Format("Backchannel buffer item count: {0} ", buffer.Count));
foreach (var bufferItem in buffer)
{
output.WriteLine(string.Format("Backchannel item: {0}", bufferItem.GetType()));
}
}
}
}

Просмотреть файл

@ -5,6 +5,7 @@
using System;
using System.Linq;
using System.Net.Http;
using AI;
using Xunit;
using Xunit.Abstractions;
@ -21,24 +22,25 @@
public void CorrelationInfoIsPropagatedToDependendedService()
{
#if netcoreapp2_0 // Correlation works on .Net core.
InProcessServer server;
using (server = new InProcessServer(assemblyName, InProcessServer.UseApplicationInsights))
using (var server = new InProcessServer(assemblyName, InProcessServer.UseApplicationInsights))
{
using (var httpClient = new HttpClient())
{
var task = httpClient.GetAsync(server.BaseHost + "/");
task.Wait(TestTimeoutMs);
}
var actual = server.Execute<Envelope>(() => server.Listener.ReceiveItems(2, TestListenerTimeoutInMs));
var dependencyTelemetry = actual.OfType<TelemetryItem<RemoteDependencyData>>().FirstOrDefault();
Assert.NotNull(dependencyTelemetry);
var requestTelemetry = actual.OfType<TelemetryItem<RequestData>>().FirstOrDefault();
Assert.NotNull(requestTelemetry);
Assert.Equal(requestTelemetry.tags["ai.operation.id"], dependencyTelemetry.tags["ai.operation.id"]);
Assert.Contains(dependencyTelemetry.tags["ai.operation.id"], requestTelemetry.tags["ai.operation.parentId"]);
}
var telemetries = server.BackChannel.Buffer;
Assert.True(telemetries.Count >= 2);
var requestTelemetry = telemetries.OfType<RequestTelemetry>().Single();
var dependencyTelemetry = telemetries.OfType<DependencyTelemetry>().Single();
Assert.Equal(requestTelemetry.Context.Operation.Id, dependencyTelemetry.Context.Operation.Id);
Assert.Equal(requestTelemetry.Context.Operation.ParentId, dependencyTelemetry.Id);
#endif
}
}

Просмотреть файл

@ -1,19 +1,16 @@
using System.Diagnostics;
namespace MVCFramework20.FunctionalTests.FunctionalTest
{
namespace MVCFramework20.FunctionalTests.FunctionalTest
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using AI;
using FunctionalTestUtils;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Xunit;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.DependencyCollector;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
using Xunit.Abstractions;
public class DependencyTelemetryMvcTests : TelemetryTestsBase
@ -27,9 +24,7 @@ namespace MVCFramework20.FunctionalTests.FunctionalTest
public void CorrelationInfoIsNotAddedToRequestHeaderIfUserAddDomainToExcludedList()
{
#if netcoreapp2_0 // Correlation is supported on .Net core.
InProcessServer server;
using (server = new InProcessServer(assemblyName, InProcessServer.UseApplicationInsights))
using (var server = new InProcessServer(assemblyName, InProcessServer.UseApplicationInsights))
{
var dependencyCollectorModule = server.ApplicationServices.GetServices<ITelemetryModule>().OfType<DependencyTrackingTelemetryModule>().Single();
dependencyCollectorModule.ExcludeComponentCorrelationHttpHeadersOnDomains.Add(server.BaseHost);
@ -39,20 +34,24 @@ namespace MVCFramework20.FunctionalTests.FunctionalTest
var task = httpClient.GetAsync(server.BaseHost + "/");
task.Wait(TestTimeoutMs);
}
}
var telemetries = server.BackChannel.Buffer;
try
{
Assert.True(telemetries.Count >= 2);
var requestTelemetry = telemetries.OfType<RequestTelemetry>().Single();
var dependencyTelemetry = telemetries.OfType<DependencyTelemetry>().Single();
Assert.NotEqual(requestTelemetry.Context.Operation.Id, dependencyTelemetry.Context.Operation.Id);
}
catch (Exception e)
{
string data = DebugTelemetryItems(telemetries);
throw new Exception(data, e);
var actual = server.Execute<Envelope>(() => server.Listener.ReceiveItems(TestListenerTimeoutInMs));
try
{
var dependencyTelemetry = actual.OfType<TelemetryItem<RemoteDependencyData>>().FirstOrDefault();
Assert.NotNull(dependencyTelemetry);
var requestTelemetry = actual.OfType<TelemetryItem<RequestData>>().FirstOrDefault();
Assert.NotNull(requestTelemetry);
Assert.NotEqual(requestTelemetry.tags["ai.operation.id"], dependencyTelemetry.tags["ai.operation.id"]);
}
catch (Exception e)
{
string data = DebugTelemetryItems(actual);
throw new Exception(data, e);
}
}
#endif
}
@ -72,20 +71,25 @@ namespace MVCFramework20.FunctionalTests.FunctionalTest
var task = httpClient.GetAsync(server.BaseHost + "/" + path);
task.Wait(TestTimeoutMs);
}
}
var telemetries = server.BackChannel.Buffer;
try
{
Assert.True(telemetries.Count >= 2);
var requestTelemetry = telemetries.OfType<RequestTelemetry>().Single();
var dependencyTelemetry = telemetries.OfType<DependencyTelemetry>().First(t => t.Name == "MyDependency");
Assert.Equal(requestTelemetry.Context.Operation.Id, dependencyTelemetry.Context.Operation.Id);
}
catch (Exception e)
{
string data = DebugTelemetryItems(telemetries);
throw new Exception(data, e);
var actual = server.Execute<Envelope>(() => server.Listener.ReceiveItems(TestListenerTimeoutInMs));
try
{
var dependencyTelemetry = actual.OfType<TelemetryItem<RemoteDependencyData>>()
.First( t => ((TelemetryItem<RemoteDependencyData>)t).data.baseData.name == "MyDependency");
Assert.NotNull(dependencyTelemetry);
var requestTelemetry = actual.OfType<TelemetryItem<RequestData>>().FirstOrDefault();
Assert.NotNull(requestTelemetry);
Assert.Equal(requestTelemetry.tags["ai.operation.id"], dependencyTelemetry.tags["ai.operation.id"]);
}
catch (Exception e)
{
string data = DebugTelemetryItems(actual);
throw new Exception(data, e);
}
}
}
@ -103,34 +107,42 @@ namespace MVCFramework20.FunctionalTests.FunctionalTest
var task = httpClient.GetAsync(server.BaseHost + "/" + path);
task.Wait(TestTimeoutMs);
}
}
// Filter out any unexpected telemetry items.
IEnumerable<ITelemetry> telemetries = server.BackChannel.Buffer.Where((t) => t.Context?.Operation?.Name != null && t.Context.Operation.Name.Contains(path));
try
{
Assert.NotNull(telemetries);
var requestTelemetry = telemetries.OfType<RequestTelemetry>().Single();
var dependencyTelemetry = telemetries.First(t => t is DependencyTelemetry && (t as DependencyTelemetry).Name == "MyDependency");
Assert.Equal(requestTelemetry.Id, dependencyTelemetry.Context.Operation.ParentId);
}
catch (Exception e)
{
string data = DebugTelemetryItems(server.BackChannel.Buffer);
throw new Exception(data, e);
var actual = server.Execute<Envelope>(() => server.Listener.ReceiveItems(TestListenerTimeoutInMs));
try
{
var dependencyTelemetry = actual.OfType<TelemetryItem<RemoteDependencyData>>()
.First(t => ((TelemetryItem<RemoteDependencyData>)t).data.baseData.name == "MyDependency");
Assert.NotNull(dependencyTelemetry);
var requestTelemetry = actual.OfType<TelemetryItem<RequestData>>().FirstOrDefault();
Assert.NotNull(requestTelemetry);
Assert.Contains(requestTelemetry.tags["ai.operation.id"], dependencyTelemetry.tags["ai.operation.parentId"]);
}
catch (Exception e)
{
string data = DebugTelemetryItems(actual);
throw new Exception(data, e);
}
}
}
private string DebugTelemetryItems(IList<ITelemetry> telemetries)
private string DebugTelemetryItems(Envelope[] telemetries)
{
StringBuilder builder = new StringBuilder();
foreach (ITelemetry telemetry in telemetries)
foreach (Envelope telemetry in telemetries)
{
DependencyTelemetry dependency = telemetry as DependencyTelemetry;
if (dependency != null) {
builder.AppendLine($"{dependency.ToString()} - {dependency.Data} - {dependency.Duration} - {dependency.Id} - {dependency.Name} - {dependency.ResultCode} - {dependency.Sequence} - {dependency.Success} - {dependency.Target} - {dependency.Type}");
} else {
builder.AppendLine($"{telemetry.ToString()} - {telemetry.Context?.Operation?.Name}");
TelemetryItem<RemoteDependencyData> dependency = telemetry as TelemetryItem<RemoteDependencyData>;
if (dependency != null)
{
var data = ((TelemetryItem<RemoteDependencyData>)dependency).data.baseData;
builder.AppendLine($"{dependency.ToString()} - {data.data} - {data.duration} - {data.id} - {data.name} - {data.resultCode} - {data.success} - {data.target} - {data.type}");
}
else
{
builder.AppendLine($"{telemetry.ToString()} - {telemetry.name}");
}
}

Просмотреть файл

@ -1,15 +1,14 @@
using System.Threading;
using System.Threading.Tasks;
namespace MVCFramework20.FunctionalTests.FunctionalTest
namespace MVCFramework20.FunctionalTests.FunctionalTest
{
using System.Linq;
using System.Net.Http;
using AI;
using FunctionalTestUtils;
using Microsoft.ApplicationInsights.DataContracts;
using Xunit;
using Xunit.Abstractions;
public class RequestTelemetryMvcTests : TelemetryTestsBase
{
private const string assemblyName = "MVCFramework20.FunctionalTests";
@ -80,17 +79,25 @@ namespace MVCFramework20.FunctionalTests.FunctionalTest
var task = httpClient.GetAsync(server.BaseHost + "/Home/Contact");
task.Wait(TestTimeoutMs);
}
}
var telemetries = server.BackChannel.Buffer;
Assert.Contains(telemetries.OfType<DependencyTelemetry>(), t => t.Name == "GET /Home/Contact");
Assert.True(telemetries.Count >= 4);
Assert.Contains(telemetries.OfType<RequestTelemetry>(), t => t.Name == "GET Home/Contact");
Assert.Contains(telemetries.OfType<EventTelemetry>(), t => t.Name == "GetContact");
Assert.Contains(telemetries.OfType<MetricTelemetry>(),
t => t.Name == "ContactFile" && t.Value == 1);
Assert.Contains(telemetries.OfType<TraceTelemetry>(),
t => t.Message == "Fetched contact details." && t.SeverityLevel == SeverityLevel.Information);
var telemetries = server.Execute<Envelope>(() => server.Listener.ReceiveItems(5, TestListenerTimeoutInMs));
Assert.True(telemetries.Length >= 5);
Assert.Contains(telemetries.OfType<TelemetryItem<RemoteDependencyData>>(),
t => ((TelemetryItem<RemoteDependencyData>)t).data.baseData.name == "GET /Home/Contact");
Assert.Contains(telemetries.OfType<TelemetryItem<RequestData>>(),
t => ((TelemetryItem<RequestData>)t).data.baseData.name == "GET Home/Contact");
Assert.Contains(telemetries.OfType<TelemetryItem<EventData>>(),
t => ((TelemetryItem<EventData>)t).data.baseData.name == "GetContact");
Assert.Contains(telemetries.OfType<TelemetryItem<MetricData>>(),
t => ((TelemetryItem<MetricData>)t).data.baseData.metrics[0].name == "ContactFile" && ((TelemetryItem<MetricData>)t).data.baseData.metrics[0].value == 1);
Assert.Contains(telemetries.OfType<TelemetryItem<MessageData>>(),
t => ((TelemetryItem<MessageData>)t).data.baseData.message == "Fetched contact details." && ((TelemetryItem<MessageData>)t).data.baseData.severityLevel == AI.SeverityLevel.Information);
}
}
}
}

Просмотреть файл

@ -1,6 +1,7 @@
namespace MVCFramework20.FunctionalTests.FunctionalTest
{
using FunctionalTestUtils;
using Microsoft.ApplicationInsights.DataContracts;
using Xunit;
using Xunit.Abstractions;
@ -17,7 +18,18 @@
[Fact]
public void TestBasicDependencyPropertiesAfterRequestingBasicPage()
{
this.ValidateBasicDependency(assemblyName, "/Home/About/5", InProcessServer.UseApplicationInsights);
const string RequestPath = "/Home/About/5";
using (var server = new InProcessServer(assemblyName))
{
DependencyTelemetry expected = new DependencyTelemetry();
expected.ResultCode = "200";
expected.Success = true;
expected.Name = "GET " + RequestPath;
expected.Data = server.BaseHost + RequestPath;
this.ValidateBasicDependency(server, RequestPath, expected);
}
}
[Fact]

Просмотреть файл

@ -2,7 +2,7 @@
<PropertyGroup>
<VersionPrefix>2.0.0</VersionPrefix>
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
<RuntimeIdentifier Condition=" '$(TargetFramework)' == 'net461' ">win7-x86</RuntimeIdentifier>
<DelaySign>true</DelaySign>
<PreserveCompilationContext>true</PreserveCompilationContext>
@ -43,8 +43,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.0.0" />
@ -63,7 +62,8 @@
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -23,7 +23,10 @@ namespace MVCFramework20.FunctionalTests
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITelemetryChannel>(new BackTelemetryChannel());
var builder = new ConfigurationBuilder();
builder.AddApplicationInsightsSettings(instrumentationKey: "Foo", endpointAddress: "http://localhost:4001/v2/track/", developerMode: true);
services.AddApplicationInsightsTelemetry(builder.Build());
services.AddMvc();
}

Просмотреть файл

@ -1,10 +1,11 @@
namespace WebApi20.FunctionalTests.FunctionalTest
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]
namespace WebApi20.FunctionalTests.FunctionalTest
{
using System;
using FunctionalTestUtils;
using Microsoft.ApplicationInsights.DataContracts;
using Xunit;
using Microsoft.ApplicationInsights.Extensibility;
using Xunit.Abstractions;
public class ExceptionTelemetryWebApiTests : TelemetryTestsBase

Просмотреть файл

@ -1,9 +1,8 @@
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]
namespace WebApi20.FunctionalTests.FunctionalTest
namespace WebApi20.FunctionalTests.FunctionalTest
{
using FunctionalTestUtils;
using Microsoft.ApplicationInsights.DataContracts;
using Xunit;
using Xunit.Abstractions;
public class TelemetryModuleWorkingWebApiTests : TelemetryTestsBase
@ -18,7 +17,18 @@ namespace WebApi20.FunctionalTests.FunctionalTest
[Fact]
public void TestBasicDependencyPropertiesAfterRequestingBasicPage()
{
this.ValidateBasicDependency(assemblyName, "/api/values");
const string RequestPath = "/api/values";
using (var server = new InProcessServer(assemblyName))
{
DependencyTelemetry expected = new DependencyTelemetry();
expected.ResultCode = "200";
expected.Success = true;
expected.Name = "GET " + RequestPath;
expected.Data = server.BaseHost + RequestPath;
this.ValidateBasicDependency(server, RequestPath, expected);
}
}
[Fact]

Просмотреть файл

@ -10,6 +10,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.ApplicationInsights.Channel;
using FunctionalTestUtils;
using System.IO;
namespace WebApi20.FunctionalTests
{
@ -25,8 +26,10 @@ namespace WebApi20.FunctionalTests
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITelemetryChannel>(new BackTelemetryChannel());
services.AddApplicationInsightsTelemetry(Configuration);
var builder = new ConfigurationBuilder();
builder.AddApplicationInsightsSettings(instrumentationKey: "Foo", endpointAddress: "http://localhost:4001/v2/track/", developerMode: true);
services.AddApplicationInsightsTelemetry(builder.Build());
services.AddMvc();
}

Просмотреть файл

@ -2,7 +2,7 @@
<PropertyGroup>
<VersionPrefix>2.0.0</VersionPrefix>
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
<RuntimeIdentifier Condition=" '$(TargetFramework)' == 'net461' ">win7-x86</RuntimeIdentifier>
<DelaySign>true</DelaySign>
<PreserveCompilationContext>true</PreserveCompilationContext>
@ -35,7 +35,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
@ -43,6 +42,7 @@
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.0.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
</ItemGroup>
<ItemGroup>