ServiceStack v4 : Configuring ELMAH with NLOG? - servicestack

Hi am using ServiceStack V4 . Here i tried to configure Elmah with NLog using the below statement in the AppHost construtor.
LogManager.LogFactory = new ElmahLogFactory(new NLogFactory(), new HttpApplication());
Configured Elmah to log exceptions to XML files(In web.config file).
Whenever i get an exception in the service i can see the exception in the log file(As configured for NLog) but not in XML files(For elmah).
But if i add the below statements i can see the exception logged to XML files(As configured for elmah).
ServiceExceptionHandlers.Add((httpReq, request, exception) =>
{
HttpContext context = HttpContext.Current;
ErrorLog.GetDefault(context).Log(new Error(exception, context));
return DtoUtils.CreateErrorResponse(request, exception);
});
But the below link says we no need to add ServiceExceptionHandlers
How do we integrate elmah logging in servicestack
Can anyone please help me out in explaining where i am wrong.

This section on configuring Elmah and the Logging.Elmah UseCase for a working example of ServiceStack and Elmah configured together.
The ElmahLogFactory should be configured in your Global.asax before initializing the ServiceStack AppHost, e.g:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
var debugMessagesLog = new ConsoleLogFactory();
LogManager.LogFactory = new ElmahLogFactory(debugMessagesLog, this);
new AppHost().Init();
}
}
The constructor accepts an alternate logger to use for your Debug/Info messages as well as the instance of the HttpApplication you wish to log to which on AppStartUp is the Global instance itself, that is accessible at runtime at HttpContext.Current.ApplicationInstance.

Related

No logs when exception is thrown in bot

We have an ASP.Net Core v4 bot that we deployed to Azure. It works fine when using the testing feature in Azure. Then we deployed to MS Teams. It works find except every message is followed with another message saying "Sorry, it looks like something went wrong." That message is usually sent when an exception is thrown. I tried to go to Azure to see the logs, but it's not logging anything.
We do have logger.LogError($"Exception caught : {exception.Message}"); in in our code, and I would think that it would log it somewhere when in production. So I turned on Application Insights for the bot, but it's not logging any exceptions. I tried streaming the logs from the web server, but it doesn't log anything when an exception is thrown.
I tried watching the application logs from the "Application logs" and "Web server logs"
Here is the code that handles errors:
public AdapterWithErrorHandler(IConfiguration configuration, ILogger<BotFrameworkHttpAdapter> logger, ConversationState conversationState = null)
: base(configuration, logger)
{
OnTurnError = async (turnContext, exception) =>
{
// Log any leaked exception from the application.
logger.LogError($"Exception caught : {exception.Message}");
// Send a catch-all apology to the user.
var errorMessage = MessageFactory.Text(ErrorMsgText, ErrorMsgText, InputHints.ExpectingInput);
await turnContext.SendActivityAsync(errorMessage);
if (conversationState != null)
{
try
{
// Delete the conversationState for the current conversation to prevent the
// bot from getting stuck in a error-loop caused by being in a bad state.
// ConversationState should be thought of as similar to "cookie-state" in a Web pages.
await conversationState.DeleteAsync(turnContext);
}
catch (Exception e)
{
logger.LogError($"Exception caught on attempting to Delete ConversationState : {e.Message}");
}
}
};
}
And here is the log settings for the app service for our bot:
#JohnGardner is correct. Botframework catches all errors, so you wouldn't may not see them in the typical Azure App Service logging.
#VinodkumarG is also correct that you can see the errors generated by logger.LogError($"Exception caught : {exception.Message}"); in
Bot Management >> Build >>Open online code editor >> Output window
or
https://<yourEndpoint>.scm.azurewebsites.net/dev/wwwroot/:vs.output
You actually should be able to see this in Log Stream > Application Logs
I added this to my bot:
In testing:
In Output:
In Log Stream > Application Logs:
Our current recommended approach is to use Application Insights. You can use Sample 21.Corebot-App-Insights as a guide. The primary modifications are how it adds App Insights in its Startup.cs:
Full
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.ApplicationInsights;
using Microsoft.Bot.Builder.Integration.ApplicationInsights.Core;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.BotBuilderSamples.Bots;
using Microsoft.BotBuilderSamples.Dialogs;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.BotBuilderSamples
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// Create the credential provider to be used with the Bot Framework Adapter.
services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>();
// Add Application Insights services into service collection
services.AddApplicationInsightsTelemetry();
// Create the telemetry client.
services.AddSingleton<IBotTelemetryClient, BotTelemetryClient>();
// Add ASP middleware to store the http body mapped with bot activity key in the httpcontext.items. This will be picked by the TelemetryBotIdInitializer
services.AddTransient<TelemetrySaveBodyASPMiddleware>();
// Add telemetry initializer that will set the correlation context for all telemetry items.
services.AddSingleton<ITelemetryInitializer, OperationCorrelationTelemetryInitializer>();
// Add telemetry initializer that sets the user ID and session ID (in addition to other bot-specific properties such as activity ID)
services.AddSingleton<ITelemetryInitializer, TelemetryBotIdInitializer>();
// Create the telemetry middleware to track conversation events
services.AddSingleton<IMiddleware, TelemetryLoggerMiddleware>();
// Create the Bot Framework Adapter with error handling enabled.
services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
// Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.)
services.AddSingleton<IStorage, MemoryStorage>();
// Create the User state. (Used in this bot's Dialog implementation.)
services.AddSingleton<UserState>();
// Create the Conversation state. (Used by the Dialog system itself.)
services.AddSingleton<ConversationState>();
// The Dialog that will be run by the bot.
services.AddSingleton<MainDialog>();
// Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
services.AddTransient<IBot, DialogAndWelcomeBot<MainDialog>>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseDefaultFiles();
app.UseStaticFiles();
//app.UseHttpsRedirection();
app.UseBotApplicationInsights();
app.UseMvc();
}
}
}
Diff vs CoreBot
You may also find this blog post useful: Bot Analytics: Behind the Scenes

