How to specify log file path with log4net.config? - asp.net-core-2.0

In my log4net.config I put
<appender name="Access" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="%envFolderPath{CommonApplicationData}\MyApp\test.txt"/>
& my code for configuration is
XmlDocument log4netConfig = new XmlDocument();
log4netConfig.Load(File.OpenRead("log4net.config"));
var repo = log4net.LogManager.CreateRepository(Assembly.GetEntryAssembly(),
typeof(log4net.Repository.Hierarchy.Hierarchy));
log4net.Config.XmlConfigurator.Configure(repo, log4netConfig["log4net"]);
but it didn't creating file at 【C:\ProgramData\MyApp】.
I also tried using
%envFolderPath{ApplicationData}
%envFolderPath{ProgramData}
Any ideas.
Thank you!

Works fine on my machine. You can try to debug it with steps:
Try to log information to some hardcoded path like C:\temp to make sure, your configuration is working fine.
Add reference to System.Configuration.ConfigurationManager to make sure all librieries are in place
Use this line to configure log4net:
XmlConfigurator.Configure(LogManager.GetRepository(Assembly.GetEntryAssembly()), new FileInfo("log4net.config"));
Make sure you have enough permission to write to Special Folders.
Create new Console Application in .net core with the same configuration, and enable internal debugging:
log4net.Util.LogLog.InternalDebugging = true;
You will see exactly what's going on. You will see what paths your application is using and you will see any errors that occurs during internal log4net configuration.

Related

Why is XML validation in a Blazor application giving different messages on localhost and as an Azure Static Web App?

edit
I made a simplified repo at https://github.com/GilShalit/XMLValidation
I am building an XML editor in Blazor WebAssembly (TargetFramework=net5.0). Part of the functionality involves validating the XML for completeness and according to a complex xsd schema with three includes.
These are the steps I follow:
build an XmlSchemaSet and add 4 schemas to it by calling the following method for each xsd:
private async Task loadSchema(string path, string nameSpace)
{
byte[] byteArrayS = await _client.GetByteArrayAsync(path);
Console.WriteLine($"{path}: {byteArrayS.Length}");
MemoryStream streamS = new MemoryStream(byteArrayS);
XmlReader xmlSchemaReader = XmlReader.Create(streamS);
schemaSet.Add(nameSpace, xmlSchemaReader);
}
Initializing an event handler with:
ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
loading the XML into an XmlDocument:
byte[] byteArrayX = Encoding.ASCII.GetBytes(await _editorTarget.GetValue());
MemoryStream streamX = new MemoryStream(byteArrayX);
XmlReader reader = XmlReader.Create(streamX);
XmlDocument document = new XmlDocument();
document.Load(reader);
validating according to the schemaSet:
document.Schemas = schemaSet;
document.Validate(eventHandler);
ssteps 3 and 4 are run inside a Try...Catch block and running locally when the XML is not well formed (missing closing tag for example), the document.Load(reader); line produces an error with a message like the following:
The 'publicationStmt1' start tag on line 9 position 11 does not match the end tag of 'publicationStmt'. Line 11, position 12.
which is great. But validating a similar situation in the application deployed to Azure produces the following error message:Xml_MessageWithErrorPosition, Xml_TagMismatchEx, 11, 12.
Schema validation errors are caught in the event handler when the line document.Validate(eventHandler); is run and a typical message is:
The element 'fileDesc' in namespace 'http://www.tei-c.org/ns/1.0' has invalid child element 'publicationStmt1' in namespace 'http://www.tei-c.org/ns/1.0'. List of possible elements expected: 'editionStmt, extent, publicationStmt' in namespace 'http://www.tei-c.org/ns/1.0'.
But when run on Azure the message is Sch_InvalidElementContentExpecting.
What could the reason for this difference in the validation results between running locally and in Azure?
I tried to disable linking by adding:
<ItemGroup>
<BlazorLinkerDescriptor Include="LinkerConfig.xml" />
</ItemGroup>
But that did not make a difference in the deployed application, and running locally with Release instead of Debug did not change anything either.
I also made sure the 4 xsd files are actually loaded when running from Azure.
It looks like Blazor does not include localised error message templates from System.Xml.Res class. My guess is Blazor strips it away when building it via your CI/CD pipeline. It's possible your dev machine and build agent have different locales.
I would suggest playing with the following project properties to try force bundling all cultures and/or loading invariant culture based on en_US:
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
<InvariantGlobalization>true</InvariantGlobalization> <!-- If the app doesn't require localization, you may configure the app to support the invariant culture -->
</PropertyGroup>
You also mentioned tweaking the linker, but according to documentation it only kicks in for Release builds (you seem to not have tried deploying debug version yet). So I would suggest to try deploy a debug build of your app just to eliminate linker completely.
You also could force-link all i18 resources:
<PropertyGroup>
<BlazorWebAssemblyI18NAssemblies>all</BlazorWebAssemblyI18NAssemblies>
</PropertyGroup>
and add System.Xml to LinkerConfig.xml so hopefully it gets served to the client without further optimisations:
<linker>
<assembly fullname="System.Xml" />
</linker>
So this was a feature not a bug...
An issue I opened on Dev community was picked up by the dotnet/runtime team and added to the GitHub issue tracker here.
It turns out exception messages are removed to save on size.
Using <UseSystemResourceKeys>false</UseSystemResourceKeys> enables exception messages and I must say I am not seeing an increase in size.

