Nlog filter when condition with equals not working - asp.net-core

I have to pass the variable value from my startup class
LogManager.Configuration.Variables["environment"] = "Development";
I have added below filter in my nlog.config file
<rules>
<logger name="*" minlevel="Error" writeTo="logfile">
<filters>
<when condition="equals('${var:environment}', 'Development')" action="Ignore" />
</filters>
</logger>
</rules>
Even though I pass the value as Development, the message is still getting logged instead of ignore.
However, when I hardcoded the value it's working

You have found a bug in NLog, but it should work if you do this (Will also be faster):
<rules>
<logger name="*" minlevel="Error" writeTo="logfile">
<filters defaultAction='log'>
<when condition="'${var:environment}' == 'Development'" action="Ignore" />
</filters>
</logger>
</rules>
Notice you can also use Layout in minLevel. Ex. minLevel="${var:EnvironmentMinLevel:whenEmpty=Error}", which is much faster than <filters>.
NLog.LogManager.Configuration.Variables["EnvironmentMinLevel"] = "Off";
NLog.LogManager.ReconfigExistingLoggers();
See also https://github.com/NLog/NLog/wiki/Filtering-log-messages#semi-dynamic-routing-rules
See also: https://github.com/NLog/NLog/wiki/Environment-specific-NLog-Logging-Configuration

Related

How to omit one message processor in MUnit test?

I have a flow, in which I have an error handler which deletes an input file.
<on-error-propagate enableNotifications="true" logException="true" doc:name="On Error Propagate" doc:id="ebacee56-e127-4338-87a7-458659983dee" type="APP:UNSUPPORTED_DOCUMENT_TYPE">
<logger level="INFO" doc:name="Wrong document type" doc:id="84408377-4f4b-4115-8205-531faa8b9afd" message="#["file: " ++ attributes.fileName ++ " - skipping wrong type"]" category="correctionsImport" />
<delete doc:name="Delete inbound file" doc:id="6dc7298f-f0bc-4905-aa5d-c8972af9b225" config-ref="XMLFile" path="#[attributes.path]" />
</on-error-propagate>
I also have a MUnit test for this:
<test name="ImportCorrectionsFlowTestWithIncorrectDocumentType" doc:id="b4bd8c08-3c8d-4ac9-a4bd-a09afa43126f" description="Test" expectedErrorType="APP:UNSUPPORTED_DOCUMENT_TYPE">
<execution>
<read doc:name="POL249_C.INVOICE.CORRECTION-INCENTIVE-CREDIT-INCORRECT-DOCUMENT-TYPE.5921266020-test.xml" doc:id="b92e3cca-aacc-4259-a070-1967eceddc33" config-ref="XMLFileTest" path="corrections/incorrect/CORRECTION-INCENTIVE-CREDIT-INCORRECT-DOCUMENT-TYPE.xml" />
<flow-ref doc:name="Flow-ref to ImportCorrectionsFlow" doc:id="d3409a91-7f64-47b6-a469-e0faa39696f7" name="ImportCorrectionsFlow" />
<logger level="INFO" doc:name="Logger" doc:id="d69ee72f-ed46-4c4b-a142-7a140c0f5c64" />
</execution>
</test>
The problem is, when I run this test, the source file is deleted, and I don't want this to happen. How can I prevent deletion of the file? Can I somehow mock the file deletion flow component so it doesn't delete the file? Or can I mock the file somehow?
You should be able to mock the delete operation using the mock-when processor:
<munit:test name="ImportCorrectionsFlowTestWithIncorrectDocumentType" doc:id="b4bd8c08-3c8d-4ac9-a4bd-a09afa43126f" description="Test" expectedErrorType="APP:UNSUPPORTED_DOCUMENT_TYPE">
<munit:behavior>
<munit-tools:mock-when processor="file:delete">
<munit-tools:with-attributes>
<munit-tools:with-attribute attributeName="doc:name" whereValue="#['Delete inbound file']"/>
</munit-tools:with-attributes>
</munit-tools:mock-when>
</munit:behavior>
<munit:execution>
...
</munit:execution>
</munit:test>

Add More Logger on Mulesoft 3.9

i want to add another logger to save only request and response messages different than default logger. Default Logger i still using to save all process of my flow. Anyone have idea how to add another log? Notes: A new logger will write into the new log file not same with default.
You need to add a new file appender to the log4j2.xml and add loggers that reference it instead of the default root logger.
log4j2.xml:
<Appenders>
...
<RollingFile name="another-file" fileName="${sys:mule.home}${sys:file.separator}logs${sys:file.separator}other.log"
filePattern="${sys:mule.home}${sys:file.separator}logs${sys:file.separator}other-%i.log">
<PatternLayout pattern="%-5p %d [%t] [processor: %X{processorPath}; event: %X{correlationId}] %c: %m%n" />
<SizeBasedTriggeringPolicy size="10 MB" />
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
...
<!-- Mule set a category package only to the new appender -->
<AsyncLogger name="com.mycompany.project.module" level="INFO" additivity="false">
<AppenderRef ref="another-file" />
</AsyncLogger>
In the Mule application use the category of the loggers to determine to which file it will be sent:
<logger level="INFO" doc:name="Logger" message="default log"/>
<logger level="INFO" category="com.mycompany.project.module" doc:name="Log to second logger" message="another log" />

