View TraceWriter.Info() logs in Azure Function without Application Insights - c#

My Azure Function app uses the TraceWriter.Info() method to write logs. Very simple to use and it used to be very simply to view:
public static void Run([TimerTrigger("0 0 22 * * *", RunOnStartup = false)]TimerInfo myTimer, TraceWriter log)
{
log.Info("My log!");
}
However, now when I go to the portal and click the "Monitor" tab, which used to show the output in a console-like window, it demands that I setup Application Insights whilst giving me an error:
I cannot click the "Configure" button to set it up. As far as I know my app specifies nothing about Application Insights, yet the error seems to suggest that it does.
My questions:
Is it possible to get the old console window back?
Failing that, why can I not configure app insights?

Is it possible to get the old console window back?
As Thomas said, I add the APPINSIGHTS_INSTRUMENTATIONKEY in Application settings of function and could reproduce your problem. So, after deleting the APPINSIGHTS_INSTRUMENTATIONKEY, you will get the old console window back.
Failing that, why can I not configure app insights?
After deleting that attribute you will configure app insight successfully. And it will generate a specific app insight for your function app.

Related

ASP.NET Core 2.2 App Service hosted on Azure returning 500 without an exception being thrown

I have developed an App Service backend hosted on Azure using ASP.NET Core 2.2.
From time to time I'm getting a 500 status but I'm not able to find out where is that 500 being generated.
I'm using application Insights and I see on Failed Requests that sometimes there are some calls to my App Service which are returning 500.
If I reproduce that same call with same values with Postman I'm not getting any 500. There are also some End Client Apps making requests to this backend. I believe it's happening to them but why I can't reproduce the same result if I'm performing the same request with same values.
I know that 500 implies "Internal Server Error" and that it is related to the Application code but I've even configured my App Service to use a Global Error handling but I never get that 500 when I'm executing the same request that I see on Application Insights.
I have set on my Configure on StartUpp class the global error handling (just to show you that I have also enabled that)
app.UseExceptionHandler(config => ExceptionHandlingSettings.ConfigureGlobalExcpetionHandling(config));
I would like to know where or how to get more information in order to find out the code generating the error/exception because I guess there is some bug in my code which throws an unhandled exception.
Here are couple of steps which you can do to understand the root cause:
1- Change stdoutLogEnabled="false" to true and then check the logs at stdoutLogFile=".\logs\stdout". The error(s) there might tell you something.
The ASP.NET Core Module stdout log often records useful error messages not found in the Application Event Log. To enable and view stdout logs:
Navigate to the Diagnose and solve problems blade in the Azure portal.
Under SELECT PROBLEM CATEGORY, select the Web App Down button.
Under Suggested Solutions > Enable Stdout Log Redirection, select the button to Open Kudu Console to edit Web.Config.
In the Kudu Diagnostic Console, open the folders to the path site > wwwroot. Scroll down to reveal the web.config file at the bottom of the list.
Click the pencil icon next to the web.config file.
Set stdoutLogEnabled to true and change the stdoutLogFile path to: \?\%home%\LogFiles\stdout.
Select Save to save the updated web.config file.
Make a request to the app.
Return to the Azure portal. Select the Advanced Tools blade in the DEVELOPMENT TOOLS area. Select the Go→ button. The Kudu console opens in a new browser tab or window.
Using the navigation bar at the top of the page, open Debug console and select CMD.
Select the LogFiles folder.
Inspect the Modified column and select the pencil icon to edit the stdout log with the latest modification date.
When the log file opens, the error is displayed.
Please make sure to remove the logging once the inspection is completed.
2 - Use Middleware for handling erroneous request like app.UseDeveloperExceptionPage();
3- You can add application Insight in your app and try to put Info logging to understand what part of your code is causing the failure.
For additional reference, please check below doc:
https://learn.microsoft.com/en-us/aspnet/core/test/troubleshoot-azure-iis?view=aspnetcore-3.0
https://learn.microsoft.com/en-us/azure/azure-monitor/app/asp-net-exceptions
Hope it helps.

What is the simplest way to run a timer-triggered Azure Function locally once?