Azure App Service Application Settings Ignored, Using web.config Instead

I recently deployed an ASP.Net Web API project to our Azure App Service test slot but started receiving an error when making requests to the API endpoints. Through remote debugging, it became clear that the app was extracting my dev connection strings from the deployed web.config file.
The connection strings are supposed to come from the Application Settings we set up via the Azure Portal - and, in previous deployments, they were - but that's not the case.
Why would this happen and what can be done to ensure the correct behaviour occurs? We absolutely don't want our production database secrets being put into GIT via the web.config...
I recently experienced the same problem and fixed it:
In Azure App Services, the machine-wide web.config file is located at D:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config.
This file differs to a normal machine-wide web.config file because it has this extra element:
<system.web>
...
<compilation>
<assemblies>
<add assembly="EnvSettings, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
...
</assemblies>
</compilation>
</system.web>
The EnvSettings.dll assembly is located inside D:\Program Files\IIS\Microsoft Web Hosting Framework (unfortunately this directory is access-controlled and I can't get into it).
But EnvSettings.dll is mirrored in the GAC, so I was able to copy it from there.
Inside EnvSettings.dll is an [assembly: PreApplicationStartMethod] attribute that runs a method in EnvSettings.dll which copiesthe APPSETTING_ and database connection-string settings from Environment Variables into the .NET Framework ConfigurationManager.AppSettings and ConfigurationManager.ConnectionStrings collections.
Note this copying only happens once (during application startup), and only in the first AppDomain - so if you have other AppDomain instances in your application they won't see the updated ConfigurationManager.
Therefore, if you see that your Azure Portal configuration settings for your App Service are not being used when you dump your ConfigurationManager, then the following is likely happening:
You used <clear /> in your <compilation><assemblies> element, which stops EnvSettings.dll from being loaded at all.
In which case you need to either add back the <add assembly="EnvSettings... element from above to your own web.config, or find some other way to load it.
I don't recommend saving EnvSettings.dll locally and adding an assembly reference to your project, as EnvSettings.dll is part of the Microsoft Web Hosting Framework.
Or you have code that is clearing or resetting ConfigurationManager after EnvSettings populates it for you.
Or something else is going on that I have no idea about!
As an alternative to having EnvSettings.dll copy your settings over, another option is to copy the environment-variables over yourself - and as you control the code that does this it means you can call it whenever you need to (e.g. if you ever reset them).
Here's the code I used:
public static class AzureAppSettingsConfigurationLoader
{
public static void Apply()
{
foreach( DictionaryEntry environmentVariable in Environment.GetEnvironmentVariables() )
{
String name = (String)environmentVariable.Key;
String value = (String)environmentVariable.Value;
if( name.StartsWith( "APPSETTING_", StringComparison.OrdinalIgnoreCase ) )
{
String appSettingName = name.Substring( "APPSETTING_".Length );
ConfigurationManager.AppSettings[ appSettingName ] = value;
}
else if( name.StartsWith( "SQLAZURECONNSTR_", StringComparison.OrdinalIgnoreCase ) )
{
String csName = name.Substring( "SQLAZURECONNSTR_".Length );
ConfigurationManager.ConnectionStrings.Add( new ConnectionStringSettings( csName, value, providerName: ""System.Data.SqlClient" ) );
}
}
}
}
See my sample here: http://mvc5appsettings.azurewebsites.net/
// My web.config also has a "HERO_TEXT" key in
// that reads "Value from web.config"
string hero = ConfigurationManager.AppSettings["HERO_TEXT"];
Wiki page on App Settings for .NET:
https://github.com/projectkudu/kudu/wiki/Managing-settings-and-secrets
As already mentioned here, make sure you have that App Setting in the right slot.
As I know, the settings in Azure portal will override existing setting in Web.config. So If you want to ignore the Azure Application settings in portal and use Web.config instead. I am afraid you need to configure the settings in web.config, and remove the same key/pair in Azure portal.

log4net is unable to load the file MySql.Data from GAC

I am trying to evaluate the use of log4net for my new Windows Services platform. I was hoping to use generate logs in my MySql database.
I have the latest of MySql (6.9.4.0) and log4net.
I have a create a simple windows console application and to that added a configuration file log4net.config which has my appender information.
Added the following line of code to AssemblyInfo class
[assembly: XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
and the following in my Program class
private static readonly ILog _debugLogger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
I have both log4net and MySql.Data Gaced in GAC_MSIL and both assemblies added to assemblyBinding section of the Application.config file
When I execute the program I see no logs generated. On turning on Apaches internal logging i see the error that it failed to load the MySql.Data file
Copy MySql.Data file to bin folder and the logs are generated absolutely fine.
Any clues?
Thanks
Regards
Sid
My bad. The connection type element in the appender was missing the complete assembly name. It had MySql.Data.MySqlClient.MySqlConnection, MySql.Data
but should have had
MySql.Data.MySqlClient.MySqlConnection, MySql.Data, Version=6.9.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d
Works fine.

log4j produces no output on specific Weblogic servers

We are distributing an application that is deployed as a bunch of WAR files in various WebLogic servers (9, 10 and 11) at various customers' sites. Those apps are using commons-logging and log4j. It works perfectly everywhere except at a specific site where no logs are generated from our app. That site is on 11g and has a bunch of other Oracle software installed (BPEL, OSB etc)
In our code, we use:
public class Foo {
private final static Log log = LogFactory.getLog(Foo.class);
public void bar () {
log.trace("bar called");
...
Since we want to let the customers adapt their logs configuration, we have a configuration folder in the server CLASSPATH:
CLASSPATH=/opt/app/domain_foo/foo_config/:....
In that folder, two files for logs, commons-logging.properties:
org.apache.commons.logging.Log org.apache.commons.logging.impl.Log4JLogger
And log4j.properties: (this is a simplified one that has the same issue, actual file contains 5 loggers with various parameters)
log4j.rootLogger=INFO, fileApp
# File appender
log4j.appender.fileApp=org.apache.log4j.RollingFileAppender
log4j.appender.fileApp.file=fooapp.log
log4j.appender.fileApp.maxFileSize=10240KB
log4j.appender.fileApp.maxBackupIndex=5
log4j.appender.fileApp.append=true
log4j.appender.fileApp.layout=org.apache.log4j.PatternLayout
log4j.appender.fileApp.layout.ConversionPattern=%d{dd/MM/yyyy HH:mm:ss,SSS} %-5p %-70.70C %m%n
log4j.logger.be.foo=DEBUG
The file fooapp.log is created (so it was able to find the properties file) but empty.
I tried to check the log settings in Weblogic but they seem to be the same on working and not working servers.
I copied the CLASSPATH to my server and it is still working fine.
I don't really know where to look anymore. Any ideas ?
It is a bit tricky but the answer is in the environment named: APPLICATIONS_DIRECTORY that should point to the path where APPLICATIONS_DIRECTORY/fooapp.log should be. You can get the directory location from System.getenv("APPLICATIONS_DIRECTORY");

Combined Azure web role and worker role project not seeing app.config when deployed

I'm implementing the combined web/worker role scenario as described here where you simply add the following to your worker role:
public override void Run()
{
// This is a sample worker implementation. Replace with your logic.
Trace.WriteLine("WorkerRole1 entry point called", "Information");
while (true)
{
Thread.Sleep(10000);
Trace.WriteLine("Working", "Information");
}
}
The problem, as noted in the post's comments, is that this worker process cant read web.config so you have to add an app.config. It is also noted that app.config does not get deployed automatically.
So my question is how do I configure my project so app.config will get deployed?
I've added app.config to my project, set the Build Action to "Content", and "Copy always"
THIS WORKS FINE IN THE EMULATOR, but not when deployed to Azure.
Note: I noticed in the emulator a projectname.dll.config is created, but not when deployed to Azure.
I'm using VS2010, Windows Azure Tools 2011
I know some will suggest using the .cscfg file instead, but many of my components get their settings from web.config/app.config:
Elmah, Transient Fault Handling Client, Diagnostics, Email, etc...
Please read thoroughly this blog post. It explains in great details what is happening in Windows Azure Web Role with Full IIS.
What you need to do, is to add a WaIISHost.exe.config file (with copy to output = copy always). And put all the configurations you need in that file. This is because, your code (RoleEntryPoint) lives in WaIISHost.exe process, and not your pdojectName.dll process.
For me using Azure SDK 1.8 and deploying my Web Worker Role from the Visual Studio using publish, I had to include a config file, named. ProjectName.Dll.config with my settings. The configuration from app.config is not picked up by the web role when running in windows azure. And the app.config file is not converted into a ProjectName.Dll.config and added automatically to the bin folder of the deployment package, so you have to create it by hand and set it to copy always.
I'm using Azure SDK 2.0 and OS Family 3, and has been very confused about this. So I created a MVC 4.0 website with all 4 config files suggested in various answers. That is:
Web.config
App.config
WaIISHost.exe.config
[AssemblyName].dll.config
All but Web.config was set to "Copy if newer".
In the configs file I wrote:
<appSettings>
<add key="AppSettingFile" value="[NameOfConfigFile]"/>
</appSettings>
In the WebRole.cs I have the following code:
public class WebRole : RoleEntryPoint
{
public override void Run()
{
string appSetting = ConfigurationManager.AppSettings["AppSettingFile"] ?? "No config file found";
Trace.TraceInformation("Config file: " + appSetting);
while (true)
{
...
}
}
}
Result when deployed with 4 .config files:
"Config file: App.config". So App.config must be the answer, right?
Wrong! Result when deployed with only Web.config and App.config:
"Config file: No config file found". Hmm wierd.
Result when deployed with Web.config, App.config and [AssemblyName].dll.config:
"Config file: [AssemblyName].dll.config". So [AssemblyName].dll.config must be the answer, right?
Wrong! Result when deployed with only Web.config and [AssemblyName].dll.config:
"Config file: No config file found". WTF!
Result when deployed with only Web.config and WaIISHost.exe.config:
"Config file: No config file found".
Result when deployed with Web.config, App.config and WaIISHost.exe.config:
"Config file: No config file found". WTF!
So my conclusion is that you need to have 3 or 4 config files to be able to configure the Worker role of a Web project.
This is clearly a bug. Personally I think the intention from MS was to change from WaIISHost.exe.config to App.config (to align with Worker Roles and .NET in general). But App.config is only used when all 4 .config files exists.
So for now I'm having Web.config and both App.config and [AssemblyName].dll.config, and they contain exactly the same.
Hopefully going forward with Azure SDK 2.x we can use only App.config and Web.config.

Resources