Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

log4net ADO.NET Appender works on Dev Fabric, but fails silently on Azure

I'm using log4net appender ADO.NET to log messages of Azure Worker Role to the SQL Azure instance (default diagnostics just does not fit). For some reason, while running the worker in dev fabric, logging works. Yet, when the instance is deployed to the cloud (with exactly the same config) errors do not get logged.

Configuration happens in the code using this file:

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <renderer renderingClass="{ExceptionRenderer}" renderedClass="System.Exception" />
  <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
    <layout type="log4net.Layout.PatternLayout">
      <!--<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />-->
      <conversionPattern value="%message%newline" />
    </layout>
  </appender>
  <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
    <bufferSize value="3" />
    <connectionType value="{ConnectionType}" />
    <connectionString value="{ConnectionString}" />
    <commandText value="INSERT INTO Salescast_Log ([Date],[Thread],[Version],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, '{Version}',@log_level, @logger, @message, @exception)" />
    <parameter>
      <parameterName value="@log_date" />
      <dbType value="DateTime" />
      <layout type="log4net.Layout.RawTimeStampLayout" />
    </parameter>
    <parameter>
      <parameterName value="@thread" />
      <dbType value="String" />
      <size value="255" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%thread" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@log_level" />
      <dbType value="String" />
      <size value="50" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%level" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@logger" />
      <dbType value="String" />
      <size value="255" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%logger" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@message" />
      <dbType value="String" />
      <size value="4000" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%message" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@exception" />
      <dbType value="String" />
      <size value="4000" />
      <layout type="{ExceptionLayoutType}" />
    </parameter>
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="ERROR" />
      <levelMax value="FATAL" />
    </filter>
  </appender>
  <root>
    <level value="DEBUG" />
    <appender-ref ref="TraceAppender" />
    <appender-ref ref="AdoNetAppender" />
  </root>
</log4net>

log4net is initialized with the proper values, when the Autofac IoC environment is initalized (per role startup). The code looks like this:

static ILogProvider BuildProvider(IComponentContext context)
{
  var connection = context
    .Resolve<IProvideBusSettings>()
    .GetString("SqlConnection")
    .ExposeException("Failed to get SQL string for logging");

  var xml = Properties.Resources.Logging
    .Replace("{ConnectionType}", typeof(SqlConnection).AssemblyQualifiedName)
    .Replace("{ConnectionString}", connection)
    .Replace("{ExceptionLayoutType}", typeof(LoggingTrimmedExceptionLayout).AssemblyQualifiedName)
    .Replace("{ExceptionRenderer}", typeof(LoggingExceptionRenderer).AssemblyQualifiedName)
    .Replace("{Version}", SystemDescriptor.Default.Version.ToString());

  var doc = new XmlDocument();
  doc.LoadXml(xml);
  XmlConfigurator.Configure(doc.DocumentElement);
  return new LoggingProvider();
}

Default Azure OS is used. SQL connections are obviously valid.

Could anybody, please, think of reason, why log4net logs errors from the dev fabric, but fails to do that from the azure OS, using exactly the same service configuration files?

like image 860
Rinat Abdullin Avatar asked May 18 '10 15:05

Rinat Abdullin


People also ask

What is Appender in log4net?

An appender is basically a destination that the logging information will go to.Examples of appenders are the console, a file, a database, an API call, etc. 1. Add log4net Package

How do I integrate log4net with azure Apps service?

Therefore, integrated log4net into the Azure Apps Service that consumes the ASP.NET Core Web API instead of within the API itself. Install the log4Net (add the reference) by right-clicking on the project –> Manage NuGet packages. Then search for and install the log4net binaries, as seen in Figure 1.

How to configure log4net in ASP NET Core?

Normally, configuration in ASP.NET Core is inside your appsettings.json. Configuration for log4net is still using xml as in any other platforms. Thus, you have two options – either to integrate it on your web.config file or create a new config file. In this sample, we are going to create a new config file called log4net.config:

Is it possible to store a log file locally in azure?

I think you should be careful when storing the log file locally in Azure as this is not garanteed to stick around. The VM used to store the website can be reimaged and the logs will be lost. A better solution is to use Azure diagnostics combined with log4net (would work the same for other logging mechanisms such as NLog).


1 Answers

I just ran into this and spent the better part of the day trying to figure it out. It came down to the fact that SQL Azure requires clustered indexes on your tables. The example SQL code provided by log4net to create the Log table does not have a clustered index, which is a requirement for SQL Azure. Adding any data at all to the table will fail unless it has a clustered index (as of the time this is written).

Try doing a manual insert statement using SQL Server Management Studio while connected to SQL Azure and it will tell you straight away if this is the problem. If so, run the following SQL to add a clustered index on the table (assuming you used the SQL direct from log4net) and then try again.

CREATE UNIQUE CLUSTERED INDEX PK_Log ON [Log]
  ([Id])
GO
like image 51
Mike Taber Avatar answered Oct 02 '22 11:10

Mike Taber