My function will be triggered from an existing ServiceBus topic. I have created the function using the new tooling in VS2017 (15.3) preview, as a compiled function.
How can I test this function locally?
For a non-http triggered function, you can send a POST request to the local administrator endpoint. More info here
like this (I am using Postman)
If you want to check whether your function will be triggered by Azure Service Bus messages, you need to own a Azure Subscription and create a Service Bus namespace because Microsoft haven't provided Azure Service Bus emulator like Azure Storage emulator.
If you want to debug your function, you could create a new console application and invoke the function you defined. Steps below are for your reference.
Step 1, Create a Console Application.
Step 2, Add Project reference to the function project.
Step 3, Install Microsoft.Azure.WebJobs -Version 2.1.0-beta1 package from NuGet to your console application.
Install-Package Microsoft.Azure.WebJobs -Version 2.1.0-beta1
Step 4, Use following code to invoke your function.
class Program
{
static void Main(string[] args)
{
Function1.Run("msg1", new MyTraceWriter(TraceLevel.Info));
}
}
public class MyTraceWriter : TraceWriter
{
public MyTraceWriter(TraceLevel level) : base(level)
{
}
public override void Trace(TraceEvent traceEvent)
{
Console.WriteLine(traceEvent.Message);
}
}
You run the project in debug mode and create a JSON payload for the message then you can post a complete json object in this format.
{
"input": "<trigger_input>"
}
for example
http://localhost:7071/admin/functions/OrderFunction
You can then read message in your function body and get the Json you posted.
Encoding.UTF8.GetString(message.Body)
Related
I'm trying to set up an Azure function that can trigger a Azure devops build pipeline. But I'm not sure on how to proceed with this and if it's even possible to do so.
I already have a build pipeline ready to be used but the conventional triggers that are already provided by Azure devops cannot be used. I can't disclose the reason but I need to trigger it using an Azure function. Any help regarding this would be really helpful.
Thanks.
You can simply use the REST APIs of Azure DevOps and call those from your function. See here: API for automating Azure DevOps Pipelines?
How to proceed with this and if it's even possible to do so.
Of course, it can do to trigger a Azure Devops pipeline by Azure function.
To achieve this, you will use Visual Studio also, better with the version 2017 or higher , and also installed .Net Core SDK and Develop Azure Functions using Visual Studio.
In the Azure Function App you created, open HttpTrigger1, and
click Get Function Url. This is a key point, so better save
it in the txt. Because as this execution, Azure Function just act as
a switching proxy or mechanism.
Create a Azure Function project in Visual studio. In template,
choose HttpTrigger template, Azure Functions v1 (.NET
Framework) from the framework dropdown.
Open .cs file and input the below script in it:
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
namespace PartsUnlimited.AzureFunction
{
public static class Function1
{
[FunctionName("HttpTriggerCSharp1")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route =
null)]HttpRequestMessage req, TraceWriter log)
{
var userIdKey = req.GetQueryNameValuePairs().FirstOrDefault(q =>
string.Equals(q.Key, "UserId", StringComparison.OrdinalIgnoreCase));
var userId = string.IsNullOrEmpty(userIdKey.Value) ? int.MaxValue : Convert.ToInt64(userIdKey.Value);
var url = $"https://<<APIAppServiceUrl>>/api/{(userId > 10 ? "v1" : "v2")}/specials/GetSpecialsByUserId?id={userId}";
using (HttpClient httpClient = new HttpClient())
{
return await httpClient.GetAsync(url);
}
}
}
}
Replace <<APIAppServiceUrl>> with your AzureWebsite.net URL.
Go xxxxWebsite->Controllers->StoreController.cs, replace the url
variable in line 46 with your Function url which copied in Step 1.
Click Commit and Push All to push the changes to the Azure
Devops repository.
Create a build pipeline, and enable CI. And also, create release pipeline, add deloy Azure App task and enable CD.
That's all the steps you need to create. There has been a blog which written by our Azure DevOps Labs and it has the detailed steps, you can refer to it.
REST API can be easily invoked from an azure function.
You can pretty much deploy a whole infrastructure as well as deploy the code just based on a function call using azure DevOps.
Refer this for more information: https://learn.microsoft.com/en-us/rest/api/azure/devops/
I am monitoring a lot of applications in Azure Application Insights.
In all of them I add some custom properties to events, traces etc so I can filter/group in the portal.
Is it possible to add the same custom properties to the built in application insight integration with Azure Functions?
Have read the documentation but can't find anything about it.
Edit:
I maintain a large number of applications hosted in various environments. About 15 of these are Azure Functions.
From all my applications I send telemetry to the same application insights instance via a log handler. To filter/group the information I add "CustomerName" and "CustomerInstance" properties to all events automatically via my log handler.
When I get the standard events from an Azure Function it is difficult to present information in a useful way and correlate it with other events.
With some clever naming of the function apps I can parse the request url in analytics but not in the portal.
You can add these custom properties explicitly using telemetry.Context.Properties.Add() method.
I did a demo with function v2 as below:
1.Create a function v2 in visual studio
2.Then in the visual studio, add Microsoft.ApplicationInsights 2.8.1(latest version) via nuget package manager
3.In your Function.cs, write the following code:
using Microsoft.ApplicationInsights;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using System;
namespace FunctionApp17
{
public static class Function1
{
private static string key = System.Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY",EnvironmentVariableTarget.Process);
private static TelemetryClient telemetry = new TelemetryClient() { InstrumentationKey= key };
[FunctionName("Function1")]
public static void Run([TimerTrigger("*/10 * * * * *")]TimerInfo myTimer, ILogger log)
{
if (!telemetry.Context.Properties.ContainsKey("Function_appName"))
{
telemetry.Context.Properties.Add("Function_appName", "myfuncapp111");
}
else
{
telemetry.Context.Properties["Function_appName"] = "myfuncapp111";
}
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
telemetry.TrackEvent("event111");
telemetry.TrackTrace("trace111");
}
}
}
4.Publish to azure, and in your function app -> Application settings, add the instrumentation key:
5.After the function app is running, nav to your application insights -> search, you can add your filters which defined in your code.
Then you can see the filtered message:
I'm looking to create a WebJob that takes in a request and sends a response, much like an Azure Function with an HTTP trigger. I want to use a WebJob instead because I need to use wkhtmltopdf, which cannot run on a Consumption plan, and we are already paying for an App Service that it can run on.
I know how to run the WebJob using an HTTP POST from this link: https://stackoverflow.com/a/42824776/443044.
What I cannot figure out is how to create the WebJob itself.
Here is my Program class:
public class Program
{
[NoAutomaticTrigger]
public static void TestMethod(TextWriter logger)
{
logger.WriteLine("TEST: " + req.Content.ToString());
}
// Please set the following connection strings in app.config for this WebJob to run:
// AzureWebJobsDashboard and AzureWebJobsStorage
static void Main()
{
var config = new JobHostConfiguration();
...
var host = new JobHost(config);
host.Call(typeof(Program).GetMethod("TestMethod"), null);
}
}
The program throws an exception if I try to give TestMethod the return type of HttpResponseMessage or a parameter of type HttpRequestMessage.
How can I achieve the request/response functionality like with an Azure Function?
we are already paying for an App Service -> You do realize you can host your azure function on an existing app plan as well? learn.microsoft.com/en-us/azure/azure-functions/….
But AFAIK webjobs do not have capabilities to respond to requests.
Looks like function.json in your Azure function's zip file defines Az func's trigger. Is it possible to change the trigger from Timer based to Event based programatically? Meaning, can I have a python application running perhaps in my local computer which calls Azure python sdk and says hey, change the Azure Function x's trigger from timer based to event hub based trigger and here is the additional event hub namespace name and connection string information that you need.
This is not possible.
However, I can think of the following workaround, which should accomplish the goal.
First, you can define multiple function triggers within one function project (one function app service). They could be bound to different targets. Something like this:
public static class Functions
{
[FunctionName("FunctionTimer")]
public static async Task RunAsync([TimerTrigger("%Schedule%")]TimerInfo myTimer, ILogger log)
{
if (!AppSettings.IsTimerTriggerActive)
return;
...
}
[FunctionName("FunctionEventHub")]
public static async Task RunAsync([EventHubTrigger("", Connection = "eventHubConnectionString")] EventData[] eventDataBatch, ILogger log)
{
if (!AppSettings.IsEventHubTriggerActive)
return;
...
}
}
You cannot enable/disable a function programmatically, but you can control which one of these is active via the App Service Application Settings. The latter could be managed through the Web App API: https://learn.microsoft.com/en-us/rest/api/appservice/webapps/updateapplicationsettings
Thus you can activate either trigger. One can even skip the (de)activation if that's compatible with the logic.
With the Azure WebJobs SDK, the process of adding logging to your functions is relatively straightforward: Add a TextWriter param to your triggered function, and write to it. That's it.
The SDK will will then associate and display these logs with their execution instances in the WebJobs Dashboard, which provides a relatively data-rich, yet frictionless view into the operationalization of your webjobs.
While this data is replicated into a user-accessible Azure Storage Blob Container, more custom code would be required to periodically push these logs to App Insights, which is undesirable.
Looking for ideas or solutions for how to push all logs pushed via the injected TextWriter to be pushed to AppInsights (or OMS, for that matter), complete with the webjobs execution/trigger instance metadata, thereby allowing a unified consumption experience for various log analytics.
Based on this Feature being tracked in the WebJobs SDK, I'm assuming that for now this is not possible? A long while back I looked into trying to inject my own TextWriter instance, but I would've had to fork the WebJobs SDK and use my customized assembly that changed a lot of architecture.
You can write a custom TraceWriter that sends log to AppInsights:
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.ApplicationInsights;
using Microsoft.Azure.WebJobs.Host;
public class AppInsightsTraceWriter : TraceWriter
{
private readonly TelemetryClient _telemetryClient;
public AppInsightsTraceWriter(TraceLevel level, TelemetryClient telemetryClient)
: base(level)
{
_telemetryClient = telemetryClient;
}
public override void Trace(TraceEvent traceEvent)
{
var eventTelemetry = new EventTelemetry() {Name = "WebjobTraceEvent"};
eventTelemetry.Properties.Add(traceEvent.Level.ToString(), traceEvent.ToString());
_telemetryClient.TrackEvent(eventTelemetry);
}
}
In this example, I inject the TelemetryClient class because you should only have one instance of the TelemetryClient class in your application.
So now you just need to configure the Jobhost to use your custom writer :
// Initialize the webjob configuration.
var config = new JobHostConfiguration();
// Only one instance of the telemetry client is needed
var telemetryClient = new TelemetryClient() {InstrumentationKey = "MyInstrumentationKey"};
// Add the app insights tracer for webjob logs/traces.
config.Tracing.Tracers.Add(new AppInsightsTraceWriter(TraceLevel.Info, telemetryClient));
// Detect when the webjob shut down
var cancellationToken = new WebJobsShutdownWatcher().Token;
cancellationToken.Register(() =>
{
// Before shut down, flush the app insights client.
telemetryClient.Flush();
});
new JobHost(config).RunAndBlock();
So if you have a function like that:
public static void ProcessQueueMessage([QueueTrigger("myqueue")] string logMessage, TextWriter log)
{
log.WriteLine(logMessage);
}
Every time you use log.WriteLine, an event will be sent to App Insights.
Note: if this sample also logs from the JobHost are sent to AppInsights.
This is super old (not sure why SO decided to put it in the sidebar for me after this long) but for anyone else that stumbles upon this, app insights is now the recommended way to monitor webjob executions.
Check out the documentation here which steps through the process of connecting app insights to webjobs.
This link walks you through configuring the logging portion of a new webjobs project. Check through the earlier sections to make sure that you've got all the prerequisites.
https://learn.microsoft.com/en-us/azure/app-service/webjobs-sdk-get-started#add-application-insights-logging
static async Task Main()
{
var builder = new HostBuilder();
builder.UseEnvironment(EnvironmentName.Development);
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage();
});
builder.ConfigureLogging((context, b) =>
{
b.AddConsole();
// If the key exists in settings, use it to enable Application Insights.
string instrumentationKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
if (!string.IsNullOrEmpty(instrumentationKey))
{
b.AddApplicationInsightsWebJobs(o => o.InstrumentationKey = instrumentationKey);
}
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
I will share the detailed steps to use Application Insights in Azure Web Job, please refer to it.
Create an new Azure Application Insights in Azure portal
Create Azure Web Job project in Visual Studio and install
Microsoft.ApplicationInsights
Set the instrumentation key and send
telemetry
public static void ProcessQueueMessage([QueueTrigger("queuename")] string message, TextWriter log)
{
TelemetryClient tc = new TelemetryClient();
tc.InstrumentationKey = "key copied from Azure portal";
tc.TrackTrace(message);
tc.Flush();
//log.WriteLine(message);
}
This documentation explained how to monitor usage and performance in Windows Desktop apps, you could refer to it to know how to use Azure Application Insights in non-web application. Besides, ApplicationInsights.Helpers.WebJobs could be also helpful.