Azure Functions - TimerTrigger - Error when ran locally - azure

I have an issue when I start Azure Functions project locally. I am using AzureFunctions v1 (.Net Framework). The error I get is following:
This is my local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"AzureWebJobsDashboard": "UseDevelopmentStorage=true",
"StorageConnectionString": "UseDevelopmentStorage=true"
}
}
I googled the error without much luck.
What could be the couse of this error? Is it about configuration? Also, these are all TimerTrigger functions.
Thanks..
EDIT:
public class TimerPing: _BaseTrigger
{
static TimerPing()
{
Init();
}
[FunctionName("Timer_Ping")]
public static void Run([TimerTrigger("0 * * * * *", RunOnStartup = true)]TimerInfo myTimer, TraceWriter log)
{
//TryRun(() =>
//{
// ErrorHandler.InsertServiceLog(
// $"{SERVICE_NAME} - Ping",
// "ping",
// SensorType.Success);
//});
}
}
Please note that everything is commented out and this error still presists.
Also, in Output window on VS 2017 I get this:
Exception thrown: 'System.NotSupportedException' in mscorlib.dll
And I am running this locally using Azure.Functions.Cli\1.0.12

From the error screenshot you provided, The type initializer xxx in TimerPing.TimerPing(static constructor) throw an exception, so you should check the Init() method in it. Hope it helps.

Related

When deploy Azure function to Azure how did it know that it should read the AzureFunctionSettings from App settings instead of from local.setting.json

I created my first Azure Function which integrate with SharePoint Online list, using those main points:-
1-I created an Azure App with self-sign certificate to authorize my Azure function.
2-I created a new Azure Function project using Visual Studio 2019. here are the main components
-Function.cs:-
using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using PnP.Core.Services;
using PnP.Core.Model.SharePoint;
using System.Collections.Generic;
namespace FunctionApp1
{
public class Function1
{
private readonly IPnPContextFactory pnpContextFactory;
public Function1(IPnPContextFactory pnpContextFactory)
{
this.pnpContextFactory = pnpContextFactory;
}
[FunctionName("Function1")]
public void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
using (var context = pnpContextFactory.Create("Default"))
{
var myList = context.Web.Lists.GetByTitle("SubFolders");
Dictionary<string, object> values = new Dictionary<string, object>
{
{ "Title", System.DateTime.Now }
};
// Use the AddBatch method to add the request to the current batch
myList.Items.AddBatch(values);
context.Execute();
}
}
}
}
-Startup.cs:-
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using PnP.Core.Auth;
using System.Security.Cryptography.X509Certificates;
[assembly: FunctionsStartup(typeof(FunctionApp1.Startup))]
namespace FunctionApp1
{
class Startup :FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
var config = builder.GetContext().Configuration;
var azureFunctionSettings = new AzureFunctionSettings();
config.Bind(azureFunctionSettings);
builder.Services.AddPnPCore(options =>
{
options.DisableTelemetry = true;
var authProvider = new X509CertificateAuthenticationProvider(azureFunctionSettings.ClientId,
azureFunctionSettings.TenantId,
StoreName.My,
StoreLocation.CurrentUser,
azureFunctionSettings.CertificateThumbprint);
options.DefaultAuthenticationProvider = authProvider;
options.Sites.Add("Default", new PnP.Core.Services.Builder.Configuration.PnPCoreSiteOptions
{
SiteUrl = azureFunctionSettings.SiteUrl,
AuthenticationProvider = authProvider
});
});
}
}
}
-local.setting.json:-
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"SiteUrl": "https://***.sharepoint.com/",
"TenantId": "0b***",
"ClientId": "92***",
"CertificateThumbPrint": "EB***",
"WEBSITE_LOAD_CERTIFICATES": "EB***"
}
}
then i deploy it to Azure and it is working well, where each 5 minutes it adds a new list item.
But what i am unable to understand, is that when i test the function locally, the function reads its setting from the local.settings.json file, but after deploying it to Azure it start reading its settings from the online Azure App settings.. so how it did this behind the senses ?
This is by design.
App settings in a function app contain configuration options that affect all functions for that function app. When you run locally, these settings are accessed as local environment variables.
and
You can use application settings to override host.json setting values without having to change the host.json file itself. This is helpful for scenarios where you need to configure or modify specific host.json settings for a specific environment. This also lets you change host.json settings without having to republish your project.
Taken from App settings reference for Azure Functions.

