How to get notification when webjob status was aborted in azure - azure

Azure WebJob, how to be notified if it aborted?
(1)Always Availability is on for the service.
(2) SCM_COMMAND_IDLE_TIMEOUT = 2000.
WEBJOBS_IDLE_TIMEOUT = 2000.

But as i'm new to this. can you please help me on this one where can i put the logic
You could add the logic in the Function.cs file. For more information you could refer to the detail steps
Steps:
1.follow official document to create a webjob project.
2.Add Functions.cs in the project
using System.IO;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions;
using SendGrid;
public class Functions
{
//demo webjob trigger
public static void ProcessQueueMessage([QueueTrigger("queue")] string message, TextWriter log)
{
log.WriteLine(message);
}
// error monitor
public static void ErrorMonitor([ErrorTrigger("0:30:00", 10, Throttle = "1:00:00")]TraceFilter filter, [SendGrid] SendGridMessage message)
{
message.Subject = "WebJobs Error Alert";
message.Text = filter.GetDetailedMessage(5);
}
}
3.If want to use ErrorTrigger and SendGrid we need to config it in the Program.cs file.
static void Main()
{
var config = new JobHostConfiguration();
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
config.UseCore();
config.UseSendGrid(new SendGridConfiguration
{
ApiKey = "xxxxx",
FromAddress = new Email("emailaddress","name"),
ToAddress = new Email("emailaddress","name")
});
var host = new JobHost(config);
// The following code ensures that the WebJob will be running continuously
host.RunAndBlock();
}
4.If we want to test it locally, we need to add Storage connection string in the App Settings collection.
<connectionStrings>
<add name="AzureWebJobsStorage" connectionString="{storage connection string}" />
</connectionStrings>

Related

Azure Function (Service Bus Trigger) Not Getting started when a new message comes into the service bus queue

Created an Azure Function which is a service bus triggered in Visual Studio and published to Azure from Visual Studio.
Whenever a message goes to queue, the function is running fine from local when manually run. But the expectation is the function should automatically trigger when a message is in the queue.
I am just adding a new message manually and seeing the logs if the function got triggered automatically but it is not. When I checked the Application Insight I found the below error logs
The listener for function 'ProcessVideos' was unable to start. Service Bus account connection string 'connection' does not exist. Make sure that it is a defined App Setting.*"
Code for local.settings.json where the Service Bus connection string is set.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"connection": "Endpoint=sb://videoupload10000.servicebus.windows.net/;SharedAccessKeyName=Listen;SharedAccessKey=80n8a0MCmh+3UZN4+4B7gDy4gp3hKCxfDI/9urDmaP8=;"
}
}
Code for the actual function.
using System;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.Messaging.ServiceBus;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
namespace ReceiveMessages
{
public static class Process
{
private static string blob_connection_string = "DefaultEndpointsProtocol=https;AccountName=videostorage1000;AccountKey=y6CVtXafqKuShZuv6BMbVj9DrymzVdNDpjDVxp6hZMvuRRjcCz/i8TrOGfM5T/JCvfG33sY3xqqW+ASt3p6V+Q==;EndpointSuffix=core.windows.net";
private static string source_container_name = "unprocessed";
private static string destination_container_name = "processed";
private static readonly string _connection_string = "AccountEndpoint=https://videodbupdate.documents.azure.com:443/;AccountKey=gmR051bG7uq7o2i519m7J9nh6tb4LLctfOQ3nPMUxMu9QJWsmh1SPiY8ylvxoY3bn7kWR4cS2qwanBdIoXSrpg==;";
private static readonly string _database_name = "appdb";
private static readonly string _container_name = "video";
[FunctionName("ProcessVideos")]
public static async Task Run([ServiceBusTrigger("videoqueue", Connection = "connection")]ServiceBusReceivedMessage myQueueItem, ILogger log)
{
ReceivedMessage _message = JsonSerializer.Deserialize<ReceivedMessage>(Encoding.UTF8.GetString(myQueueItem.Body));
BlobServiceClient _client = new BlobServiceClient(blob_connection_string);
BlobContainerClient _source_container_client = _client.GetBlobContainerClient(source_container_name);
BlobClient _source_blob_client = _source_container_client.GetBlobClient(_message.VideoName);
BlobContainerClient _destination_container_client = _client.GetBlobContainerClient(destination_container_name);
BlobClient _destination_blob_client = _destination_container_client.GetBlobClient(_message.VideoName);
CosmosClient _cosmosclient = new CosmosClient(_connection_string, new CosmosClientOptions());
Container _container = _cosmosclient.GetContainer(_database_name, _container_name);
BlobDownloadInfo _info = _source_blob_client.Download();
// Copy the blob to the destination container
await _destination_blob_client.StartCopyFromUriAsync(_source_blob_client.Uri);
log.LogInformation(_info.Details.LastModified.ToString());
log.LogInformation(_info.ContentLength.ToString());
BlobDetails _blobdetails = new BlobDetails();
_blobdetails.BlobName = _message.VideoName;
_blobdetails.BlobLocation = "https://videostorage100.blob.core.windows.net/processed/" + _message.VideoName;
_blobdetails.ContentLength = _info.ContentLength.ToString();
_blobdetails.LastModified = _info.Details.LastModified.ToString();
_blobdetails.id = Guid.NewGuid().ToString();
//_container.CreateItemAsync(_blobdetails, new PartitionKey(_message.VideoName)).GetAwaiter().GetResult();
// await _container.CreateItemAsync(_blobdetails, new PartitionKey(_message.VideoName));
Console.WriteLine("Item created");
// Delete the blob from the unprocessed container
_source_blob_client.Delete();
// Add the details of the blob to an Azure Cosmos DB account
}
}
}
The local settings are not uploaded to the cloud. to add your connection string you need to do the following. Go to your function app in azure. Select "configuration" under "settings" from the left side menu items. On this screen, you should click on the button "+ New Application Settings". Once the popup opens add "connection" as the name and your connection string as the value. Click on "OK" and then on the next screen click on "save" to save and apply the settings. Hope this helps
For a python project, your connection value in function.json needs to refer to the value in local.settings.json. Should be similar for you:
function.json:
"connection": "AzureWebJobsMyServiceBus"
local.settings.json:
"AzureWebJobsMyServiceBus": "Endpoint=sb://..."

