2 Log4Net Config Within 2 Assembly Not working seperatly - c#

I have two Project
Project A and B
A is first compiled i want a basic log4net appender inside it as a A_log4net.config inside that is call in AssemblyInfo.cs with
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "A_log4net.config")]
B is compiled way later and had a custom appender and stuff configured in B_log4net.config
Who is load later and programaticly with
using (Stream stream = type.Assembly.GetManifestResourceStream(log4netConfig))
{
LogManager.ResetConfiguration();
XmlConfigurator.Configure(stream);
}
Thing is. When i use my Log in Project A the logging event are catch by Config A and B
In the same way log fire by B are catch by config A.
So what did i miss? Can i filter log in config? How to make this two config work without interacting with each other?

Related

Windows service not logging with Log4Net

I am using Log4Net v1.2.13.0 with .Net 4.5. It is logging just fine when I run my code as a console application. However, when I run it as a service I get nothing. The service is running as my login with admin permissions. When I attach to the process and step through the code in debug mode it is as if nothing in the config file has even been read. When you check the logger object none of the properties are set true, e.g. Logger.IsDebugEnabled, Logger.IsInfoEnabled etc.
Here is how I am configuring a logger instance and then retrieving the same instance.
private static readonly ILog Logger = LogManager.GetLogger(typeof(ServiceHostService));
I am setting the logging level to ALL.
Any ideas on what might be wrong?
If LogManager.GetRepository().Configured returns false, then log4net has not been initialised.
Assuming you have your config in XML, will need either a call to log4net.Config.XmlConfigurator.Configure(…) or an assembly attribute like [assembly: log4net.Config.XmlConfigurator(…)] to load the config. If it's in a separate file from the app.config, make sure that file is copied to the output.
If log4net is configured but all log levels are still disabled, check for configuration issues by looking at the results of LogManager.GetRepository().ConfigurationMessages.Cast<LogLog>().
It may help if you add your config to your question.

DLL settings from another DLL

I have a MVC project that uses foo.dll, but that foo.dll uses smu.dll so basically I never reference smu.dll within my MVC project. The problem I´m faced with is that within my MVC project I want to be able to store ssettings in web.config so that smu.dll will read.
We have tried to use both applicationsettings and appsettings without effect, when I refernce smu.dll directly from MVC or any other program it picks up the settings without a problem. Do settings for smu.dll have to go into foo.dll app.config?
EDIT
Hello again friends, and thank you for your answers.
I found out what I was doing wrong after I read the comments. In MVC there is a web.config within the Views-folder and one web.config in the root of the project. When I used sectionGroup and applicationSettings in the "Views"-web.config the config was not read by the smu.dll. I then changed the smu.dll to read appsettings instead, whereas I then put the appSettings into to "root"-web.config, then the config file was read by the dll. I hope this makes sense but I am new to this and am still learning.
Anyway, this is finally working now :)
So, you have an MVC project, and two class libraries (foo & smu) ?
MVC -> Foo (via project reference)
Foo -> Smu (via project reference)
within AppSettings of web.config, you have a setting that smu should pick up?
Shouldn't Smu just accept a param, but not care where it comes from e.g.
if Smu was a data-access class, and it needed a connection string - all it needs to allow the user to do is send it a connection string? so, you could then send that from Foo (as this class can access your config settings) ?

app.config for a class library

