I have a strange situation:
I have configured custom log4net Appender to write to Azure Table storage. I have WorkerRole and WebRole. Both roles use osFamily=”3″ (Windows Server 2012), I use .NET 4.5 in both and use ASP.NET MVC4 for the WebRole. Everything is configured and works fine locally – both the worker and the web role are logging correctly. However, when I deploy to Azure, only Worker role logs successfully, webrole does not produce any logs (any!), while it should.
I have configured log4net on the WebRole to debug and emit log4net debugging data into the Trace to check for some issues, but it sends no errors/warnings. Nor it sends logging messages.
Here is the log produced by log4net debugging (stripped sensitive data):
log4net: log4net assembly [log4net, Version=1.2.11.0, Culture=neutral,
PublicKeyToken=669e0ddf0bb1aa2a]. Loaded from
[D:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET
Files\root\59a01799\5b6b1a2\assembly\dl3\8d97587f\b9d49402_c202ce01\log4net.dll].
(.NET Runtime [4.0.30319.18010] on Microsoft Windows NT 6.2.9200.0)
log4net: defaultRepositoryType
[log4net.Repository.Hierarchy.Hierarchy] log4net: Creating repository
for assembly [_my_referenced_assembly_, Version=1.3.0.20282,
Culture=neutral, PublicKeyToken=null] log4net: Assembly
[_my_referenced_assembly_, Version=1.3.0.20282, Culture=neutral,
PublicKeyToken=null] Loaded From
[D:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET
Files\root\59a01799\5b6b1a2\assembly\dl3\8cc98c20\594c5b41_6f07ce01_my_referenced_assembly_.dll]
log4net: Assembly [_my_referenced_assembly_, Version=1.3.0.20282,
Culture=neutral, PublicKeyToken=null] does not have a
RepositoryAttribute specified. log4net: Assembly
[_my_referenced_assembly_, Version=1.3.0.20282, Culture=neutral,
PublicKeyToken=null] using repository [log4net-default-repository] and
repository type [log4net.Repository.Hierarchy.Hierarchy] log4net:
Creating repository [log4net-default-repository] using type
[log4net.Repository.Hierarchy.Hierarchy] Loaded
“Microsoft.WindowsAzure.ServiceRuntime, Version=1.8.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35” Getting
“_some_setting_1_” from ServiceRuntime: PASS (_my_value1_). Getting
“_some_setting_2_” from ServiceRuntime: PASS (_my_value2_). Getting
“_some_setting_3_” from ServiceRuntime: PASS (_my_value3_). Getting
“Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString” from
ServiceRuntime: PASS (_my_conn_string_). Getting “_some_setting_4_”
from ServiceRuntime: PASS (_my_value4_). log4net: Creating repository
for assembly [_my_WEB_assembly_, Version=1.3.0.20283, Culture=neutral,
PublicKeyToken=null] log4net: Assembly [_my_WEB_assembly_,
Version=1.3.0.20283, Culture=neutral, PublicKeyToken=null] Loaded From
[D:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET
Files\root\59a01799\5b6b1a2\assembly\dl3\f695181f\98c73242_6f07ce01_my_WEB_assembly_.dll]
log4net: Assembly [_my_WEB_assembly_, Version=1.3.0.20283,
Culture=neutral, PublicKeyToken=null] does not have a
RepositoryAttribute specified. log4net: Assembly [_my_WEB_assembly_,
Version=1.3.0.20283, Culture=neutral, PublicKeyToken=null] using
repository [log4net-default-repository] and repository type
[log4net.Repository.Hierarchy.Hierarchy] log4net: repository
[log4net-default-repository] already exists, using repository type
[log4net.Repository.Hierarchy.Hierarchy] Getting “acs:idps” from
ServiceRuntime: FAIL. Getting “acs:idps” from ConfigurationManager:
PASS ([my_value]).
Here is sample of both my app.config (for worker) and web.config (for web role) files (I also set this into WaIISHost.config just in case, but the result is still the same – totally muted WebRole):
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
...
</configSections>
...
<log4net>
<appender name="AzureTableStoreAppender" type="_MyAssembly_.Logging.AzureTableStorageAppender, MyAssembly">
</appender>
<root>
<level value="ALL" />
<appender-ref ref="AzureTableStoreAppender" />
</root>
</log4net>
</configuration>
I configure log4net via the assembly level attribute. Thus in Worker role assembly I have:
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
And in web role I have:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Web.config", Watch = true)]
As I said, everything works fine and writes table entities fine when run locally. My Local Environemtn is Windows 8 Pro, running the web roles in IIS Server (not IIS Express), which is IIS8. I also tried marking the WebRole executionContext to elevated but still nothing happens. It is like a black hole for log4net.
My custom appender is defined in a separate Assembly, .net Framework 4.5 (full), of type Class Library which is referenced in both Web and Worker projects. As already said – locally everything works fine. The assembly that defines my custom appender is definitely loaded, because it also contains business logic of my web app, which works deployed in Azure as well.
UPDATE
Interesting discovery. When I use Debug build configuration everything works everywhere (azure web role also). But when I use Release configuration (which is default for packaging and production code) I can’t seem to be able to make log4net working anywhere. Meaning that I can’t make Log4Net running even locally with Release config. No exceptions are being raised, no errors being logged. As strange as it can be…
It turns out the
Releasebuild is causing issues. According to the log4net’s FAQ section, configuring log4net via assembly level attribute may behave different inDEBUGandRELEASEconfigurations.In my setup I was using a
static readonly property(of a base controller) initialized upon declaration. This seemed to bug the logger configuration. I moved my Logger instance to aninstance propertyof my Web Application type and changed my controller property to just return Application’s property. Now everything is working fine in all build configurations.