Adding custom property to all Application Insight traces

I want to add a custom property to all traces in Application Insights.
In Asp.Net Core I've added this code
internal class TelemetryProperties : ITelemetryInitializer
{
private IConfiguration configuration;
public TelemetryProperties(IConfiguration configuration)
{
this.configuration = configuration;
}
// TODO: Not being added to all traces.
// http://apmtips.com/blog/2014/12/01/telemetry-initializers/
public void Initialize(ITelemetry telemetry)
{
var applicationName = configuration["Application:Name"];
telemetry.Context.Properties.Add("Application", applicationName);
}
}
and in the configure method of Startup.cs I have added:
TelemetryConfiguration.Active.TelemetryInitializers.Add(new TelemetryProperties(Configuration));
The intent was to add "Application" to all traces, even ones made automatically by Application Insights, but the effect is that it is ONLY being added to my custom traces that Im calling through my code.
How do I add a property to ALL traces, even ones I do not create.
Edit: The purpose of this is that I want to have multiple APIs in the same application insights log, but I want to be able to partition when neccessary by adding a defining property such as application name.
Modifying TelemetryConfiguration.Active is not the recommended approach in Asp.Net Core apps. Can you add the telemetry initializer using the below code in ConfigureServices ?
services.AddSingleton<ITelemetryInitializer, TelemetryProperties>();
https://github.com/Microsoft/ApplicationInsights-aspnetcore/wiki/Custom-Configuration#adding-new-telemetryinitializer
Please let me know if this helps.
I used your code(without change), and at my side, all the traces(the application insights adds, I didn't use any Trackxx methods) including the exception all have the property "Application". Please see the screenshots below:
If it still occurs in your side, please provide the screenshots of the appInsights' logs.

elmah in azure webjobs

does anyone know how to setup elmah in an azure webjob ? The help section in the official website says it requires a few lines of code so this is what I have
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += Log;
...
}
private static void Log(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
if (exception != null)
{
var logger = ElmahioAPI.Create("API_KEY");
logger.Messages.Error(new Guid("LOG_ID"), exception, "An error message");
}
}
I have an api_key and a log_id but nothing is being logged. I have elmah setup in a web app and I have to enter details in the web.config, this works perfectly (logging to sql server). The official help makes no reference to any settings in an app.config so how on earth does it know where to log the information ? Also they seem to have changed it so that you can read the logs from their website but how is this even setup ? Its very confusing, can anyone help ?
I have elmah setup in a web app and I have to enter details in the web.config, this works perfectly (logging to sql server).
It seems that you have confused EMLAH and elmah.io. Here are ELMAh and elmah.io differences.
ELMAH:
Errors can be logged to a variety of destinations through ELMAH’s plugin model called error logs. Plugins for XML, SQL Server, MySQL, Elasticsearch and many more exists.
elmah.io:
elmah.io is a cloud-based error management system originally developed on top of ELMAH.
As you have said, you have an API_KEY and LOG_ID, then you could use the following code to write log in emlah.io dashboard.
[ElmahIoExceptionFilter("API_KEY", "LOG_ID")]
public class Functions
{
// This function will get triggered/executed when a new message is written
// on an Azure Queue called queue.
public static void Trigger([TimerTrigger("0 */1 * * * *")]TimerInfo myTimer, TextWriter log)
{
throw new ApplicationException("Error from webjob");
}
}
The log screen shot are as below:
For same demo about Elmah.Io, you could refer to this github.

How can I know if and when IIS was reset in the past?

I'm having some troubles in my production environment, I found some clues that can lead to an IIS reset, but I'm not sure.
How and where can I find if there was an IIS reset in the past?
Edit:
Regarding the future resets the Kevin's solutions is ok and I have successfully used it.
You could create a Global.asax file on your ASP .Net application. Then you can hook into the application start and stop events with the following methods:
public void Application_Start(object sender, EventArgs e)
{
// log iis started
}
public void Application_End(object sender, EventArgs e)
{
// log iis stopped
}
All you have to do is declare these methods in your global.asax file, ASP .Net will automatically call them when your application is started/stopped. You can then do any logging code you need inside these methods.

Custom authentication at the URL level, use ISAPI still with .NET or is there a new way?

Is there a non-IIS way of authenticating users that is not with HTML?
I know I can create my own ISAPI filter for IIS, but I want to achieve the same thing, with .NET code and not integrate it with IIS.
Is there a way to do this now, with the latest .NET, or is ISAPI still the way to go?
If you want to apply your custom authentication for all contents, an ISAPI extension is required for IIS 5/6/7.
Greg's way only works for ASP.NET content on IIS 5/6. However, if you understand the Integrated Pipeline feature of IIS 7 well, you can configure an ASP.NET HTTP module like Greg's to apply to all contents.
MSDN and IIS.net can provide me more details if you do a search further.
You can use an IHttpModule to do this type of thing, e.g.
public class AuthModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.AuthenticateRequest += OnAuthenticateRequest;
context.AuthorizeRequest += OnAuthorizeRequest;
}
private static void OnAuthenticateRequest(object sender, EventArgs e)
{
// authenticate the user here...
// (note that the sender argument is an HttpApplication instance)
}
private static void OnAuthorizeRequest(object sender, EventArgs e)
{
// ...then authorize their attempted action here, if needed
}
}

Resources