• Version 1.16.0
Show / Hide Table of Contents

Dictionary Validator Sample Project

This sample demonstrates how to validate FIX messages from the summary log file by the given dictionary.

© Onix Solutions

Source code


using System;
using System.IO;
using System.Runtime.Serialization;
using NLog.Extensions.Logging;
using OnixS.Fix;

namespace DictionaryValidator
{
    [Serializable]
    public class CannotParseLogFileException : Exception
    {
        public CannotParseLogFileException(string message)
                : base(message)
        {
        }
    }

    static class DictionaryValidator
    {
        private static string GetLicenseStoreFolder()
        {
            string path = Path.Join(AppContext.BaseDirectory, "../../../../../license");

            if (Directory.Exists(path))
                return path;

            // expecting it run after dotnet publish using default paths
            return Path.Join(AppContext.BaseDirectory, "../../../../../../license");
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static int Main(string[] args)
        {
            if (0 == args.Length)
            {
                Console.WriteLine($"Usage: {nameof(DictionaryValidator)} FixLogFileToValidate.summary <DictionaryFile> [DictionaryId] \n");
                return 2;
            }

            try
            {
                var settings = new EngineSettings()
                {
                    DisableNetworkLevel = true,
                    LicenseStore = GetLicenseStoreFolder(),
                    ValidateRequiredFields = true,
                    ValidateUnknownFields = true,
                    ValidateRepeatingGroupEntryCount = true,
                    ValidateDuplicatedFields = true,
                    LoggerProvider = new NLogLoggerProvider()
                };

                if (args.Length > 1)
                {
                    settings.Dictionary = args[1];
                }

                Engine.Init(settings);

                IMessageInfoDictionary dictionary = null;

                if (args.Length > 2)
                {
                    dictionary = Engine.Instance.MessageInfoDictionaryManager[args[2]];
                }

                int numberOfProcessedMessages = ParseLogFile(args[0], dictionary);

                Console.WriteLine($"Validated {numberOfProcessedMessages} message(s)");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception: " + ex);

                return 1;
            }
            finally
            {
                // From https://github.com/NLog/NLog/wiki/Tutorial:
                // NET Application running on Mono / Linux are required to stop threads / timers before entering application shutdown phase.
                // Failing to do this will cause unhandled exceptions and segmentation faults, and other unpredictable behavior.
                NLog.LogManager.Shutdown(); // Flush and close down internal threads and timers
            }

            return 0;
        }

        static int ParseLogFile(string logFile, IMessageInfoDictionary dictionary)
        {
            int lineCounter = 0;

            using (StreamReader sr = new StreamReader(logFile))
            {
                while (-1 != sr.Peek())
                {
                    ++lineCounter;
                    string line = sr.ReadLine();

                    line = line.Trim();

                    if (0 == line.Length)
                    {
                        continue;
                    }

                    int startOfFixMsgIndex = line.IndexOf("8=FIX");

                    if (-1 == startOfFixMsgIndex)
                    {
                        throw new CannotParseLogFileException("Cannot find the start of the FIX message (8=FIX) in line # " + lineCounter
                                                            + " of " + logFile);
                    }

                    const char DelimChar = '\u0001';
                    const string CheckSumTagStr = "10";
                    const char TagValueSepChar = '=';
                    const int CheckSumValueLength = 6;

                    int startOfCheckSumTag = line.IndexOf(DelimChar+CheckSumTagStr+ TagValueSepChar, startOfFixMsgIndex, StringComparison.Ordinal);
                    if (-1 == startOfCheckSumTag)
                    {
                        throw new CannotParseLogFileException("Cannot find the checksum of the FIX message (10=***) in line # " + lineCounter
                            + " of " + logFile);
                    }

                    line = line.Substring(startOfFixMsgIndex, startOfCheckSumTag + CheckSumValueLength + 2 - startOfFixMsgIndex);

                    try
                    {
                        Message message = null;

                        if (null == dictionary)
                        {
                            message = Message.Parse(line, Engine.Instance.MessageInfoDictionaryManager);
                        }
                        else
                        {
                            message = Message.Parse(line, dictionary);
                        }

                        message.Validate();
                    }
                    catch (Exception)
                    {
                        File.WriteAllText("Failed.summary", line);

                        throw;
                    }
                }
            }

            return lineCounter;
        }
    }
}

In this article
Back to top Copyright © Onix Solutions.
Generated by DocFX