I'm setting up a dll to be used as a third party dll for a different application. I want this dll to have it's own logging so the external application doesn't have to deal with setting up anything (I don't believe they use the same logging as we do). I've read that may not be the best solution but it's the task I've been given. We want to use log4net with this. I've looked at a few of the other questions on here and they mention that it is configurable via code, however, the main issue I'm having is that there is no clear cut entry point into our code to configure log4net. I'm curious if I should just abandon having the dll configure itself and have a method that is called by the secondary application that configures the dll's logging or if there is a better way to go about this. Any input would be much appreciated
You can configure log4net programmatically. Perhaps add this code to the constructor of your DLL.
if (!log4net.LogManager.GetRepository().Configured)
{
// my DLL is referenced by web service applications to log SOAP requests before
// execution is passed to the web method itself, so I load the log4net.config
// file that resides in the web application root folder
var configFileDirectory = (new DirectoryInfo(TraceExtension.AssemblyDirectory)).Parent; // not the bin folder but up one level
var configFile = new FileInfo(configFileDirectory.FullName + "\\log4net.config");
if (!configFile.Exists)
{
throw new FileLoadException(String.Format("The configuration file {0} does not exist", configFile));
}
log4net.Config.XmlConfigurator.Configure(configFile);
}
Related
Is there a mechanism (or config file setting) that will trace read operations against a .NET config file?
Background: I'm working on a SOAP test client application and there's one point where it's complaining about not finding the endpoint element and contract details in the configuration file. There are 9 services, 8 are working fine. The naming of the problem service is complicated with spelling errors (service name, wsdl port name...) I'm starting to suspect that parts of the .NET framework use convention rather than direct configuration to locating parts of the binding configuration. I think I have the name mutated correctly in the various places but when making the connection it still errors.
After all that, what would help is if I could get a trace output as the program (framework) reads through the configuration file. It would be easy at that point to see what specifically is miss-spelled or where it is my mistake.
It's almost impossible to search for this topic, all the hits along the lines of "debugging config file" return links for adding logging to a config file or configuration management of an app build.
Can any one let me know how to implement logging with Enterprise Library 6.0 in C#. I want to do logging in Database, if it is available otherwise log the exceptions , information, messages into LOG file.
Can anyone tell me How to implement logging into Db, otherwise log in file dynamically.
I will have both logging DB and file config changes in App.config/Web.config.
So please help me on this how to implement logging dynamically based on runtime value:
If Db is available and accessible, then log, otherwise if DB is not accessible, then log to Log-file or event-viewer.
The new version 6 makes comprehensive use of the factory pattern, hence you need to set the logger up differently in version 6:
Try the following:
IConfigurationSource configsrc = ConfigurationSourceFactory.Create();
LogWriterFactory logWriterFactory = new LogWriterFactory(configsrc);
Logger.SetLogWriter(logWriterFactory.Create());
Logger.Write("logtest", "General");
Your description of your database logging requirements isn't quite clear, but I think these Code examples and links should be what you are looking for.
We created an extendable project in wcf using reflection.
the web service loads different modules in run time depends on the input request.
We use .NET reflection for dynamically loading of module libraries.
The system runs on IIS.
During our tests we noticed that we couldn't replace our existing dlls once loaded via Reflection. We tried to copy our new dll into bin directory but we received an error similar ' the dll used by an application '
We can assure its only our system use that dll.
However replacing the dll could possible stopping the IIS.
But we require replacing the dll without stopping the IIS. Is there anyway we can handle this in code level ?
Appreciate your quick response.
IOrder orderImpl = null;
try
{
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\" + assemInfo.AssemblyQualifiedName + ".dll";
path = path.Replace("file:\\", "");
Assembly a = Assembly.LoadFile(path);
Type commandType = a.GetType(assemInfo.AssemblyQualifiedName + "." + assemInfo.ClassName);
orderImpl = (IOrder)commandType.GetConstructor(new System.Type[] { typeof(LocalOrderRequest) }).Invoke(new object[] { order });
}
catch (Exception ex)
{
throw new OrderImplException("-1", ex.Message);
}
Thanks
RSF
I'm going to make two assumptions from your question: 1) Uptime is critical to your app and that's why it can't be shut down for 30-seconds to update it; 2) It is not in a fault-tolerant, load-balanced farm.
If that's the case, then solving #2 will also resolve how to update the DLL with no downtime.
For an app that can't be shutdown for a few seconds to update a DLL, you should have an infrastructure that supports that needed stability. The risk of an unexpected outage is far greater than the impact of updating the app.
You should have more than one server behind a load-balancer that provides fault-tolerant routing if one of the servers goes down.
By doing this, you minimize the risk of downtime from failure and you can update the DLLs by shutting of IIS on one node, updating it, then restarting it. The load-balancing will recognize that the node is down and route traffic to the good node(s) until the updated one is again available. Repeat with the other node(s) and you've updated your app with no downtime.
You could try creating your own AppDomain and then load/unload assemblies from there. Here's an article about that: http://people.oregonstate.edu/~reeset/blog/archives/466
I am developing c# application, which is running as a windows service.
What ever transactions we are doing in the application i am writing it into log file.
A log directory is added in app.config file as below.
<add key ="LogDir" value="log" />
<add key ="LogLevel" value="2" />
And in the c# code the above one is accessing as below.
int logLevel = Convert.ToInt32(ConfigurationManager.AppSettings["logLevel"]);
if (logLevel > 0)
{
logger = new Logger();
logger.TraceLevel = logLevel - 1;
logger.logDir = ConfigurationManager.AppSettings["logDir"];
logger.logFileBaseName = "touchserver";
}
And then when any process is happening i am writing the data to the log as below.
TouchServer.Log(Logger.MessageType.Trace, 1, "Item successfully deleted");
And when i run my application in debug mode (i mean as console application) the log file will be created in the application's debug folder and the data will write into the log file.
But my problem is that when i install my application as service the log file is not getting created in the debug folder, and i am unable to see the actions performed , in case if anything went wrong.
Please help me to find a solution in this.
And i am installing service using Installutil command.
Thanks in advance
sangita
While you could get into why this is not working and fix the solution, overall there is no need to implement a logging component.
There are excellent free libraries available that do this very well. log4net is very popular. It is easy to use, feature rich and efficient. Take a look at it.
But my problem is that when i install my application as service the log file is not getting created in the debug folder, and i am unable to see the actions performed , in case if anything went wrong.
Check out what are the result of the IO operations by using Process Monitor. I suspect you'll find the identity being used to run the service process does not have write permissions where it is trying to write the log file.
But the better option is to use an existing logging library as Hemal suggests.
I have a WCF service that is hosted on a c# console application. Is there a way to restart this service, preferably by calling an endpoint in the service itself (ex. myService.Restart()).
Thanks
I have to do something similar when I perform an automatic update of a remote WCF service. In your Restart() method, close the host:
try
{
host.Description.Endpoints.Where(x => !x.Address.ToString().EndsWith("MEX")).ForEach(endpoint => _log.InfoFormat("Closing {0}", endpoint.Address));
host.Close(TimeSpan.FromSeconds(5));
}
catch (Exception)
{
host.Abort();
}
I wait for my update to apply, and then after a success or failure, I re-open the host using the same code I used to start it in the first place.
If you just wanted to restart immediately, you could just call host.Open(), or you could set up a timer to call it, etc.
try
{
host.Open();
host.Description.Endpoints.Where(x => !x.Address.ToString().EndsWith("MEX")).ForEach(endpoint => _log.InfoFormat("Host opened at: {0}", endpoint.Address));
}
catch (Exception ex)
{
_log.Error("Unable to open host.", ex);
}
To answer my question, I have solved the problem by doing the following:
Separating the code that loads the DLL files from the WCF service code into another class library project
Create an interface with the same method signatures as the ones that load DLL files in the new project (this interface is used by both projects now)
In the web service, load the other project in a new application domain. This way the DLL files are locked by the new application domain not the default.
If I want to update my nunit DLL files now, all I have to do is unload the application domain from the web service, update the files and finally create a new application domain.
AppDomain remoteDomain = AppDomain.CreateDomain("New Domain");
IClass1 class1 = (IClass1)remoteDomain.CreateInstanceFromAndUnwrap(
"Test1.dll", "Test1.Class1");
Note: IClass1 is the common interface between the projects.
you definitely are not going to be able to 'restart' a faulted service from calling that same service itself. In theory you could host 2 services in the same process. put the one you want to be 'restartable' in a public static variable and restart it within the other service. The problem would be restarting the restarter service if it faults... :) and you definitely want 'administrator-like' restrictions on your restarter service so unauthorized users can't do it.
It's a bit kludgy, but I suppose you could expose a callback on your service that the host could attach to and take appropriate action when it's triggered. That would give your host the ability to decide what a "restart" really means and how it needs to be executed. More importantly, it lets your decide whether it should do something extreme like spawn off a watcher process and then off itself or gracefully trash and reinstantiate your service (preferable).
Mmmmmm... kludge....
You cannot ask a service to restart itself. Consider a windows service (a service hosted in windows provided container) which has a RESTART functionality. Here RESTART functionality is provided not by the service but by the container. The container controls how to stop the service and start it.
Similarly in your case, you should try to look out for options if your container can provide the functionality you need. Since you want to control it remotely, the container should also be available remotely, which cannot be possible if the container is a console application. Instead it has to be another web service or web application.