Serilog logging part of message in Azure Application Insight

After searching lot on google and trying to find what could be the problem, logged issue in github repo where from I had read about serilog implmentation in .Net Core function app - https://github.com/serilog/serilog-sinks-applicationinsights/issues/179
Serilog is not logging complete message in Azure application insights, no idea what could be the reason. However on console it is logging complete message. Below is code snippet in Startup.cs
public override void Configure(IFunctionsHostBuilder builder)
{
var logger = ConfigureLogging();
builder.Services.AddLogging(lb => lb.AddSerilog(logger));
}
private Logger ConfigureLogging()
{
var telemetryConfiguration = TelemetryConfiguration.CreateDefault();
telemetryConfiguration.InstrumentationKey =
Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
int defaultLoggingSwitch = 3;//Warning
int tloggingSwitch = 3;//Warning
int tSloggingSwitch = 3;//Warning
Int32.TryParse(Environment.GetEnvironmentVariable("DefaultLogging"), out defaultLoggingSwitch);
Int32.TryParse(Environment.GetEnvironmentVariable("TMPLoggingSwitch"), out tloggingSwitch);
Int32.TryParse(Environment.GetEnvironmentVariable("TESLoggingSwitch"), out tSloggingSwitch);
LoggingLevelSwitch SeriLogLevelSwitch = new LoggingLevelSwitch((LogEventLevel)defaultLoggingSwitch);
LoggingLevelSwitch TMPLoggingSwitch = new LoggingLevelSwitch((LogEventLevel)tloggingSwitch);
LoggingLevelSwitch TESLoggingSwitch = new LoggingLevelSwitch((LogEventLevel)tSloggingSwitch);
var logger = new LoggerConfiguration()
.MinimumLevel.ControlledBy(SeriLogLevelSwitch)
.MinimumLevel.Override("ClassName", TMPLoggingSwitch)
.MinimumLevel.Override("IEventsService", TESLoggingSwitch)
.Enrich.FromLogContext()
.WriteTo.ApplicationInsights(telemetryConfiguration, TelemetryConverter.Events)
.CreateLogger();
return logger;
}
Consuming in Eventhub based function app as shown below -
Injecting logger in Function App class -
public EventHubProcessing(ITypeService teService, IConfiguration configuration, IServiceScopeFactory serviceScopeFactory, ILogger<ISampleClass> logger)
{
log = logger;
}
Run method below -
public async Task Run([EventHubTrigger("%EVENTHUB-RECIEVE%", Connection = "EVENTHUB-RECIEVE-CONN",ConsumerGroup = "%ConsumerGroup%")] EventData[] events, Microsoft.Azure.WebJobs.ExecutionContext executionContext, CancellationToken cancellationToken)
{
string json = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count);
log.LogInformation($"Event Hub trigger function processed a message: {json}");
}
Below are nuget package versions -
Serilog Nuget versions
Please let me know if anything else is required.
There are two places in Azure Application Insight which shows log message. At one place it was not showing complete message which I think is supposed to show only initial part of log message but in another field complete message was shown. So it is not an issue at all.