Azure Durable Functions - OrchestrationTrigger stuck

I am new to azure durable functions. I have created a sample azure durable function using vs 2019. I am running default generated azure durable function template code locally with azure storage enumerator and when I run the durable function, the OrchestrationTrigger stuck and not able to resume.
The hub name is samplehubname. There a pending records present in the samplehubnameInstances azure table but there is no records in the samplehubnameHistory azure table.
There is no exception and no errors in the code.
SampleFunction.cs
public static class SampleFunction
{
[FunctionName("SampleFunction")]
public static async Task<List<string>> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var outputs = new List<string>();
// Replace "hello" with the name of your Durable Activity Function.
outputs.Add(await context.CallActivityAsync<string>("SampleFunction_Hello", "Tokyo"));
// returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
return outputs;
}
[FunctionName("SampleFunction_Hello")]
public static string SayHello([ActivityTrigger] string name, ILogger log)
{
log.LogInformation($"Saying hello to {name}.");
return $"Hello {name}!";
}
[FunctionName("SampleFunction_HttpStart")]
public static async Task<HttpResponseMessage> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log)
{
// Function input comes from the request content.
string instanceId = await starter.StartNewAsync("SampleFunction", null);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
}
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"AzureWebJobsSecretStorageType": "files", //files
"MyTaskHub": "samplehubname"
}
}
host.json
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensions": {
"durableTask": {
"hubName": "%MyTaskHub%"
}
}
}
samplehubname-control-03 Message Queue
{"$type":"DurableTask.AzureStorage.MessageData","ActivityId":"72b75a34-e403-4772-aed0-fbb10039795a","TaskMessage":{"$type":"DurableTask.Core.TaskMessage","Event":{"$type":"DurableTask.Core.History.ExecutionStartedEvent","OrchestrationInstance":{"$type":"DurableTask.Core.OrchestrationInstance","InstanceId":"f8d0499a4297480c8bdf4a56954861d3","ExecutionId":"2e46b87e4cf74c2dab572d92e012bded"},"EventType":0,"ParentInstance":null,"Name":"Function1","Version":"","Input":"null","Tags":null,"EventId":-1,"IsPlayed":false,"Timestamp":"2021-09-21T15:41:35.0156514Z"},"SequenceNumber":0,"OrchestrationInstance":{"$type":"DurableTask.Core.OrchestrationInstance","InstanceId":"f8d0499a4297480c8bdf4a56954861d3","ExecutionId":"2e46b87e4cf74c2dab572d92e012bded"}},"CompressedBlobName":null,"SequenceNumber":1,"Sender":{"$type":"DurableTask.Core.OrchestrationInstance","InstanceId":"","ExecutionId":""}}
Any help will appreciated.
If your orchestration code has contain a loop too much, the guidance in our Eternal orchestration documentation.
In your code there is not much loop available. So, you need to use the durable functions eternal orchestrations TerminateAsync (.NET) method of the orchestration client binding to stop it.
Add your durable function into application insights to check the clear view of issue. It may help to fix the issue.
Check the similar issue here.
Try the steps and use fan in/ fan out in durable function durable functions patterns fan out and fan in

Azure Functions not Sending Email or Printing Console Log

