The simplest example is to put the log files on a file share which you can reach more easily. Use a different file for each server though!
You can also set up log4net to log to a database. You just use a table in a database, so it could be a new table in your CMS database or a separate database. Very nice because you can use SQL to filter and order rows. You can probably find a lot of examples on the web how to set it up. Here's mine that logs to a table called Log_Log4net in my database (connection string anonymized):
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="100" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="Data Source=server;Database=database;User Id=user;Password=password" />
<commandText value="INSERT INTO Log_log4net ([Date],[Thread],[Level],[Logger],[Message],[Exception],[Server],[Application]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception, 'local', 'IOK')" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%method - %message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
It is important to log the server in a column so you know where the message came from.
You can create the same table layout using this SQL:
CREATE TABLE [dbo].[Log_log4net](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Date] [datetime] NOT NULL,
[Thread] [varchar](255) NOT NULL,
[Level] [varchar](50) NOT NULL,
[Logger] [varchar](255) NOT NULL,
[Message] [varchar](4000) NOT NULL,
[Exception] [varchar](4000) NULL,
[Server] [varchar](50) NULL,
[Application] [varchar](50) NULL,
CONSTRAINT [PK_Log_log4net] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Great! Thanks Magnus! Have you experienced any cons (performance wise) using ADO logging? No locking issues?
File logging is ruled out in our case since we don't have access to the production env. So ADO has to be our choice. And then we need to wrap this up in a grid for easy searching/filtering on the edit server. Muchos gracias for the example! =)
Performance is really good. It buffers before writing to DB so it doesn't do an insert every time there's a log entry. This means you get a block of writes from one server and then a block from a different server so it's not completely in date order (you can of course sort in SQL). Haven't noticed any locking issues and I've been using it with up to 40-50 servers logging to the same database.
You should however create an sql server task or something to delete old entries from the table, log4net doesn't do that itself as far as I know.
Anyone have a working example for how to set up logging in a load-balanced environment? We have two front servers with disabled edit/admin and they currently log to a file (which we cannot reach).
Would be nice to have a log view tool on the edit server that can check the logs from the front servers.