Skip to content

Commit d9f4b92

Browse files
authored
Merge pull request #97025 from lgayhardt/appinsightsfunavail1119
App Insights Availability Azure Functions code change
2 parents 1d84b4b + 6a25302 commit d9f4b92

File tree

10 files changed

+74
-103
lines changed

10 files changed

+74
-103
lines changed

articles/azure-monitor/app/availability-azure-functions.md

Lines changed: 74 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,31 @@ ms.subservice: application-insights
66
ms.topic: conceptual
77
author: morgangrobin
88
ms.author: mogrobin
9-
ms.date: 10/11/2019
9+
ms.date: 11/22/2019
1010

1111
---
1212

1313
# Create and run custom availability tests using Azure Functions
1414

15-
This article will cover how to create an Azure Function with TrackAvailability() that will run periodically according to the configuration given in TimerTrigger function. The results of this test will be sent to your Application Insights resource, where you will be able to query for and alert on the availability results data. This allows you to create customized tests similar to what you can do via [Availability Monitoring](../../azure-monitor/app/monitor-web-app-availability.md) in the portal. Customized tests will allow you to write more complex availability tests than is possible using the portal UI, monitor an app inside of your Azure VNET, change the endpoint address, or create an availability test even if this feature is not available in your region.
15+
This article will cover how to create an Azure Function with TrackAvailability() that will run periodically according to the configuration given in TimerTrigger function with your own business logic. The results of this test will be sent to your Application Insights resource, where you will be able to query for and alert on the availability results data. This allows you to create customized tests similar to what you can do via [Availability Monitoring](../../azure-monitor/app/monitor-web-app-availability.md) in the portal. Customized tests will allow you to write more complex availability tests than is possible using the portal UI, monitor an app inside of your Azure VNET, change the endpoint address, or create an availability test even if this feature is not available in your region.
1616

17+
> [!NOTE]
18+
> This example is designed solely to show you the mechanics of how the TrackAvailability() API call works within an Azure Function. Not how to write the underlying HTTP Test code/business logic that would be required to turn this into a fully functional availability test. By default if you walk through this example you will be creating an availability test that will always generate a failure.
1719
1820
## Create timer triggered function
1921