I have create a Function App at Azure Painel. Then my function project looks like this
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsDashboard": "DefaultEndpointsProtocol=...",
"AzureWebJobsStorage": "DefaultEndpointsProtocol=...",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
host.json
{
"version": "2.0",
"functionTimeout": "00:10:00",
"logging": {
"fileLoggingMode": "debugOnly",
"logLevel": {
"Function": "Trace",
"default": "Trace"
},
"console": {
"isEnabled": "true"
}
}
}
MyFunction.cs
[FunctionName("MyFunction")]
public static async Task Run([TimerTrigger("0 0 * * * *", RunOnStartup = true)]TimerInfo ti, ILogger log)
{
log.LogInformation($"Timer trigger function started at: {DateTime.Now}");
var lib = new MyLibJobs();
await lib.Run();
log.LogInformation($"Timer trigger function executed at: {DateTime.Now}");
}
public async Task Run()
{
var logger = new LoggerConfiguration().WriteTo.Console().CreateLogger();
logger.Information("=== === === === === === === === === === === === === === ===");
logger.Information("shometing");
ElasticEmail.Send(...);
...
}
When I run the function, I'm able to get the first log. But after that nothing more seems to work (running locally all works). Inside MyLibJobs I have LoggerConfiguration and ElasticEmail but none of this seems to be called. No console logs or no emails been sent.
What could I be missing here?
change the code to receive ILogger in the constructor, it will print the errors. About the messages I do believe it's throwing and exception, which you also be able to catch using the provided code:
using System;
using Microsoft.Extensions.Logging;
public class MyLibJobs
{
private ILogger _log;
public MyLibJobs(ILogger log)
{
_log = _log;
}
public async Task Run()
{
_log.Information("=== === === === === === === === === === === === === === ===");
_log.Information("shometing");
try
{
ElasticEmail.Send(...);
}
catch(Exception ex)
{
_log.LogError(ex, "error when trying to send email);
throw;
}
}
}
[FunctionName("MyFunction")]
public static async Task Run([TimerTrigger("0 */1 * * * *", RunOnStartup = true)]TimerInfo ti, ILogger log)
{
log.LogInformation($"Timer trigger function started at: {DateTime.Now}");
var lib = new MyLibJobs(log);
await lib.Run();
log.LogInformation($"Timer trigger function executed at: {DateTime.Now}");
}
Update:
If you want to use EMAIL on Azure Web App, the only way is via an SMTP relay. The third party service such as SendGrid provides these type of services.
Original Answer:
Is this what you want?
This is mycode:
Function1.cs:
using System;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Serilog;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace ConsoleLogFunction
{
public static class Function1
{
public class MyLibJobs
{
public async Task Run()
{
var logger = new LoggerConfiguration().WriteTo.Console().CreateLogger();
logger.Information("=== === === === === === === === === === === === === === ===");
logger.Information("shometing");
}
}
[FunctionName("Function1")]
public static async Task Run([TimerTrigger("*/1 * * * * *")]TimerInfo myTimer, ILogger log)
{
log.LogInformation($"Timer trigger function started at: {DateTime.Now}");
var lib = new MyLibJobs();
await lib.Run();
log.LogInformation($"Timer trigger function executed at: {DateTime.Now}");
}
}
}
host.json:
{
"version": "2.0",
"functionTimeout": "00:10:00",
"logging": {
"fileLoggingMode": "debugOnly",
"logLevel": {
"Function": "Information",
"default": "Trace"
},
"console": {
"isEnabled": "true"
}
}
}
please note that you close the information level.
Okay... It seems that the main problem it wasn't with the log or email, well maybe with the log (a little), but not with the email.
Because I had the same code running on Azure WebJob (and working), I thought that it should be working in the same way with Azure Functions (which seems not). That's why my question was focused on logs and email, but the issue could be related to something else.
Indeed serilog seems to not work on Azure Functions. So it makes the Thiago Custodio answer right. I should be using Microsoft.Extensions.Logging.ILogger.
During the program steps, to trigger the email, something else should be done, where I'll explain
The program basically do the follow steps:
a. log that it started
b. download some csv data
c. write these csv data into a csv file
d. read the csv file, compare with another one and write another csv file
e. send the csv file diff to another api
f. finally send email with the summary about what was done
Doing some researches, I read that Path.GetTempPath() changes accordingly the function runs. That said I think that this could be the main the problem. I just don't know what exactly because I have never got an error, the Functions just ran like no tomorrow.
To workaround this, I decide to write my files inside "D:\home\data\temp". There I can see my files and all steps are running correctly.
I can't say that this is the write answer. But it's the one that worked for me.

How to debug EventHubTrigger locally?

I'm trying to debug an Azure Function locally. It's an EventHubTrigger.
The problem is that I need to debug the code locally because I still don't have the "real" settings.
My code currently looks like this:
public static class Notificator
{
[FunctionName("Notificator")]
public static async Task Run([EventHubTrigger("achievements")]UserAchivementNofication notification, ILogger log)
{
}
}
But when I try to debug it, I'm getting this error:
Microsoft.Azure.WebJobs.Host: Error indexing method
'Notificator.Run'. Microsoft.Azure.WebJobs.ServiceBus: No event hub
receiver named achievements.
And it's normal, because it doesn't exist.
My local.settings.json is like this:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"AzureWebJobsDashboard": "UseDevelopmentStorage=true"
}
}
How can I debug my code?
Thank you!
You need to create an EventHub on Azure so that you can test the EventHug trigger locally,
Goto local.settings.json to add some settings:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"AzureWebJobsDashboard": "UseDevelopmentStorage=true",
"EventHubConnectionString": "YourEventHubConnectionString"
}
}
Your function should be like this:
public static void Run([EventHubTrigger("EventHubName", Connection = "EventHubConnectionString")]EventData myEventHubMessage, TraceWriter log)