I have a few C# Azure Functions that run on a schedule using timer triggers. I've set them up like so, where %TimerSchedule% refers to a cron expression in the app settings:
public static void Run([TimerTrigger("%TimerSchedule%")]TimerInfo myTimer, TraceWriter log)
During development, I often want to run the functions locally using Azure Functions Tools for Visual Studio + Azure Functions Core Tools. But when I hit F5 to debug the function locally it (usually) doesn't run immediately. Instead, it starts waiting for the next occurrence as per the timer schedule. So for example, if my cron expression says to run daily at 8PM, I'd have to wait until 8PM for the function to actually run on my machine.
So my question is: What is the simplest and best way to make a function run once locally?
Things I have tried or considered:
Use a more frequent timer schedule just for local development
This is OK but not perfect – you still have to wait a little bit unless it's very frequent, and if it's very frequent then the function might run multiple times. This is what I'm doing now.
Write a console app or unit test that directly calls the function's Run() method
This isn't 100% straightforward because you have to provide TimerInfo and TraceWriter arguments to Run() – and I've found surprisingly little documentation for that.
Microsoft's Strategies for testing your code in Azure Functions page is not very helpful on this topic – it only mentions timer triggers as a way to test other trigger types.
In a perfect world, I'd hit F5 and the function would immediately run once – just like developing a "normal" .NET app.
I had the same question, and used the DEBUG-flag to have the RunOnStartup only while debugging:
public static void Run(
[TimerTrigger("* 0 7 * * 1-5"
#if DEBUG
, RunOnStartup=true
#endif
)]TimerInfo myTimer, TraceWriter log)
{
You could perhaps use the RunOnStartup flag as documented here. It doesn't quite meet your brief regarding it only running once, but it should at least execute it locally once the app has started.
/// Gets or sets a value indicating whether the function should be invoked
/// immediately on startup. After the initial startup run, the function will
/// be run on schedule thereafter.
Example using attribute binding:
[TimerTrigger("%TimerSchedule%", RunOnStartup = true)]TimerInfo myTimer
From https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=windows%2Ccsharp%2Cbash#non-http-triggered-functions
Non-HTTP triggered functions
For all kinds of functions other than HTTP triggers and webhooks, you can test your functions locally by calling an administration endpoint. Calling this endpoint with an HTTP POST request on the local server triggers the function. You can optionally pass test data to the execution in the body of the POST request. This functionality is similar to the Test tab in the Azure portal.
You call the following administrator endpoint to trigger non-HTTP functions:
http://localhost:{port}/admin/functions/{function_name}
To pass test data to the administrator endpoint of a function, you must supply the data in the body of a POST request message. The message body is required to have the following JSON format:
{
"input": "<trigger_input>"
}
If you are using VS Code, use the Azure Functions extension:
Hit F5 to enter debug mode, this starts the function app.
Go to the Azure icon in the Activity bar.
Under Local Project, find the function you want to run, right click, and select "Execute Function Now".
Check out this MS quickstart guide.
Using postman should do the trick. Follow the below steps to Run or debug you Timer Trigger Locally.
1 . RUN your Project.
Open Postman and past this url http://localhost:{port}/admin/functions/{function_name}
Make sure to use a POST Method with Json body of
{
"input": ""
}
Press SEND.
You Should receive a response of 202.
I had the same question. I fixed it with a Unittest.
Indeed you need to stub out the TraceWriter and the TimerInfo.
Here some code how I did this.
TimerInfo:
public class ScheduleStub : TimerInfo
{
public ScheduleStub(TimerSchedule schedule, ScheduleStatus status, bool isPastDue = false) : base(schedule, status, isPastDue)
{
}
}
And the TraceWriter:
public class TraceWriterStub : TraceWriter
{
protected TraceLevel _level;
protected List<TraceEvent> _traces;
public TraceWriterStub(TraceLevel level) : base(level)
{
_level = level;
_traces = new List<TraceEvent>();
}
public override void Trace(TraceEvent traceEvent)
{
_traces.Add(traceEvent);
}
public List<TraceEvent> Traces => _traces;
}
Start your function with this curl command
curl --request POST -H "Content-Type:application/json" --data '{"input":""}' http://localhost:7071/admin/functions/{function_name}
The input data is required, without it the function won't be triggered.
Another approach is to trigger manually the function from Postman:
Manually run a non HTTP-triggered function.
POST /admin/functions/<function name> HTTP/1.1
Host: localhost:<port>
Content-Type: application/json
{}
For me, it looks like that on postman for a timerTrigger function called Function1:
Just add another function with HTTP trigger type within the same class, add your code, or call your Run method from that function and invoke it from your browser.
Be sure to comment/remove that function when deployed to prod, or you will have the ability to trigger the function via HTTP calls in prod.

Asp.net Core azure web app logging

I have an asp.net core deployed to azure, and I am trying to configure logging to my application using the Microsoft.Extentions.Logging interfaces.
currently my app is writing the logs to Log Files folder in the web app storage.
This seems like the right place to log my changes. However, I want to view these logs in a normal interface - downloading a text file everytime, is kinda annoying.
I have looked into application insights, and azure diagnostic logs, but none of them suggest how to work with it using the ILogger interface.
First of all you have to configure logs in your application on Azure:
There is also an option to look at the application console output:
You can also configure Storage on Azure and save logs there (you can configure that in Diagnostic logs section).
If you want to use the Log Stream in an easy way in Azure, you can do this:
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
var sourceSwitch = new SourceSwitch("DefaultSourceSwitch");
sourceSwitch.Level = SourceLevels.Information;
loggerFactory.AddTraceSource(sourceSwitch, new TextWriterTraceListener(writer: Console.Out));
}
TraceListener will ensure that your logs will go to the standard trace output.
You also need to enable stdoutLogEnabled in the web.config (set it to true).
<aspNetCore stdoutLogEnabled="true" />
If you do these two things, you will see all your logs and system logs as well in the LogStream. You can control the level yourself.
P.S. This will work only on Full .NET Framework
P.P.S. I think if you turn on logging to blob under Diagnostic logs setting in Azure, you can have it saved to blob. So everything will happen without you writing any code and manually writing to some location.

