Do we really need ApplicationInsights.config file in C#.NET project? - c#

To log a piece of information like errors, information, warnings and many more we used log4NET library and logging in a local file. But our new requirement, Along with file we need to log this information into Azure Application Insights.
We are working with .NET C# Library,
Is really required ApplicationInsights.config file with .NET C# Project? If not what is the best approach to solving this problem.
Is caching applicationInsights.config instrumentKey? if yes then what will be the solution?
Scenario 1: Tried without adding ApplicationInsights.config file
Output: Log4Net logs are not adding in Azure Application Insights
Scenario 2: Tried with adding ApplicationInsights.config file
Output: Log4Net logs are coming
Scenario 3: When I add Nuget API for ApplicationInsights.Log4NetAppender, It creates log4Net section and includes AIAppender. We have separate log4Net.config and it has only File Appender. We want to use only log4Net.config and remove log4net section from App.Config file.
Output: I removed log4Net section from App.Config and added it in log4Net.config and tested but logs are not adding in Application Insights.
Scenario 4: Implemented TelemetryClient through C# code with ApplicationInsights.config logs are coming in Application Insights
TelemetryClient telemetryClient = new TelemetryClient();
telemetryClient.InstrumentKey =<Your Instrument Key>;
// To test
telemetryClient.TrackTrace("Test through code");

The configuration of Application Insights can be done by any combination of config file and code: only the one, or the other, or both of them.
If you find an ApplicationInsights.config file in your project, it was most probably created by installing one of the Application Insights (AI) Nuget packages, but you can remove it and make the same configuration by code.
To allow the mix of configuration by config file and code, the AI clients and configuration classes have GetDefault() or Active static members that give access to an object which can be used globally. For example, you can see that the Log4Net appender TelemetryClient.cs
uses the active telemetry configuration:
public TelemetryClient() : this(TelemetryConfiguration.Active)
If you check the docs for TelemetryConfiguration.Active you'll see this:
Gets the active TelemetryConfiguration instance loaded from the ApplicationInsights.config file. If the configuration file does not exist, the active configuration instance is initialized with minimum defaults needed to send telemetry to Application Insights.
NOTE: Things are a bit different depending on the platform. For example in .NET Core is more advisable to use dependency injection. Have a look under at your case under Code-base monitoring.
For example, if you have a configuration file like this:
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
<InstrumentationKey>exxxxxxe-axxf-4xx6-bxx2-7xxxxxxxxxx3</InstrumentationKey>
this would take the instrumentation key from it:
_configuration = TelemetryConfiguration.CreateDefault();
If you remove the config file, this will not fail, but you'll need to do set the instrumentation key in code:
_configuration.InstrumentationKey = "exxxxxxe-axxf-4xx6-bxx2-7xxxxxxxxxx3";
If your config file include intializers, modules or whatever, you can also configure them by code. For example:
<TelemetryInitializers>
<Add Type="...MyInitializer, ..." />
</TelemetryInitializers>
can be setup in code like this:
_configuration.TelemetryInitializers.Add(new MyInitializer(...));

Related

How to set up NLog configuration file load/reload when the app-config path is changed?

.Net applications are set up so that multiple instances of the same program will be (re)using the same application config (.exe.config - app.config in Visual Studio).
In our scenario we need to run each of the instances with their own .exe.config. This is not something that .Net is made to do "out of the box". However this nice little wrapper does the trick for us: https://stackoverflow.com/a/6151688/95008
This worked fine for us, until we realized that NLog does not seem to respect the app-config change. We are adding a config-section in the .exe.config for NLog which should make it possible each instance to log with different rules and targets to different locations.
But, it seems that NLog is not respecting the app-config changes. My guess is that it internally is not asking via the AppSettings API for its config-section, instead perhaps using code to manually look up the .exe.config and the config-section within it.
So, three alternatives it seems:
Look into NLog changing the code for this in a future release (given that this indeed is the issue). I will be posting an issue with the project for Update: Link to NLog issue.
Loading the configuration manually, either from the section of the .exe.config or from a specific nlog.config file (maybe given via a setting in the .exe.config). But, how do we do this effectively, so that any loggers created are based on the configs manually loaded?
Maybe there is another solution for this?
My guess is that it internally is not asking via the AppSettings API for its config-section, instead perhaps using code to manually look up the .exe.config and the config-section within it.
That's correct, as NLog is using the same code for the NLog's config, whether it's in web.config or in nlog.config
Reloading the config is easy in code, just do:
NLog.LogManager.Configuration = NLog.LogManager.Configuration.Reload();
and if there are loggers made before the config is reloaded,
NLog.LogManager.ReconfigExistingLoggers()

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.

Using log4net in .net windows application

We are using log4Net to log messages into files and database from our .Net 3.5 windows application.
The winforms application is deployed on to production environment and is up and running.
Before the deployment, the level node attribute value is set to "ALL".
<level value="ALL"/>
While the application is running, I need to change the level to say "ERROR" and save the xml.And then, the log4net should log only "error" type messages in the log.
How do i achieve this using log4net?
If not feasible,any other approach please?
Thanks.
By default, if you keep your log4net configuration in a separate file (as opposed to in the app.config file) you can update that file and the application will immediately change what level it logs information thanks to the XmlConfigurator in log4net.
If you'd like to update the logging level dynamically from within your application, there's a simple way of doing that thanks to the LINQ to XML capabilities from .Net 3.5+. I've written a blog post outlining how to do that here.
Using
[assembly:
log4net.Config.XmlConfigurator(Watch=true)]
may work, according to the documentation
In the application you would need to have a filewatcher on the config file, then re-run the log4net initialisation on change of config file.

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>];

external configuration file for enterprise library

If i use an external configuration file for Microsoft enterprise library for my program, then all the configuration for enterprise library must reside in the external configuration file? can i still have part of the configuration in the hosting configuration file?
If I understand you correctly you want to configure Entlib in an external file, and override some settings on your app.config?
If that's the case, check the EntLib Hands-On Labs. Particularly take a look at the configuration HOL; it shows you how to inherit configuration from a shared location, and override it.
I am using Enterprise Library 5.0
I needed to reference my enterprise library config outside the app.config.
I used the following with my own logging factory:
var configSource = new FileConfigurationSource("EntiLib.config");
var logWriterFactory = new LogWriterFactory(configSource);
var logWriter = logWriterFactory.Create();
I was able to find this solution on CodePlex
answer on code plex
Good links by Nicolas and Peter. Glad you found the hands-on labs useful. In addition, please take a look at this chapter that we wrote to explain various configuration scenarios, including:
reading configuration information from a wide range of sources.
enforcing common configuration settings across multiple applications.
sharing configuration settings between applications.
specifying a core set of configuration settings that applications can inherit.
merging configuration settings that are stored in a shared location.
creating different configurations for different deployment environments.

Categories

Resources