Why Azure function is not writing to Service Bus Topic

My function is like
[FunctionName("MyFunctionName")]
[return: ServiceBus("mytopic", Connection = "ServiceBusConnectionString")]
public static async Task<string> MyFunctionAsync([QueueTrigger("my-input-queue")] string msgIn, TraceWriter log)
{
My local.settings.json has
{
"IsEncrypted": false,
"Values": {
"ServiceBusConnectionString": "[my connection string]"
}
}
where [my connection string] is copy-pasted from a Primary Connecting String under one of the Shared access policies with a Send claim.
This just silently fails: Messages get stuck in my-input-queue and no errors are written to log streaming. However I'm 100% sure the attribute is the issue because I've deployed 100 different combinations of this to try and make it work :).
Any ideas?
Based on my test,it should work with servicebus attribute. The following is my test code.
[return: ServiceBus("topicName",Connection = "ServiceBusConnectionString", EntityType = EntityType.Topic)]
public static async Task<string>Run([QueueTrigger("queueName")]string myQueueItem, TraceWriter log)
{
...
return myQueueItem; // write to the Topic.
}
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "xxxxxx",
"AzureWebJobsDashboard": "xxxxxxxx",
"ServiceBusConnectionString": "xxxxxx"
}
}
You could get more information about Azure Service Bus output binding from this tutorial. You also could do that with follwoing way
[FunctionName("ServiceBusOutput")]
public static void Run([[QueueTrigger("queueName")]string myQueueItem,
TraceWriter log,
[ServiceBus("topicName",Connection = "ServiceBusConnectionString", EntityType = EntityType.Topic)]out string queueMessage)
{
log.Info("Azure Function Demo - Azure Service Bus Queue Topic");
queueMessage = myQueueItem;
}
You are missing the required settings for your QueueTrigger, so your function isn't triggering on new items in the queue. You should have values for AzureWebJobsStorage and AzureWebJobsDashboard, and your QueueTrigger should have a value for the Connection field.
For more information about how to wire up QueueTriggers and test locally, see this answer.

Resources