By default Exago saves a log file WebReportsLog.txt
to the application’s Temp path. The logger maintains a lock on the file for the lifespan of the application. The log file cannot be edited or deleted without restarting the application or releasing the lock.
Note
As of version 2018.1, the .NET API logs to the file
<Temp>WebReportsApiLog.txt
There are five configurable verbosity levels for the logger. By default, Exago logs at the Info level. Set the level by changing the Admin Console >
Important
Setting the log level to DEBUG in a production environment can have unintended performance consequences. Only use DEBUG level logging in production temporarily and under advisement from the Exago Support, Services or Development teams.
The logger can load its configuration from a file and continually watch the file for changes. A config file can be used to lock or unlock the log file, change the log file name and path, as well as customize and extend logging capability.
A custom log configuration file overrides the application’s configuration settings.
Notice
Enabling or disabling logging with
log4net
will require restarting the web server.
To use a custom log configuration:
Note
This article references
<WebApp>/
and<Sched>/
as a placeholder for the Web Application and Scheduler Service’s install location respectively. The default install location isC:Program FilesExagoExagoWeb
(/opt/Exago/
on Linux), orC:Program FilesExagoExagoScheduler
(/opt/Exago/Scheduler/
on Linux); however, these directories can be changed during installation.
log4net.config
in the <WebApp>Config
directory of the Exago Web Application, or open the <Sched>/eWebReportsScheduler.exe.config
for the Scheduler Service. The following shows a sample config file:Note
For versions pre-v2019.2.32, pre-v2020.1.15, or pre-v2021.1.3, replace
#%-3property{ThreadId}
with#%-3thread
in theconversionPattern
nodes.
<log4net> <appender name="RollingFile" type="log4net.Appender.RollingFileAppender" > <file value="WebReportsLog.txt" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date #%-3property{ThreadId} %-5level [%-8.8property{ReportId}][%-8.8property{SessionId}] - %message%newline" /> </layout> <maxSizeRollBackups value="10" /> <maximumFileSize value="1MB" /> <rollingStyle value="Size" /> </appender> <appender name="PerfRollingFile" type="log4net.Appender.RollingFileAppender" > <file value="WebReportsPerfLog.txt" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date #%-3property{ThreadId} %-5level %logger [%-8.8property{ReportId}][%-8.8property{SessionId}] - %message%newline" /> </layout> <maxSizeRollBackups value="10" /> <maximumFileSize value="1MB" /> <rollingStyle value="Size" /> </appender> <root> <level value="DEBUG" /> <appender-ref ref="RollingFile" /> </root> <!-- Set logging level to DEBUG and use logger define at the ROOT level --> <logger name="Exago Logger"> <level value="DEBUG" /> </logger> <!-- Disable Performance Logging <logger name="Perf Logger"> <level value="OFF" /> </logger> --> <!-- Enable Perf Logging in general log file --> <logger name="Perf Logger"> <level value="INFO" /> </logger> <!-- Perf logging in its own file <logger name="Perf Logger" additivity="False"> <level value="INFO" /> <appender-ref ref="PerfRollingFile" /> </logger> --> </log4net>
log4net.config
file as follows:log4net.config
fileFor full details about the log4net.config
file, refer to Apache’s official log4net documentation. Below are some common changes that can be made that apply to Exago.
The appender
sections control the log output. There can be seperate log files output for both the standard Exago application log and for performance logging. In the example two appenders are defined, one named RollingFile and the other PerfRollingFile which can be used for application and performance logging, respectively.
This node determines the location of the log file. This should be a fully qualified file path.
<file value="PathToLog.txt" />
<conversionPattern value="%date %-5level [%property{SessionId}] %message%newline" />
Configures which information is logged and the format of how it is written.
See Apache log4Net SDK Documentation – PatternLayout Class for details on how to format the conversionPattern
.
<lockingModel type="log4net.Appender.FileAppender+ExclusiveLock" />
Configures the locking model in use for the log file. To temporarily disable the write lock, you can use: log4net.Appender.FileAppender+MinimalLock
Note
This will result in a performance reduction until it is reset.
The root
and logger
nodes establish loggers that receive information from Exago and then send it to the appenders that actually write the files.
The Exago Logger is used by the main application. The Perf Logger records application performance. By default, logs will then be passed to the the root logger unless their corresponding additivity attribute is False.
In the example file, both Application logging (via the <logger
node) and Performance logging (via the
name="Exago Logger"><logger name="Perf Logger">
node) are enabled. They will capture the data then will use the <root>
logger since the additivity attribute is not specified. The <root>
logger uses the RollingFile appender
, so both the Application and Performance log data will be written to the same file.
To write the application and performance logs to different files, comment out the <logger name="Perf Logger">
node and uncomment the <logger name="Perf
node. The log level and destination appender are then further defined:
Logger" additivity="False">
Specifies the Exago logging level: OFF, ERROR, INFO, or DEBUG.
Important
Setting the log level to DEBUG in a production environment can have unintended performance consequences. Only use DEBUG level logging in production temporarily and under advisement from the Exago Support, Services or Development teams.
<level value="INFO" />
Specify the name of an appender in the ref attribute of this node.
<appender-ref ref="PerfRollingFile"
Exago uses a specific version of the log4net.dll file that is shipped with the application. When a .NET embedding application implements a different version of log4net, there can be conflicts. The solution is to add a runtime assembly binding redirect to the Exago web.config.
<dependentAssembly> <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral"/> <bindingRedirect oldVersion="1.2.11.0" newVersion="1.2.15.0" /> </dependentAssembly>
See Redirecting Assembly Versions (MSDN) for more information.
log4net does provide the ability to troubleshoot logging. Should you need to troubleshoot, add the following to Exago’s web.config file below appSettings
:
<system.diagnostics> <trace autoflush="true"> <listeners> <add name="textWriterTraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="C:tmplog4net.txt" /> </listeners> </trace> </system.diagnostics>
In addition to the above, add the following entry to the appSettings collection:
<add key=”log4net.Internal.Debug” value=”true”/>
Save the file, refresh IIS and give IIS_IUSRS full permission to the folder where logging logs are set to be stored. In the example above, that would be “C:tmp”. Then, attempt to execute Exago reports and check the logging log file to see why Exago logging is failing.
The following will describe the necessary steps to store Exago logging information in a database. The sample referenced here is configured for MS SQL Server, but log4net provides examples for other database types.
CREATE TABLE [dbo].[exagoweb] ( [id] [int] IDENTITY (1, 1) NOT NULL, [timestamp] [datetime] NOT NULL, [logger] [varchar] (255) NOT NULL, [thread] [varchar] (255) NOT NULL, [level] [varchar] (50) NOT NULL, [reportId] [varchar] (255) NOT NULL, [sessionId] [varchar] (255) NOT NULL, [message] [varchar] (4000) NOT NULL )
<?xml version="1.0" encoding="UTF-8"?> <log4net> <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender"> <bufferSize value="100" /> <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <connectionString value="database connection string" /> <commandText value="INSERT INTO exagoweblog ([timestamp],[logger],[thread],[level],[reportId],[sessionId],[message]) VALUES (@timestamp, @logger, @thread, @level, @reportId, @sessionId, @message)" /> <parameter> <parameterName value="@timestamp" /> <dbType value="DateTime" /> <layout type="log4net.Layout.RawTimeStampLayout" /> </parameter> <parameter> <parameterName value="@logger" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%logger" /> </layout> </parameter> <parameter> <parameterName value="@thread" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%-3thread" /> </layout> </parameter> <parameter> <parameterName value="@level" /> <dbType value="String" /> <size value="50" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%-5level" /> </layout> </parameter> <parameter> <parameterName value="@reportId" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%-8.8property{ReportId}" /> </layout> </parameter> <parameter> <parameterName value="@sessionId" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%-8.8property{SessionId}" /> </layout> </parameter> <parameter> <parameterName value="@message" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message" /> </layout> </parameter> </appender> <root> <level value="INFO" /> <appender-ref ref="AdoNetAppender" /> </root> </log4net>
You should no longer see information being saved to disk, and should see entries being populated in the database table instead.