I cannot see a app.config file generated for a class library by the VS2008 wizard. In my research I found that in an application only one app.config exists.
Is it a bad thing to add an app.config manually to a class library or are there any other methods which will serve the purpose of an app.config in class library?
I need to store log4net config information inside the app.config file.
You generally should not add an app.config file to a class library project; it won't be used without some painful bending and twisting on your part. It doesn't hurt the library project at all - it just won't do anything at all.
Instead, you configure the application which is using your library; so the configuration information required would go there. Each application that might use your library likely will have different requirements, so this actually makes logical sense, too.
I don't know why this answer hasn't already been given:
Different callers of the same library will, in general, use different configurations. This implies that the configuration must reside in the executable application, and not in the class library.
You may create an app.config within the class library project. It will contain default configurations for items you create within the library. For instance, it will contain connection strings if you create an Entity Framework model within the class library.
However, these settings will not be used by the executable application calling the library. Instead, these settings may be copied from the library.dll.config file into the app.config or web.config of the caller, so that they may be changed to be specific to the caller, and to the environment into which the caller is deployed.
This is how it has been with .NET since Day 1.
Jon, a lot of opinion has been given that didn't correctly answer your question.
I will give MY OPINION and then tell you how to do exactly what you asked for.
I see no reason why an assembly couldn't have its own config file. Why is the first level of atomicy (is that a real word?) be at the application level? Why not at the solution level? It's an arbitrary, best-guess decision and as such, an OPINION. If you were to write a logging library and wanted to include a configuration file for it, that would be used globally, why couldn't you hook into the built-in settings functionality? We've all done it ... tried to provide "powerful" functionality to other developers. How? By making assumptions that inherently translated to restrictions. That's exactly what MS did with the settings framework, so you do have to "fool it" a little.
To directly answer your question, simply add the configuration file manually (xml) and name it to match your library and to include the "config" extension. Example:
MyDomain.Mylibrary.dll.Config
Next, use the ConfigurationManager to load the file and access settings:
string assemblyPath = new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath;
Configuration cfg = ConfigurationManager.OpenExeConfiguration(assemblyPath);
string result = cfg.AppSettings.Settings["TEST_SETTING"].Value;
Note that this fully supports the machine.config heierarchy, even though you've explicitly chosen the app config file. In other words, if the setting isn't there, it will resolve higher. Settings will also override machine.config entries.
In fact, the class library you are implementing, is retrieving information from app.config inside the application that is consuming it, so, the most correct way to implement configuration for class libraries at .net in VS is to prepare app.config in the application to configure everything it consumes, like libraries configuration.
I have worked a little with log4net, and I found that the one who prepared the application always had a section for log4net configuration inside main app.config.
This configuration for example has a log4net section.
If you want to configure your project logging using log4Net, while using a class library, There is no actual need of any config file. You can configure your log4net logger in a class and can use that class as library.
As log4net provides all the options to configure it.
Please find the code below.
public static void SetLogger(string pathName, string pattern)
{
Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
PatternLayout patternLayout = new PatternLayout();
patternLayout.ConversionPattern = pattern;
patternLayout.ActivateOptions();
RollingFileAppender roller = new RollingFileAppender();
roller.AppendToFile = false;
roller.File = pathName;
roller.Layout = patternLayout;
roller.MaxSizeRollBackups = 5;
roller.MaximumFileSize = "1GB";
roller.RollingStyle = RollingFileAppender.RollingMode.Size;
roller.StaticLogFileName = true;
roller.ActivateOptions();
hierarchy.Root.AddAppender(roller);
MemoryAppender memory = new MemoryAppender();
memory.ActivateOptions();
hierarchy.Root.AddAppender(memory);
hierarchy.Root.Level = log4net.Core.Level.Info;
hierarchy.Configured = true;
}
Now instead of calling XmlConfigurator.Configure(new FileInfo("app.config")) you can directly call SetLogger with desired path and pattern to set the logger in Global.asax application start function.
And use the below code to log the error.
public static void getLog(string className, string message)
{
log4net.ILog iLOG = LogManager.GetLogger(className);
iLOG.Error(message); // Info, Fatal, Warn, Debug
}
By using following code you need not to write a single line neither in application web.config nor inside the app.config of library.
Actually, for some rare case you could store app.config in class libraries (by adding manually) and parse it by OpenExeConfiguration.
var fileMap =
new ExeConfigurationFileMap {ExeConfigFilename =
#"C:\..somePath..\someName.config"};
System.Configuration.Configuration config =
ConfigurationManager.OpenMappedExeConfiguration(fileMap,
ConfigurationUserLevel.None);
You should really estimate the real need of this. For abstract data its not the best solution, but "Config Sections" could be very usefull!!
For example, we organised our N-Tier WCF architecture decoupled, without any metadata, simply by using Unity Container and Injection Factory based on Channel Factory T. We added externall ClassLibrary dll with just [Service Contract] Interfaces and common app.config in order to read endpoints from clientsection, and easily add/change them at one place.
You do want to add App.config to your tests class library, if you're using a tracer/logger. Otherwise nothing gets logged when you run the test through a test runner such as TestDriven.Net.
For example, I use TraceSource in my programs, but running tests doesn't log anything unless I add an App.config file with the trace/log configuration to the test class library too.
Otherwise, adding App.config to a class library doesn't do anything.
Your answer for a non manual creation of an app.config is Visual Studio Project Properties/Settings tab.
When you add a setting and save, your app.config will be created automatically.
At this point a bunch of code is generated in a {yourclasslibrary.Properties} namespace containing properties corresponding to your settings. The settings themselves will be placed in the app.config's applicationSettings settings.
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="ClassLibrary.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<ClassLibrary.Properties.Settings>
<setting name="Setting1" serializeAs="String">
<value>3</value>
</setting>
</BookOneGenerator.Properties.Settings>
</applicationSettings>
If you added an Application scoped setting called Setting1 = 3 then a property called Setting1 will be created.
These properties are becoming at compilation part of the binary and they are decorated with a DefaultSettingValueAttribute which is set to the value you specified at development time.
[ApplicationScopedSetting]
[DebuggerNonUserCode]
[DefaultSettingValue("3")]
public string Setting1
{
get
{
return (string)this["Setting1"];
}
}
Thus as in your class library code you make use of these properties if a corresponding setting doesn't exist in the runtime config file, it will fallback to use the default value. That way the application won't crash for lacking a setting entry, which is very confusing first time when you don't know how these things work.
Now, you're asking yourself how can specify our own new value in a deployed library and avoid the default setting value be used?
That will happen when we properly configure the executable's app.config. Two steps. 1. we make it aware that we will have a settings section for that class library and 2. with small modifications we paste the class library's config file in the executable config. (there's a method where you can keep the class library config file external and you just reference it from the executable's config.
So, you can have an app.config for a class library but it's useless if you don't integrate it properly with the parent application.
See here what I wrote sometime ago: link
There is no automatic addition of app.config file when you add a class library project to your solution.
To my knowledge, there is no counter indication about doing so manualy. I think this is a common usage.
About log4Net config, you don't have to put the config into app.config, you can have a dedicated conf file in your project as well as an app.config file at the same time.
this link http://logging.apache.org/log4net/release/manual/configuration.html will give you examples about both ways (section in app.config and standalone log4net conf file)
I would recommend using Properties.Settings to store values like ConnectionStrings and so on inside of the class library. This is where all the connection strings are stores in by suggestion from visual studio when you try to add a table adapter for example.
enter image description here
And then they will be accessible by using this code every where in the clas library
var cs= Properties.Settings.Default.[<name of defined setting>];

How can log4net be configured using a System.Configuration.Configuration

I have developed a library that is being consumed by an add-in architecture in another application. My library uses log4net for logging.
This works fine in testing as the location of the app.config can be resolved and log4net is configured using:
log4net.Config.XmlConfigurator.Configure();
When loaded as an add-in it isn't possible to resolve the application configuration using this method.
One option is to configure log4net using a Configuration that is passed in through the add-in architecture. The configuration that can be used is similar to the results of the following:
string asmFile = System.Reflection.Assembly.GetExecutingAssembly().Location;
System.Configuration.Configuration dllConfig = System.Configuration.ConfigurationManager.OpenExeConfiguration(asmFile);
How can the System.Configuration.Configuration be used with the log4net.Config.XmlConfigurator?
I can see the applicable ConfigurationSection from the configuration but can't see a way to easily get the ILoggerRepository or XmlElement required by XmlConfigurator.Configure().
System.Configuration.ConfigurationSection configSection = configuration.GetSection("log4net");
This is the best I've come up with to date and it doesn't seem particularly robust.
if (configuration.HasFile)
{
System.IO.FileInfo configFileInfo = new System.IO.FileInfo(configuration.FilePath);
log4net.Config.XmlConfigurator.Configure(configFileInfo);
}
I did think about using an XmlSerializer writing the configuration to an XmlDocument and then passing that XmlElement into Configure but I couldn't get the configuration to serialize.
I have no control over how they
consume it (other than the API I
publish) but need to provide a method
for them to configure it.
Our log4net wrapper is in a dll. The projects that use this logging framework just have to add the log4net configuration block in the config file of their webservices/clients.
Besides that the programs have to call this at the startup:
XmlConfigurator.Configure();

Access App.Config Settings from Class Library Called through Unit Test Project

I have the following setup:
ASP.net 3.5 Web Site Project
C# Class Library with business logic
C# Class Library for unit testing
The business logic library does all of the db access. It gets connection strings from the web.config file of the web site by accessing System.Configuration.ConfigurationManager.ConnectionStrings. When the library is called by the web site, this works fine, as the library looks for the config of the caller.
I want to be able to test my business logic through the unit testing class library. I have put an App.config file in the root of the testing class library. From what I read, when the testing library calls data access procedures that are part of the business logic library, the connection settings from the App.config file of the testing library should be accessed and used. However, when I try to run my unit tests, I am getting errors back that indicate that the testing library's App.config file (and/or its contents) is not being accessed successfully.
My retrieval of the config properties (from within the business logic library) looks like this:
public SqlConnection MainConnection {
get {
string conn = "";
try {
conn = System.Configuration.ConfigurationManager.ConnectionStrings["connString"].ConnectionString;
} catch {
// might be calling from test project. Need to reference app settings
conn = System.Configuration.ConfigurationManager.AppSettings["connString"];
}
return new SqlConnection(conn);
}
}
When this is called from the website project, it works. From within the unit test, the conn variable is never set to anything (I have also tried System.Configuration.ConfigurationSettings.AppSettings, and using instead of with the same result). What do I need to do to make the business logic class library successfully retrieve the unit test class libraries settings, when called from within the NUnit GUI?
I just found the solution here. App.config is now being used properly when running my tests through the NUnit GUI.
Apparently if you are using the NUnit GUI and add the assembly by going through Project > Add Assembly, it doesn't access the app.config. However, if you add the assembly to the NUnit project by dragging the dll from Windows Explorer into the NUnit GUI, then it will access the app.config.
Alternatively, you can add the assembly through the GUI and then go in the NUnit GUI > Project > Edit, and set the Configuration File Name to the name of the configuration file (VS will set this to name.of.your.dll.config) and set the Project Base to the \bin\Debug directory of your project (these are the extra steps that are done in the background when you drag in the assembly vs adding it manually.
I'd recommend changing the design such that your business-logic layer, instead of having the responsibility to locate configuration settings, is injected with them.
Your Web app could inject settings it reads from its Web.config file, while your unit test could inject different settings (e.g. connection string to a test database, etc.)
Just rename app.config to name.of.your.dll.config. It works for me.
Try WebConfigurationManager.OpenWebConfiguration() method
Configuration config = WebConfigurationManager.OpenWebConfiguration(#"x:\path\web.config");
KeyValueConfigurationCollection appSettings = config.AppSettings.Settings;
string connString = appSettings["connString"].Value;

Categories

Resources