0

I'm creating a console app which does importing of some data of different kinds. The type of data to import is specified by argument. For each type of import I created a logger and an appender with different filenames specified:

<logger name="ClientsImporter">
  <level value="INFO" />
  <appender-ref ref="ClientsImporter" />
</logger>

<logger name="PricesImporter">
  <level value="INFO" />
  <appender-ref ref="PricesImporter" />
</logger>

<appender name="ClientsImporter" type="log4net.Appender.RollingFileAppender">
  <file value="..\logs\ClientsImporter_log" />
  [...]
</appender>

<appender name="PricesImporter" type="log4net.Appender.RollingFileAppender">
  <file value="..\logs\ImbalancePricesImporter_log" />
  [...]
</appender>

<root>
  <level value="INFO" />
  <appender-ref ref="VisualStudioDebugOutput" />
  <appender-ref ref="ColoredConsoleAppender" />
</root>

In my code I have a class for each import type and this class instance of Logger created like this:

internal readonly ILog Log = LogManager.GetLogger("ClientsImporter");

The problem is that apparently log4net wants exclusive lock on all files for all appenders. Not only those used by current run of application. This is a problem because some imports can overlap witch each other (performed by different instances of same program) and then log4net throws error that it cannot get exclusive lock on log files (even those that will not be used by it).

Is there any way to tell log4net which loggers to use and ignore others?

Episodex
  • 4,479
  • 3
  • 41
  • 58

2 Answers2

1

You can set the locking on the files to MinimalLock with lockingModel:

<appender name="ClientsImporter" type="log4net.Appender.RollingFileAppender">
  <file value="..\logs\ClientsImporter_log" />
  **<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>**
  [...]
</appender>
Peter
  • 27,590
  • 8
  • 64
  • 84
  • I found this solution before, but I hoped it is possible for log4net to just not use appenders that are not used in the application. But it's true that this should workaround my problem, so if nobody finds better answer I will accept. – Episodex May 23 '14 at 11:02
  • It seems you make global loggers for each appender, I would only instantiate a logger when I need it, not before. – Peter May 23 '14 at 11:08
  • How can I do it? I put the line which is creating logger on top of the class but not in constructor. But AFAIK it's instantiating only after the class was instantiated itself? – Episodex May 23 '14 at 11:17
  • When you create the class you can give the logger name in the constructorparameters, if you know the Importer before constructing the class. – Peter May 23 '14 at 11:29
  • It's what I do. Each class is only using one logger which is defined on the top of the class (example in my question). It's not possible to instantiate more than one importer class during one program run. But it looks like log4net is checking app.config and is locking all files whether or not they are used in the code. – Episodex May 23 '14 at 12:24
1

In this answer I told the OP that log4net was usually greedy regarding its log files' creation:

the file is created as soon as the appender is initialized in the ActivateOptions() method. From what I see you need a custom FileAppender that will handle all your business rules. It would need to

- override the default ActivateOptions method to prevent file creation
- override the Append method to create a new timestamped file when a message is logged
- use data passed in the LoggingEvent class (you have some properties available on the class) to retrieve the filename; you have to determine the filename before logging.

Unless you want to benefit from behavior it already implements(impersonation for example), I'd recommend skipping inheritance from the FileAppender class and inherit directly from the TextWriterAppender class.

So I think that - unless you want to customize the behavior of the appenders - the fallback proposed by peer may be the most efficient option since it will avoid the exclusive locks on log files. You will still have logfiles that are created as soon as the configuration is parsed.

Community
  • 1
  • 1
samy
  • 14,832
  • 2
  • 54
  • 82
  • Thanks for explanation. I think I will go the way peer suggested. But I read that it won't work with RollingFileAppender. Is that true? – Episodex May 24 '14 at 21:07
  • @Episodex The RollingFileAppender calls the base method to open files, which in turns opens the file with the locking model OpenFile method, so the behavior will be applied there too. If there are problems they should not come from the RollingFileAppender ignoring the locking model, rather from some other form of interaction. Keep us posted and open another question if necessary – samy May 26 '14 at 08:02