2022
- If you have an Application Insights Resource:
2123
- By default Azure Functions creates an Application Insights resource but if you would like to use one of your already created resources you will need to specify that during creation.
2224
- Follow the instructions on how to [create an Azure Functions resource and Timer triggered function](https://docs.microsoft.com/azure/azure-functions/functions-create-scheduled-function) (stop before clean up) with the following choices.
23-
- Click the Application Insights section before selecting **Create**.
25+
- Select the **Monitoring** tab near the top.
2426

2527
![ Create an Azure Functions app with your own App Insights resource](media/availability-azure-functions/create-function-app.png)
2628

27-
- Click **Select existing resource** and type the name of your resource. Select **Apply**
29+
- Select the Application Insights dropdown box and type or select the name of your resource.
2830

2931
![Selecting existing Application Insights resource](media/availability-azure-functions/app-insights-resource.png)
3032

31-
- Select **Create**
33+
- Select **Review + create**
3234
- If you do not have an Application Insights Resource created yet for your timer triggered function:
3335
- By default when you are creating your Azure Functions application it will create an Application Insights resource for you.
3436
- Follow the instructions on how to [create an Azure Functions resource and Timer triggered function](https://docs.microsoft.com/azure/azure-functions/functions-create-scheduled-function) (stop before clean-up).
@@ -37,143 +39,90 @@ This article will cover how to create an Azure Function with TrackAvailability()
3739

3840
Copy the code below into the run.csx file (this will replace the pre-existing code). To do this, go into your Azure Functions application and select your timer trigger function on the left.
3941

40-
![Azure function's run.csx in Azure portal](media/availability-azure-functions/runcsx.png)
42+
>[!div class="mx-imgBorder"]
43+
>![Azure function's run.csx in Azure portal](media/availability-azure-functions/runcsx.png)
4144
4245
> [!NOTE]
4346
> For the Endpoint Address you would use: `EndpointAddress= https://dc.services.visualstudio.com/v2/track`. Unless your resource is located in a region like Azure Government or Azure China in which case consult this article on [overriding the default endpoints](https://docs.microsoft.com/azure/azure-monitor/app/custom-endpoints#regions-that-require-endpoint-modification) and select the appropriate Telemetry Channel endpoint for your region.
4447
4548
```C#
49+
#load "runAvailabilityTest.csx"
50+
4651
using System;
4752
using System.Diagnostics;
48-
using System.Net.Http;
49-
using System.Threading.Tasks;
5053
using Microsoft.ApplicationInsights;
54+
using Microsoft.ApplicationInsights.Channel;
5155
using Microsoft.ApplicationInsights.DataContracts;
5256
using Microsoft.ApplicationInsights.Extensibility;
53-
using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel;
54-
using Microsoft.Azure.WebJobs;
55-
using Microsoft.Azure.WebJobs.Host;
56-
using Microsoft.Extensions.Logging;
57-
58-
// [CONFIGURATION_REQUIRED] configure test timeout accordingly for which your request should run
59-
private static readonly HttpClient HttpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
60-
57+
6158
// The Application Insights Instrumentation Key can be changed by going to the overview page of your Function App, selecting configuration, and changing the value of the APPINSIGHTS_INSTRUMENTATIONKEY Application setting.
62-
//DO NOT replace the code below with your instrumentation key, the key's value is pulled from the environment variable/application setting key/value pair.
63-
private static readonly string InstrumentationKey = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
64-
65-
// [CONFIGURATION_REQUIRED] Configure EndpointAddress
66-
private static readonly TelemetryConfiguration TelemetryConfiguration = new TelemetryConfiguration(InstrumentationKey, new ServerTelemetryChannel() { EndpointAddress = "<EndpointAddress>" });
67-
private static readonly TelemetryClient TelemetryClient = new TelemetryClient(TelemetryConfiguration);
68-
69-
[FunctionName("Function")]
70-
public static async void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
59+
// DO NOT replace the code below with your instrumentation key, the key's value is pulled from the environment variable/application setting key/value pair.
60+
private static readonly string instrumentationKey = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
61+
62+
//[CONFIGURATION_REQUIRED]
63+
// If your resource is in a region like Azure Government or Azure China, change the endpoint address accordingly.
64+
// Visit https://docs.microsoft.com/azure/azure-monitor/app/custom-endpoints#regions-that-require-endpoint-modification for more details.
65+
private const string EndpointAddress = "https://dc.services.visualstudio.com/v2/track";
66+
67+
private static readonly TelemetryConfiguration telemetryConfiguration = new TelemetryConfiguration(instrumentationKey, new InMemoryChannel { EndpointAddress = EndpointAddress });
68+
private static readonly TelemetryClient telemetryClient = new TelemetryClient(telemetryConfiguration);
69+
70+
public async static Task Run(TimerInfo myTimer, ILogger log)
7171
{
7272
log.LogInformation($"Entering Run at: {DateTime.Now}");
73-
73+
7474
if (myTimer.IsPastDue)
7575
{
7676
log.LogWarning($"[Warning]: Timer is running late! Last ran at: {myTimer.ScheduleStatus.Last}");
7777
}
78-
78+
7979
// [CONFIGURATION_REQUIRED] provide {testName} accordingly for your test function
8080
string testName = "AvailabilityTestFunction";
81-
81+
8282
// REGION_NAME is a default environment variable that comes with App Service
8383
string location = Environment.GetEnvironmentVariable("REGION_NAME");
84-
85-
// [CONFIGURATION_REQUIRED] configure {uri} and {contentMatch} accordingly for your web app. {uri} is the website that you are testing the availability of, make sure to include http:// ot https:// in your url. If {contentMatch} is present on the page, the test will succeed, otherwise it will fail.
86-
await AvailabilityTestRun(
87-
name: testName,
88-
location: location,
89-
uri: "<http://example.com>",
90-
contentMatch: "<Enter a short string of text that is present in the body of the page your are testing>",
91-
log: log
92-
);
93-
}
94-
95-
private static async Task AvailabilityTestRun(string name, string location, string uri, string contentMatch, ILogger log)
96-
{
97-
log.LogInformation($"Executing availability test run for {name} at: {DateTime.Now}");
98-
84+
85+
log.LogInformation($"Executing availability test run for {testName} at: {DateTime.Now}");
9986
string operationId = Guid.NewGuid().ToString("N");
100-
87+
10188
var availability = new AvailabilityTelemetry
10289
{
10390
Id = operationId,
104-
Name = name,
91+
Name = testName,
10592
RunLocation = location,
10693
Success = false
10794
};
108-
95+
10996
var stopwatch = new Stopwatch();
11097
stopwatch.Start();
111-
bool isMonitoringFailure = false;
112-
98+
11399
try
114100
{
115-
using (var httpResponse = await HttpClient.GetAsync(uri))
116-
{
117-
// add test results to availability telemetry property
118-
availability.Properties.Add("HttpResponseStatusCode", Convert.ToInt32(httpResponse.StatusCode).ToString());
119-
120-
// check if response content contains specific text
121-
string content = httpResponse.Content != null ? await httpResponse.Content.ReadAsStringAsync() : "";
122-
if (httpResponse.IsSuccessStatusCode && content.Contains(contentMatch))
123-
{
124-
availability.Success = true;
125-
availability.Message = $"Test succeeded with response: {httpResponse.StatusCode}";
126-
log.LogTrace($"[Verbose]: {availability.Message}");
127-
}
128-
else if (!httpResponse.IsSuccessStatusCode)
129-
{
130-
availability.Message = $"Test failed with response: {httpResponse.StatusCode}";
131-
log.LogWarning($"[Warning]: {availability.Message}");
132-
}
133-
else
134-
{
135-
availability.Message = $"Test content does not contain: {contentMatch}";
136-
log.LogWarning($"[Warning]: {availability.Message}");
137-
}
138-
}
139-
}
140-
catch (TaskCanceledException e)
141-
{
142-
availability.Message = $"Test timed out: {e.Message}";
143-
log.LogWarning($"[Warning]: {availability.Message}");
101+
await RunAvailbiltyTestAsync(log);
102+
availability.Success = true;
144103
}
145104
catch (Exception ex)
146105
{
147-
// track exception when unable to determine the state of web app
148-
isMonitoringFailure = true;
106+
availability.Message = ex.Message;
107+
149108
var exceptionTelemetry = new ExceptionTelemetry(ex);
150109
exceptionTelemetry.Context.Operation.Id = operationId;
151-
exceptionTelemetry.Properties.Add("TestName", name);
110+
exceptionTelemetry.Properties.Add("TestName", testName);
152111
exceptionTelemetry.Properties.Add("TestLocation", location);
153-
exceptionTelemetry.Properties.Add("TestUri", uri);
154-
TelemetryClient.TrackException(exceptionTelemetry);
155-
log.LogError($"[Error]: {ex.Message}");
156-
157-
// optional - throw to fail the function
158-
//throw;
112+
telemetryClient.TrackException(exceptionTelemetry);
159113
}
160114
finally
161115
{
162116
stopwatch.Stop();
163117
availability.Duration = stopwatch.Elapsed;
164118
availability.Timestamp = DateTimeOffset.UtcNow;
165-
166-
// do not make an assumption as to the state of the web app when monitoring failures occur
167-
if (!isMonitoringFailure)
168-
{
169-
TelemetryClient.TrackAvailability(availability);
170-
log.LogInformation($"Availability telemetry for {name} is sent.");
171-
}
172-
173-
// call flush to ensure telemetries are sent
174-
TelemetryClient.Flush();
119+
120+
telemetryClient.TrackAvailability(availability);
121+
// call flush to ensure telemetry is sent
122+
telemetryClient.Flush();
175123
}
176124
}
125+
177126
```
178127

179128
On the right under view files, select **Add**. Call the new file **function.proj** with the following configuration.
@@ -184,35 +133,57 @@ On the right under view files, select **Add**. Call the new file **function.proj
184133
<TargetFramework>netstandard2.0</TargetFramework>
185134
</PropertyGroup>
186135
<ItemGroup>
187-
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.6.1" />
136+
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.8.2" /> <!-- Ensure youre using the latest version -->
188137
</ItemGroup>
189138
</Project>
190139

191140
```
192141

193-
![On the right select, add. Name the file function.proj](media/availability-azure-functions/addfile.png)
142+
>[!div class="mx-imgBorder"]
143+
>![On the right select, add. Name the file function.proj](media/availability-azure-functions/addfile.png)
144+
145+
On the right under view files, select **Add**. Call the new file **runAvailabilityTest.csx** with the following configuration.
146+
147+
```C#
148+
public async static Task RunAvailbiltyTestAsync(ILogger log)
149+
{
150+
// Add your business logic here.
151+
throw new NotImplementedException();
152+
}
153+
154+
```
194155

195156
## Check availability
196157

197158
To make sure everything is working, you can look at the graph in the Availability tab of your Application Insights resource.
198159

199-
![Availability tab with successful results](media/availability-azure-functions/availtab.png)
160+
> [!NOTE]
161+
> If you implemented your own business logic in runAvailabilityTest.csx then you will see successful results like in the screenshots below, if you did not then you will see failed results.
162+
163+
>[!div class="mx-imgBorder"]
164+
>![Availability tab with successful results](media/availability-azure-functions/availtab.png)
200165
201166
When you set up your test using Azure Functions you will notice, that unlike using **Add test** in the Availability tab, the name of your test will not appear and you will not be able to interact with it. The results are visualized but you get a summary view instead of the same detailed view you get when you create an availability test via the portal.
202167

203168
To see the end-to-end transaction details, select **Successful** or **Failed** under drill into, then select a sample. You can also get to the end-to-end transaction details by selecting a data point on the graph.
204169

205-
![Select a sample availability test](media/availability-azure-functions/sample.png)
170+
>[!div class="mx-imgBorder"]
171+
>![Select a sample availability test](media/availability-azure-functions/sample.png)
172+
173+
>[!div class="mx-imgBorder"]
174+
>![End-to-end transaction details](media/availability-azure-functions/end-to-end.png)
206175
207-
![End-to-end transaction details](media/availability-azure-functions/end-to-end.png)
176+
If you ran everything as is (without adding business logic), then you will see that the test failed.
208177

209178
## Query in Logs (Analytics)
210179

211180
You can use Logs(analytics) to view you availability results, dependencies, and more. To learn more about Logs, visit [Log query overview](../../azure-monitor/log-query/log-query-overview.md).
212181

213-
![Availability results](media/availability-azure-functions/availabilityresults.png)
182+
>[!div class="mx-imgBorder"]
183+
>![Availability results](media/availability-azure-functions/availabilityresults.png)
214184
215-
![Dependencies](media/availability-azure-functions/dependencies.png)
185+
>[!div class="mx-imgBorder"]
186+
>![Dependencies](media/availability-azure-functions/dependencies.png)
216187
217188
## Next steps
218189

144 KB
Loading
-110 KB
Loading
172 KB
Loading
111 KB
Loading
71.3 KB
Loading
210 KB
Loading
105 KB
Loading
31.9 KB
Loading
43 KB
Loading

0 commit comments

Comments
 (0)