Parameters empty (or not supplied to CommandText) when using NLog with ASP.NET Core and SQLite

I've set up NLog in an ASP.NET Core MVC application using the examples in the documentation. Logging to a file (target=file) works without any problems.
However, logging to the Sqlite database results in an exception:
2018-10-30 20:04:41.4394 Error DatabaseTarget(Name=db): Error when
writing to database. Exception: System.InvalidOperationException: Must
add values for the following parameters: #MachineName, #Logged,
#Level, #Message, #Logger, #Callsite, #Exception at
Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior
behavior) at Microsoft.Data.Sqlite.SqliteCommand.ExecuteNonQuery()
at NLog.Targets.DatabaseTarget.WriteEventToDatabase(LogEventInfo
logEvent) at NLog.Targets.DatabaseTarget.Write(LogEventInfo
logEvent)
Any ideas why the values of these parameters are empty? Or maybe the parameters are not passed at all?
NLog configuration 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">
<targets>
<target xsi:type="File" name="file" fileName="nlog-${shortdate}.log"
layout="${longdate}|${machinename}|${level:upperCase=true}|${logger}|${callsite}|${message} ${exception:tostring}" />
<target xsi:type="Database"
name="db"
dbProvider="Microsoft.Data.Sqlite.SqliteConnection, Microsoft.Data.Sqlite"
connectionString="Data Source=database.db;">
<commandText>
INSERT INTO Log (MachineName, Logged, Level, Message, Logger, CallSite, Exception)
VALUES (#MachineName, #Logged, #Level, #Message, #Logger, #Callsite, #Exception);
</commandText>
<parameter name="#MachineName" layout="${machinename}" />
<parameter name="#Logged" layout="${longdate}" />
<parameter name="#Level" layout="${level:upperCase=true}" />
<parameter name="#Message" layout="${message}" />
<parameter name="#Logger" layout="${logger}" />
<parameter name="#CallSite" layout="${callsite}" />
<parameter name="#Exception" layout="${exception:tostring}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="file" />
<logger name="*" minlevel="Info" writeTo="db" />
</rules>
</nlog>
Unable to fix the issue using Microsoft.Data.Sqlite I switched to using System.Data.SQLite (NuGet) instead, which fixed the issue right away.
Remove the Microsoft.Data.Sqlite reference and add a reference System.Data.SQLite (1.0.109.2 at the time of writing) in your .csproj file. Update the dbProvider attribute value in nlog.config to System.Data.SQLite.SQLiteConnection, System.Data.SQLite and you're set.
nlog.config snippet:
<target xsi:type="Database"
name="db"
dbProvider="System.Data.SQLite.SQLiteConnection, System.Data.SQLite"
connectionString="Data Source=database.db;">
...
</target>

Mule ESB problems with interceptor-stack

I'm new to Mule and having trouble with using interceptor-stack elements.
The following seems like it is taken right out of their documentation here: http://www.mulesoft.org/documentation/display/33X/Using+Interceptors
<interceptor-stack name="default">
<logging-interceptor/>
<timer-interceptor/>
</interceptor-stack>
<flow name="MyFlowFlow1" doc:name="MyFlowFlow1">
<interceptor-stack ref="default"/> <!--this is line 15 -->
<logger level="INFO" message="Got here"/>
</flow>
but I get an exception saying it's invalid.
Can someone tell me what I'm doing wrong?
org.xml.sax.SAXParseException; lineNumber: 15; columnNumber: 43; cvc-complex-type.2.4.a: Invalid content was found starting with element 'interceptor-stack'. One of '{"http://www.mulesoft.org/schema/mule/core":annotations, "http://www.mulesoft.org/schema/mule/core":description, "http://www.mulesoft.org/schema/mule/core":abstract-message-source, "http://www.mulesoft.org/schema/mule/core":abstract-inbound-endpoint, "http://www.mulesoft.org/schema/mule/core":abstract-message-processor, "http://www.mulesoft.org/schema/mule/core":abstract-outbound-endpoint, "http://www.mulesoft.org/schema/mule/core":abstract-mixed-content-message-processor, "http://www.mulesoft.org/schema/mule/core":response}' is expected.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
...etc...
EDIT - This is to address the responses below.
This first private flow works perfectly when invoked from another flow via flow-ref. I see the "got here" message and the timing.
<flow name="test2Flow1" doc:name="test2Flow1">
<timer-interceptor/>
<logger level="INFO" message="got here" doc:name="Logger"/>
</flow>
However, this second private flow does not work when invoked from another flow...in fact, it won't even parse. The only difference is that the explicit use of the timer-interceptor is changed to be a reference to an interceptor-stack containing the timer-interceptor.
<interceptor-stack name="default">
<timer-interceptor/>
</interceptor-stack>
<flow name="test2Flow1" doc:name="test2Flow1">
<interceptor-stack ref="default"/>
<logger level="INFO" message="got here" doc:name="Logger"/>
</flow>
I think your flow is invalid because it doesnt have a message processor.
Take a look on the anatomy of a flow.
http://www.mulesoft.org/documentation/display/current/Using+Flows+for+Service+Orchestration#UsingFlowsforServiceOrchestration-TheAnatomyofaFlow
Your message processor must be the first item in the flow
Interceptors are meant to be used within components.
This configuration should work:
<interceptor-stack name="default">
<logging-interceptor/>
<timer-interceptor/>
</interceptor-stack>
<flow name="test2Flow1" doc:name="test2Flow1">
<pooled-component class="com.MyComponent">
<interceptor-stack ref="default"/> <!--this is line 15 -->
</pooled-component>
<logger level="INFO" message="Got here"/>
</flow>

WCF - One OperationContract sees Web.config, another doesn't

I have a WCF service with two methods, Ping and PutAddress. Ping works fine, but PutAddress was failing to initialize NHibernate correctly. Narrowing down the issue, I realized that the relevant settings from Web.config were not being read by PutAddress.
Strangely, Ping does have access to the settings from Web.config. I removed all of the NHibernate code and boiled it down to just trying to read the settings. Ping is able to read the settings (returns non-null, values in result are correct) while PutAddress' result is null.
Again, NHibernate is now completely out of the picture. Both methods simply try to read the relevant settings from Web.config. Ping succeeds while PutAddress fails.
Any thoughts?
Interface:
[ServiceContract]
public interface IMyService
{
[OperationContract]
string Ping();
[OperationContract]
Address PutAddress(Address address);
}
Implementation:
public class MyService : IMyService
{
public string Ping()
{
NHibernate.Cfg.ConfigurationSchema.HibernateConfiguration result =
(NHibernate.Cfg.ConfigurationSchema.HibernateConfiguration)
System.Configuration.ConfigurationManager.GetSection("hibernate-configuration");
if (result == null)
{
System.Diagnostics.Debugger.Break(); // Does NOT break, "Pong" returned
}
return "Pong";
}
public Address PutAddress(Address address)
{
NHibernate.Cfg.ConfigurationSchema.HibernateConfiguration result =
(NHibernate.Cfg.ConfigurationSchema.HibernateConfiguration)
System.Configuration.ConfigurationManager.GetSection("hibernate-configuration");
if (result == null)
{
System.Diagnostics.Debugger.Break(); // Breaks, result is null
}
return address; // Return version potentially modified with DB-assigned ID
}
}
EDIT:
Here is the (sanitized) Web.config
<?xml version="1.0"?>
<configuration>
<configSections>
<!-- NHibernate Section -->
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler,NHibernate"/>
<!-- Log4Net Section -->
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<!-- NHibernate Configuration -->
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="dialect">
NHibernate.Dialect.MySQLDialect
</property>
<property name="connection.provider">
NHibernate.Connection.DriverConnectionProvider
</property>
<property name="connection.driver_class">
NHibernate.Driver.MySqlDataDriver
</property>
<property name="connection.connection_string">
Server=localhost;Database=DB;User ID=USER;Password=PASS
</property>
<property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
<property name="show_sql">true</property>
<mapping assembly="MyService"/>
</session-factory>
</hibernate-configuration>
<!-- Log4Net Configuration -->
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender, log4net">
<layout type="log4net.Layout.PatternLayout, log4net">
<param name="ConversionPattern" value="%d %p %m%n"/>
</layout>
</appender>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="log.txt"/>
<param name="AppendToFile" value="true"/>
<param name="DatePattern" value="yyyy.MM.dd"/>
<layout type="log4net.Layout.PatternLayout,log4net">
<conversionPattern value="%d %p %m%n"/>
</layout>
</appender>
<root>
<priority value="DEBUG"/>
<appender-ref ref="ConsoleAppender"/>
</root>
<logger name="NHibernate" additivity="false">
<level value="WARN"/>
<appender-ref ref="RollingFile"/>
<appender-ref ref="ConsoleAppender"/>
</logger>
<logger name="NHibernate.SQL" additivity="false">
<level value="ALL"/>
<appender-ref ref="RollingFile"/>
<appender-ref ref="ConsoleAppender"/>
</logger>
</log4net>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Found the problem - one call was from a Unit Test that I hand-coded, which uses MyServiceClient that was generated by Visual Studio when I added a Service Reference. The other call was from a unit test that was created by the Visual Studio (2010) Unit Test wizard, which just instantiated MyService as an object. The VS-generated unit test was running in-process as a result.
I had an odd problem myself. I could not return "DataTable" objects from a WCF operation. I wonder if there could be a problem with returning an "Address" object from a WCF operation as well.
I don't know the complete answer to your question, but I would suggest the following
In your code for PutAddress, try replacing Address PutAddress(Address address); with string PutAddress(Address address); and replace return address; with return "Pong"
By doing so, you will ascertain the flow of execution through your code. Make sure that you are actually breaking and returning null as opposed to returning a null value of address.
If the new code returns null, then you are in fact having trouble reading from the file. I suspect that it will actually return "Pong", indicating that your code is returning Address, which somehow contains null because of WCF weirdness.