NLog to Database (Oracle) - c#

I'm trying to use NLog to log to an Oracle database, already created the table but when I try to log something I get the exception:
ORA-00928: missing SELECT keyword
My NLog.config file is:
<?xml version="1.0" ?>
<nlog autoReload="true" throwExceptions="true" internalLogFile="${basedir}/App_Data/nlog.txt" internalLogLevel="Debug"
internalLogToConsole="true">
<targets>
<!--Useful for debugging-->
<target name="filelog" type="File" fileName="C:/App_Data/Site.log"
layout="${date}: ${message}" />
<target name="databaselog" type="Database">
<dbProvider>Oracle.DataAccess.Client</dbProvider>
<!-- database connection parameters -->
<!-- alternatively you could provide a single 'connectionstring' parameter -->
<connectionString>DATA SOURCE=database;PERSIST SECURITY INFO=True;USER ID=user;Password=password;Validate Connection=true</connectionString>
<commandText>
insert into RS_LOGTABLE ([log_user],[log_level],[log_date],[log_message]) values(#log_user,#log_level,#log_date,#log_message);
</commandText>
<parameter name="#log_user" layout="${message}"/>
<parameter name="#log_level" layout="${message}"/>
<parameter name="#log_date" layout="${date}"/>
<parameter name="#log_message" layout="${message}"/>
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="filelog" />
<logger name="*" minlevel="Trace" writeTo="databaselog" />
</rules>
</nlog>
And the exception occurs when I do this:
logger = LogManager.GetCurrentClassLogger();
logger.Debug("Teste logger");
I already tried to do the insert without the brackets and get another exception:
**ORA-00936: missing expression**

I guess it's bit late for you, but I hope my solution will be helpful for others.
I changed characters # for colons at commandText and at parameter tags I removed it completely. I don't use brackets and it started to work.
It should be correct this way:
<commandText>
insert into RS_LOGTABLE (log_user,log_level,log_date,log_message) values(:log_user,:log_level,:log_date,:log_message);
</commandText>
<parameter name="log_user" layout="${message}"/>
<parameter name="log_level" layout="${message}"/>
<parameter name="log_date" layout="${date}"/>
<parameter name="log_message" layout="${message}"/>
I tested it with dbProvider Oracle.DataAccess.Client.
Warning for others:
I had a variable named with reserved word and it throws another exception. More details are here PHP ORA-01745: invalid host/bind variable name Warning

Related

Unable to suppress Microsoft logs with NLog for API calls using HttpClient

I have implemented NLog for .NET Core 3.1 MVC web app and API projects. The nlog.config file for both of them is nearly identical. I've carefuly checked this and the only difference is the database table name and file name that they log to.
I'm successfully suppressing non-essential Microsoft logs from the API project, but am only partially able to do so for the web app. Specifically, Trace and Info logs by Microsoft that deal with making calls to the API using HttpClient appear in the file and database:
You can see that only one of the logs is a log that I actually wrote, and the rest are were automatically logged by Microsoft.
I'm not sure what to try here, but I've looked at the internal logs and saw nothing out of the ordinary.
I want to know how can I suppress the additional Microsoft logs and what's wrong with my current configuration?
NuGet packages I have installed (identical for both apps):
nlog.config of the web app project:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
throwConfigExceptions="true"
internalLogLevel="Info"
internalLogFile="c:\temp\internal-CNC_WebUI-nlog.txt">
<extensions>
<add assembly="Nlog.Extensions.Logging"/>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<targets>
<target xsi:type="File" name="CNC_WebUIFile" fileName="c:\temp\nlog-CNC_WebUIFile-${shortdate}.log"
layout="${aspnet-traceidentifier}|${configsetting:AppSettings.NlogConnection.AppName}|${event-properties:ObjectID}|${date}|${uppercase:${level}}|${message} ${exception:format=tostring}|${logger}|${callsite:filename=false}|${exception:toString}" />
<target name="databaseLogger" xsi:type="Database"
dbProvider="sqlserver"
dbHost="${configsetting:AppSettings.NlogConnection.DbHost}"
dbDatabase="${configsetting:AppSettings.NlogConnection.Database}"
dbUserName="${configsetting:AppSettings.NlogConnection.User}"
dbPassword="${configsetting:AppSettings.NlogConnection.Password}" >
<commandText>
INSERT INTO dbo.CNC_WebUILogs (
CorrelationId, Application, ObjectID, Logged, Level, Message,
Logger, CallSite, Exception
) VALUES (
#CorrelationId, #Application, #ObjectID, #Logged, #Level, #Message,
#Logger, #Callsite, #Exception
);
</commandText>
<parameter name="#correlationId" layout="${aspnet-traceidentifier}" />
<parameter name="#application" layout="${configsetting:AppSettings.NlogConnection.AppName}" />
<parameter name="#ObjectID" layout="${event-properties:ObjectID}" />
<parameter name="#logged" layout="${date}" />
<parameter name="#level" layout="${level}" />
<parameter name="#message" layout="${message}" />
<parameter name="#logger" layout="${logger}" />
<parameter name="#callSite" layout="${callsite:filename=false}" />
<parameter name="#exception" layout="${exception:toString}" />
</target>
</targets>
<rules>
<logger name="Microsoft.*" levels="Warn,Error,Fatal" writeTo="databaseLogger,CNC_WebUIFile"></logger>
<logger name="Microsoft.*" minlevel="Trace" final="true" />
<logger name="*" minlevel="Trace" writeTo="CNC_WebUIFile" />
<logger name="*" minlevel="${configsetting:AppSettings.NlogConnection.LogLevel}" writeTo="databaseLogger" />
</rules>
</nlog>
One of my repos that had their API call activity logged by Microsoft:
public class MfgrRepo : IMfgrRepo
{
private readonly IHttpClientFactory _clientFactory;
public MfgrRepo(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public async Task<List<MfgrDto>> Get()
{
HttpClient client = _clientFactory.CreateClient(HttpClientConfigNames.CNC);
List<MfgrDto> models = new List<MfgrDto>();
try
{
HttpResponseMessage response = await client.GetAsync("api/Mfgrs");
models.AddRange(await response.Content.ReadFromJsonAsync<List<MfgrDto>>());
}
catch (Exception ex)
{
throw ex;
}
return models;
}
}
You can configure the log levels that the M.E.Logging system uses through the appsettings.json file. This also allows you to configure the types per namespace, so you can make the System.Net.Http namespace silent that way:
{
"Logging": {
"LogLevel": {
"System.Net.Http": "Warning"
}
}
}
You already have one blackhole here:
<rules>
<logger name="Microsoft.*" levels="Warn,Error,Fatal" writeTo="databaseLogger,CNC_WebUIFile"></logger>
<logger name="Microsoft.*" minlevel="Trace" final="true" /> <!-- Black Hole -->
<logger name="*" minlevel="Trace" writeTo="CNC_WebUIFile" />
<logger name="*" minlevel="${configsetting:AppSettings.NlogConnection.LogLevel}" writeTo="databaseLogger" />
</rules>
I would just configure an additional "blackhole" like this:
<rules>
<logger name="Microsoft.*" maxLevel="Info" final="true" /> <!-- Black Hole 1 -->
<logger name="System.Net.Http.*" maxLevel="Info" final="true" /> <!-- Black Hole 2 -->
<logger name="*" minlevel="Trace" writeTo="CNC_WebUIFile" />
<logger name="*" minlevel="${configsetting:AppSettings.NlogConnection.LogLevel}" writeTo="databaseLogger" />
</rules>

NLog seems to be writing incorrect value in database

I'm using NLog for logging into database. It seems to me its misplacing value in columns. For instance, it writes StackTrace in Message column and Exception information in StackTrace column
Configuration:
<nlog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwConfigExceptions="true" throwExceptions="true">
<targets>
<target name="database" type="Database" connectionString="Data Source=Server1;initial catalog=MyDb;Integrated Security=True;">
<commandText>insert into dbo.AppException ([Level], Logger, Message, Exception, StackTrace) values (#Level, #Logger, #Message, #Exception, #StackTrace);</commandText>
<parameter name="#Level" layout="${level}" />
<parameter name="#Logger" layout="${logger}" />
<parameter name="#Message" layout="${message}" />
<parameter name="#Exception" layout="${exception}" />
<parameter name="#StackTrace" layout="${stacktrace}" />
<dbProvider>System.Data.SqlClient</dbProvider>
</target>
</targets>
<rules>
<logger name="*" minlevel="Error" writeTo="database" />
</rules>
</nlog>
My test code:
throw new IOException("This is my message");
Logging code:
logger.Error(ex);
Below is a sample row in database
In my opinion, the value in "Exception" field should be written in "Message" column and value of "StackTrace" should be written into "Exception" column and finally value of "Message" should be written in "StackTrace".
Is there anything wrong in my configuration or my expectation is wrong?
I'm guessing you are logging the exception like this:
catch (Exception ex)
{
_logger.Error(ex); // ${message} will become ex.ToString(), since no message provided.
}
If you changed to this instead:
catch (Exception ex)
{
_logger.Error(ex, "Exception caught while testing");
}
And updated NLog.config to this:
<parameter name="#Exception" layout="${exception:format=tostring,data}" />
Then you will probably get what you want.
After reading answer posted by #Rolf, I found my nlog.config setting is not correct. The format setting in nlog is important
NLog Document
I changed my nlog to below and it worked as expected
<parameter name="#Message" layout="${exception:format=message}" />
<parameter name="#Exception" layout="${exception:format=type}" />
<parameter name="#StackTrace" layout="${exception:format=stacktrace}" />

NLog entries to SQL Server in .NET Core 2.2

What I want to do is to save all my logs to a table in a separate logging database, using NLog, and I can't seem to make it work.
This is my nlog config file:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Trace"
internalLogFile="c:\temp\internal-nlog.txt">
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets>
<target name="dbLogger" xsi:type="Database"
connectionStringName="LoggingConnection" commandType="StoredProcedure"
commandText="[dbo].[NLog_AddEntry_p]">
<parameter name="#machineName" layout="${machinename}" />
<parameter name="#logged" layout="${date}" />
<parameter name="#level" layout="${level}" />
<parameter name="#message" layout="${message}" />
<parameter name="#logger" layout="${logger}" />
<parameter name="#properties" layout="${all-event-properties:separator=|}" />
<parameter name="#callsite" layout="${callsite}" />
<parameter name="#exception" layout="${exception:tostring}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="dbLogger"/>
</rules>
</nlog>
I managed to make it log in a .txt file with a similar config, but it does not write to the DB. The "LoggingConnection" connection string is identical to the one I use for normal CRUD operations in the website; the difference is that is uses another DB.
So, after some digging checking the internal log file I've come up with this solution.
System.Data.SqlClient was added to the project and it need to be. Also I've added Nlog.Config Nuget package to the project as well.
I've removed the "extension" tag and I've done some tweaks to the nlog tag
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Trace" internalLogFile="c:\temp\nlog-internal.log">
I've replaced the "connectionStringName" attribute with "connectionString" and added the connection string from the appSettings.json.

NLog not writing debug messages

In my code I have some info messages like logger.Log("dwewe") and logger.Debug("ddddf").
The problem is that the Debug messages are not being written even when I debug in VS.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
throwExceptions="true"
internalLogLevel="Trace"
internalLogFile="c:\nlog-app.log"
autoReload="false"
internalLogToConsole="true">
<!--
See http://nlog-project.org/wiki/Configuration_file
for information on customizing logging rules and outputs.
-->
<targets>
<!-- file targets -->
<target name="asyncFile" xsi:type="AsyncWrapper">
<target xsi:type="File" name="f" fileName="${basedir}/Logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message} ${event-context:item=error-source} ${event-context:item=error-class} ${event-context:item=error-method} ${event-context:item=error-message} ${event-context:item=inner-error-message} ${event-context:item=stack-trace}"/>
</target>
<!-- database targets -->
<target name="database" xsi:type="Database" keepConnection="true" useTransactions="true"
dbProvider="System.Data.SqlClient"
connectionString="data source=XXXXXX.database.windows.net;initial catalog=NLog;integrated security=false;persist security info=True;User ID=XXXXr;Password=BXXXX3"
commandText="INSERT INTO Logs(EventDateTime, EventLevel, UserName, MachineName, EventMessage, ErrorSource, ErrorClass, ErrorMethod, ErrorMessage, InnerErrorMessage, StackTrace) VALUES (#EventDateTime, #EventLevel, #UserName, #MachineName, #EventMessage, #ErrorSource, #ErrorClass, #ErrorMethod, #ErrorMessage, #InnerErrorMessage, #StackTrace)">
<!-- parameters for the command -->
<parameter name="#EventDateTime" layout="${date:s}" />
<parameter name="#EventLevel" layout="${level}" />
<parameter name="#UserName" layout="${windows-identity}" />
<parameter name="#MachineName" layout="${machinename}" />
<parameter name="#EventMessage" layout="${message}" />
<parameter name="#ErrorSource" layout="${event-context:item=error-source}" />
<parameter name="#ErrorClass" layout="${event-context:item=error-class}" />
<parameter name="#ErrorMethod" layout="${event-context:item=error-method}" />
<parameter name="#ErrorMessage" layout="${event-context:item=error-message}" />
<parameter name="#InnerErrorMessage" layout="${event-context:item=inner-error-message}" />
<parameter name="#StackTrace" layout="${event-context:item=stack-trace}" />
</target>
<target name="console" xsi:type="Console" />
</targets>
<rules>
<!-- add your logging rules here -->
<logger name="*" minlevel="Info" writeTo="database" />
<logger name="*" minlevel="Error" writeTo="asyncFile" />
<logger name="*" minlevel="Trace" writeTo="console" />
</rules>
</
The reason that you are not able to get Debug is that debug is the lowest level log level
just add following tag in rules tag in nlog.config file.
<logger name="*" minlevel="Debug" writeTo="console" />
I found the problem to be related to the default appsettings.json that Visual Studio automatically adds to the project. It looks like this.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
The solution was to remove or rename this section.
{
"Logging-DISABLE": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
This allowed nlog.config to be utilized.
You are using 3 different log targets.
Database target is set to Info level, so debug messages are not going there.
File target accepts only Error messages (and higher) so there will not be any debug either.
The last target Console is the one where debug mesages should be looged to. But as I see it you didn't set layout of the message. Try to look at this documentation. It says that layout is a required field.
Also I would suggest you temporarily set additional File target and set it to accept debug messages.
For anyone else who has this issue, an answer at a similar question just saved me: https://stackoverflow.com/a/8881521/3959735
If you are using a separate NLog.config file, make sure it's set to "copy always" via its file properties. Alternatively, you can include the NLog configuration section in your main App.config.
I think I might have caused this issue for myself either by trying to copy an NLog configuration file from another project manually; or because when adding NLog to my project I got a permissions error (of which I cannot remember any specific details) – just passing on this information in case it helps anyone diagnose their own issue.
Add nlog.config file to your project
Example of my config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="logfile" xsi:type="File" fileName="${basedir}/Logs/${date:format=yyyy-MM-dd}_log.txt" />
<target name="logconsole" xsi:type="Console" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logconsole" />
<logger name="*" minlevel="Debug" writeTo="logfile" />
</rules>
</nlog>
</configuration>

Using Stored Procedure in NLog on a Database target

I am having a bit of a problem using a stored procedure instead of a SQL INSERT statement when using NLog in a C# web application. The connection string "Logger" is correctly configured in Web.config and works properly when replacing the commandText with a SQL statement. I would appreciate a hint in the right direction. In this example the stored procedure is under the "Logs" schema and it is called "LogError".
<targets>
<target xsi:type="Database"
name="dberrorlog"
connectionStringName="Logger"
keepConnection="true"
commandText="[Logs].[LogError]" >
<parameter name="#ProgName" layout="MyAppName"/>
<parameter name="#CompName" layout="${machinename}"/>
<parameter name="#LogLevel" layout="${level}"/>
<parameter name="#UserName" layout="${identity}"/>
<parameter name="#Error" layout="${exception:format=Message}"/>
<parameter name="#SourceObj" layout="${exception:format=Method}"/>
<parameter name="#StackTrace" layout="${exception:format=StackTrace}"/>
</target>
</targets>
<rules>
<logger name="*" minlevel="Error" writeTo="dberrorlog" />
</rules>
From this NLog forum post, try using the text to execute the stored procedure:
commandtext="exec AddActivityLog
#ApplicationName,
#ApplicationTime,
#Severity,
#Logger,
#SaxoID,
#EventID,
#Message,
#URL,
#URLReferrer,
#RemoteAddress,
#Callsite,
#CurrentUICulture,
#ThreadIdentity,
#WindowsIdentity,
#MachineName,
#ProcessID,
#ThreadID,
#ThreadName,
#Stacktrace,
#Exception,
#Cookie,
#FormVariables,
#QueryString,
#HTTPUserAgent"
Side note: Claus Rathje's answer wouldn't render in my browser, so I had to look a the page source to see the configuration he posted.
Note that while #JeffOgata's solution works, it's probably not the way you want to go about solving the problem.
You can do something like this instead:
commandText="AddActivityLog"
commandType="StoredProcedure"
That way you don't have to worry about properly formatting an EXEC query.

Categories

Resources