ASP.NET web application in Azure - How to log errors?

I have a web application deployed to azure but I don't know how to log errors.
For testing purposes I have this ForceError method:
public string ForceError()
{
throw new Exception("just a test exception");
return "ok";
}
Which causes and error like this:
On Azure I enabled all Diagnostic logs like this:
But the error I forced does not appear in selected storage container.
Do you know what should I do to start logging all the errors from the application?
I am afraid just throwing an exception doesn't work in Azure Web application logging.
ASP.NET applications can use the System.Diagnostics.Trace class to log information to the application diagnostics log. The four methods in example below correspond with the diagnostic log levels:
Trace.TraceError("Message"); // Write an error message
Trace.TraceWarning("Message"); // Write a warning message
Trace.TraceInformation("Message"); // Write an information message
Trace.WriteLine("Message"); // Write a verbose message
Besides the basic information for logged events, blob storage log additional information such as the instance ID, thread ID, and a more granular timestamp (tick format) in CSV.
A great article here about logging tips and tools.
See also the Reference to the official Azure Web Apps Logging Document.
On Azure Websites, best way to log would be Application Insights, you can use free version to get insights about crashes/speed/performance.
However, Application Insights is little slower if you enable everything. But if you customize it and enable only error logging, it would push all logs to your azure application insights account and you will be able to monitor/analyze it very nicely.
For more details:
https://azure.microsoft.com/en-in/documentation/articles/app-insights-api-custom-events-metrics/
Instead of automatically configuring Application Insights, I would suggest, take an empty project, setup application insights. Notice all added config files and nuget packages. There is some insight config file, except application key/signature, you can turn off everything.
Only when you want to track an exception manually, you can create TelemetryClient and call TrackException method. You can pass more details if you need.

C# SOAP with a custom URL

Okay, simple situation: I'm writing a simple console application which connects to a SOAP web service. I've imported a SOAP Service reference and as a result, my application has a default endpoint build into it's app.config file.
The web service, however, can run on multiple servers and the URL to the proper web service is passed through the commandline parameters of my application. I can read the URL, but how do I connect the web service to this custom URL?
(It should be very simple, in my opinion. It's something I'm overlooking.)
Is this using an auto-generated class deriving from SoapHttpClientProtocol? If so, just set the Url property when you create an instance of the class.
Well, .NET can provide some very useless error messages sometimes. In IIS, the service was configured to AutoDetect cookieless mode. As a result, I had to append "?AspxAutoDetectCookieSupport=1" to the URL. Although that would fix the problem, it was just easier to go to the IIS console, open the properties of the service, go to the ASP.NET tab page, click the "Edit configuration" button, to to "State Management" in the newly popped up screen and change "Cookieless mode" into something other than "AutoDetect"...
Excuse me. Dumb error. Am going to hit myself on the head a few times for this. ;-)
As Jon said, you set the Url, as in:
Namespace.ClassName nwe = new Namespace.ClassName();
nwe.Url = "http://localhost/MyURL/site.asmx";

Categories