How to retrieve Azure App Configuration Service settings while in Program.cs

I am using Asp.NET Core 5 (v5.0.6) web API deployed as an Azure App Service and I am migrating from using appsettings.json in the API to integrating with Azure App Configuration service. I have the Azure App Configuration Service set up but the issue I am having is how to access values in my Azure App Configuration service for retrieving a connection string for database access while I am still in Program.cs.
Note that in the CreateHostBuilder() method I am examining the context.HostingEnvironment.IsDevelopment() environment variable and if it is "IsDevelopment", implying a local DEV, I am reading an Azure App Configuration Service connection string via User Secrets but if it is not a local DEV, than I rely on the Managed Identity and just pass in the endpoint value from appsettings.json.
The only values I want to get that are not in Azure App Configuration Service is the local DEV Azure App Configuration Service Connection string (from User Secrets) and the Azure App Configuration Service endpoint from Appsettings.json. All other settings should come from Azure App Configuration Service.
The problem I am trying to solve is how to access the values in Azure App Configuration Service, while still in Program.cs, to retrieve the connection string for access to the Azure SQL database I am using for logging.
In the code below, when I link the Azure App Configuration in the CreateHostBuilderMethod and call build, I expected the values in Azure App Configuration Service to then be available via the static Configuration property. However when I try to retrieve the connection string value, it is always null.
How can I correctly retrieve the values for properties in Azure App Configuration Service to use them in Program.cs?
Here is my Program.cs file;
public class Program
{
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddUserSecrets<Startup>()
.Build();
public static void Main(string[] args)
{
var host = CreateHostBuilder(args)
.Build();
var connectionString = Configuration["CoreApi:Settings:LoggingDb"]; //<-- This returns null
const string tableName = "ApiLogs";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Filter.ByExcluding(Matching.FromSource("Microsoft.EntityFrameworkCore.Query"))
.WriteTo.MSSqlServer(
connectionString: connectionString,
sinkOptions: new MSSqlServerSinkOptions { TableName = tableName })
.CreateLogger();
// TODO Enable to debug any startup Serilog issues. Make sure to comment out for PROD
// Serilog.Debugging.SelfLog.Enable(msg =>
// {
// Debug.Print(msg);
// Debugger.Break();
// });
//var host = CreateHostBuilder(args)
// .Build();
try
{
Log.Information("Starting ConfirmDelivery API");
host.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "ConfirmDelivery API Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
var settings = config.Build();
if (context.HostingEnvironment.IsDevelopment())
{
var connectionString = settings.GetConnectionString("AzureAppConfiguration");
config.AddAzureAppConfiguration(connectionString);
}
else
{
var endpoint = settings["AppConfigEndpoint"];
var credentials = new ManagedIdentityCredential();
config.AddAzureAppConfiguration(options =>
{
options.Connect(new Uri(endpoint), credentials);
});
}
}).ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Try the code below to get a config value:
using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
namespace myapp
{
class Program
{
static void Main(string[] args)
{
var configItemName = "";
var appConfigConnectionString = "";
var builder = new ConfigurationBuilder();
builder.AddAzureAppConfiguration(appConfigConnectionString);
var config = builder.Build();
Console.WriteLine(config[configItemName]);
}
}
}
Result :

Azure WebJobs and ApplicationInsights

I have following code:
public static void Main()
{
_servicesBusConnectionString = ConfigurationManager.AppSettings["Microsoft.ServiceBus.ConnectionString"];
_namespaceManager = NamespaceManager.CreateFromConnectionString(_servicesBusConnectionString);
_applicationInsightsInstrumentationKey = ConfigurationManager.AppSettings["appInsightsInstrumentationKey"];
JobHostConfiguration config = new JobHostConfiguration();
ServiceBusConfiguration serviceBusConfig = new ServiceBusConfiguration
{
ConnectionString = _servicesBusConnectionString
};
config.UseServiceBus(serviceBusConfig);
config.LoggerFactory = new LoggerFactory()
.AddApplicationInsights(_applicationInsightsInstrumentationKey, null)
.AddConsole();
config.Tracing.ConsoleLevel = TraceLevel.Off;
var host = new JobHost(config);
host.RunAndBlock();
}
and in function:
public static async Task ProcessMessages([ServiceBusTrigger(ServiceBusQueueNames.SomeQueueName)]BrokeredMessage brokeredMessage, TextWriter log)
{
try
{
_log = log;
_log.WriteLine("WebJob started processing of a message");
await _log.FlushAsync();}
It logs message to console, but not to ApplicationInsights.
Instrumentation key set properly.
Can you please say why it does not log to the ApplicationInsights?
I'v written this code accordingly https://github.com/Azure/azure-webjobs-sdk/wiki/Application-Insights-Integration
first thing to check: is your instrumentation key valid at runtime?
then, if the ikey is what you expect it to be, is it for the resource you expect it to be (you aren't looking at a dev application insights instance but the telemetry is going to a prod instance?)
if you debug this locally, do you see application insights assemblies getting loaded?
do you see console output from application insights with the debugger running?

How to push data in document db using webjobs?

I have written following code to read the data from text file and then separate the sentences and send them to azure event hub.
I am able to send the data to event hub but not able to push data in document db.
How to push data in document db using webjobs? I am running webjobs from console application, Do I need add more configuration to run it locally?
Program.cs
static void Main(string[] args)
{
JobHostConfiguration config = new JobHostConfiguration();
config.Tracing.ConsoleLevel = System.Diagnostics.TraceLevel.Error;
var eventHubConfig = new EventHubConfiguration();
eventHubConfig.AddReceiver(eventHubName, connectionString);
config.UseEventHub(eventHubConfig);
JobHost host = new JobHost(config);
config.DashboardConnectionString = StorageConnectionString;
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
//Send test messages
Task.Run(() =>
{
SendMessagesToEventHub();
});
host.RunAndBlock();
}
function.cs
class Functions
{
public static void Run([EventHubTrigger("azurepochub")] EventData message, [Microsoft.Azure.WebJobs.DocumentDB("testcosmosdb01122018", "Items", ConnectionStringSetting = "dbConnctionString")]out dynamic document)
{
string data = Encoding.UTF8.GetString(message.GetBytes());
document = data;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Message received. Data: '{data}'");
Console.ResetColor();
}
}
You could get answer from github Azure WebJobs SDK Extensions. If we want to insert document to the Azure documentdb, we need to insert the object into it. In your case, your output is string.
Do I need add more configuration to run it locally?
I also do demo for that. The following is the detail steps
1.Create an .net framework Webjob project.
2.Add the AzureWebJobsDocumentDBConnectionString in the App.config file.
<appSettings>
<!-- Service Bus specific app setings for messaging connections -->
<add key="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://[your namespace].servicebus.windows.net;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=[your secret]" />
<add key ="AzureWebJobsDocumentDBConnectionString" value="xxxxx"/>
</appSettings>
3.Add the following code in the Program.cs file.
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DocumentDB;
using Microsoft.Azure.WebJobs.ServiceBus;
using Microsoft.ServiceBus.Messaging;
namespace WebJobTest
{
// To learn more about Microsoft Azure WebJobs SDK, please see https://go.microsoft.com/fwlink/?LinkID=320976
class Program
{
// Please set the following connection strings in app.config for this WebJob to run:
// AzureWebJobsDashboard and AzureWebJobsStorage
private static string eventHubName = "eventhubNam";
private static string connectionString = "eventhub connectionstring";
static void Main()
{
JobHostConfiguration config = new JobHostConfiguration();
config.Tracing.ConsoleLevel = System.Diagnostics.TraceLevel.Error;
var eventHubConfig = new EventHubConfiguration();
eventHubConfig.AddReceiver(eventHubName, connectionString);
config.UseDocumentDB(new DocumentDBConfiguration
{
ConnectionString = "DocumentDB ConnectionString"
});
config.UseEventHub(eventHubConfig);
config.DashboardConnectionString = "storage connection string";
JobHost host = new JobHost(config);
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
//Send test messages
Task.Run(() =>
{
SendMessagesToEventHub();
});
host.RunAndBlock();
}
static void SendMessagesToEventHub()
{
var eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, eventHubName);
try
{
var message = Guid.NewGuid().ToString();
Console.WriteLine("{0} > Sending message: {1}", DateTime.Now, message);
eventHubClient.Send(new EventData(Encoding.UTF8.GetBytes(message)));
}
catch (Exception exception)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("{0} > Exception: {1}", DateTime.Now, exception.Message);
Console.ResetColor();
}
Thread.Sleep(200);
}
}
}
4.In the function.cs
public static void Run([EventHubTrigger("eventhub name")] EventData message, [DocumentDB("document Database name", "collection", ConnectionStringSetting = "AzureWebJobsDocumentDBConnectionString")]out Item document)
{
string data = Encoding.UTF8.GetString(message.GetBytes());
document = new Item{Text = data};
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Message received. Data: '{data}'");
Console.ResetColor();
}
public class Item
{
public string Text;
}
5.Check the result from console.
Finish debug from the console then check from the Azure documentdb

Resources