Damian Hickey

Mostly software and .NET related. Mostly.

Questions to ask whenever set based business concerns come up in a DDD-CQRS-ES based application

One of the biggest brain speed bumps for people who come from a centralized data-model first \ RDMBS world is the issue of duplicates. "What if we have duplicate names?" "What if we have duplicate accounts?" etc. This can be of special concern in distributed systems, where your aggregate roots may be created in different places.

Before I engage in any sort of implementation, I have several business questions that must be answered first:

  1. What is the business impact of something like this happening?
  2. Under what exact circumstances / business operations could this issue occur?
  3. What are the chances of this happening? Or, how big is the window of opportunity for this to occur?
  4. Is it possible to mitigate the chances of it happening through design of the business operations?
  5. Can it be automatically detected?
  6. How quickly can it be detected after the issue occurs?
  7. Can it be compensated (fixed) after occurring?
  8. Can the compensation be automated and transparent?

99% of the time, it turns out that set based concerns, aren't.

Putting exception message into NLog's Chainsaw log4j xml output

It doesn't appear possible to get exception infomation into the chainsaw target renderer, so I got around this by extending the Log4JXmlEventLayout and butchering the xml.

Chalk this one up as a nasty hack, it's not pretty.

[Target("ChainsawExtended")]
public class ChainsawExtendedTarget : ChainsawTarget
{
    private readonly Log4JXmlEventLayoutExtended _layout = new Log4JXmlEventLayoutExtended();

    public override Layout Layout
    {
        get { return _layout; }
        set { }
    }

    private class Log4JXmlEventLayoutExtended : Log4JXmlEventLayout
    {
        protected override string GetFormattedMessage(LogEventInfo logEvent)
        {
            string s = base.GetFormattedMessage(logEvent);
            if(logEvent.Exception == null)
            {
                return s;
            }
            s = s.Replace("<log4j:event", "<log4j:event xmlns:log4j=\"http://nlog-project.org/dummynamespace/\"");
            var element = XDocument.Parse(s);
            var messageElement = element.Descendants().Where(e => e.Name.LocalName == "message").Single();
            messageElement.Value += Environment.NewLine + logEvent.Exception;
            s = element.ToString();
            s = s.Replace(" xmlns:log4j=\"http://nlog-project.org/dummynamespace/\"", string.Empty);
            return s;
        }
    }
}