anchor.diff:          message
          
   type Logger() =
  -    static member Log(msg : IMessage) =
  -        log(msg)
  -
  -    static member Log(message : Result<_>) =
  -        logErrorChoice(message)
  +    static member Log(msg : IMessage) = log(msg)
  +
  +    static member Log(message : Result<_>) = logErrorChoice(message)
       
       static member Log(msg: string, keyword : MessageKeyword, level: MessageLevel) =
           logMethod(keyword, level)(String.Empty, msg, String.Empty)
       
       /// This is an general exception logging method. This should only be used in limited cases
  -    /// where there is no specific message available to log the error.    
  +    /// where there is no specific message available to log the error.
       static member Log(ex: Exception, keyword : MessageKeyword, level: MessageLevel) =
           logMethod(keyword, level)("Generic", sprintf "%s \n%s" ex.Message (exceptionPrinter ex), String.Empty)
   
       /// This is an general exception logging method. This should only be used in limited cases
  -    /// where there is no specific message available to log the error.    
  +    /// where there is no specific message available to log the error.
       static member Log(msg: string, ex: Exception, keyword : MessageKeyword, level: MessageLevel) =
           logMethod(keyword, level)("Generic", sprintf "%s \n%s" msg (exceptionPrinter ex), String.Empty)
positive.code:             | TransactionLogReadFailure(p, _) -> sprintf "Unable to read the transaction logs from the path: %s" p
              |> caseToMsg this
  
  
  // ----------------------------------------------------------------------------
  // Logging Section
  // ----------------------------------------------------------------------------
  
  [<AutoOpen; RequireQualifiedAccess>]
  module Log = 
      open System.Diagnostics
      let private logger = FlexSearch.Logging.LogService.GetLogger(false)
      
      let logNothing(a, b, c) = ()
      let logMethod (keyword, level) =
          match (keyword, level) with
          | Node, Critical -> logger.NodeCritical
          | Node, Error -> logger.NodeError
          | Node, Warning -> logger.NodeWarning      
          | Node, Info -> logger.NodeInfo
          | Node, Verbose -> logger.NodeVerbose
          | Index, Critical -> logger.IndexCritical
          | Index, Error -> logger.IndexError
          | Index, Warning -> logger.IndexWarning      
          | Index, Info -> logger.IndexInfo
          | Index, Verbose -> logger.IndexVerbose
          | Search, Critical -> logger.SearchCritical
          | Search, Error -> logger.SearchError
          | Search, Warning -> logger.SearchWarning      
          | Search, Info -> logger.SearchInfo
          | Search, Verbose -> logger.SearchVerbose
          | Document, Critical -> logger.DocumentCritical
          | Document, Error -> logger.DocumentError
          | Document, Warning -> logger.DocumentWarning      
          | Document, Info -> logger.DocumentInfo
          | Document, Verbose -> logger.DocumentVerbose
          | Default, Critical -> logger.DefaultCritical
          | Default, Error -> logger.DefaultError
          | Default, Warning -> logger.DefaultWarning      
          | Default, Info -> logger.DefaultInfo
          | Default, Verbose -> logger.DefaultVerbose
          | Plugin, Critical -> logger.PluginCritical
          | Plugin, Error -> logger.PluginError
          | Plugin, Warning -> logger.PluginWarning      
          | Plugin, Info -> logger.PluginInfo
          | Plugin, Verbose -> logger.PluginVerbose
          | _, Nothing -> logNothing 
         
      let log (message: IMessage) =
          match message.LogProperty() with
          | _, Nothing -> ()
          | keyword, level ->
              let om = message.OperationMessage()
              let properties = om.Properties |> Seq.fold (fun acc v -> acc + sprintf "%A; \r\n" v) ""
  
negative.code:     
      /// Converts any object to a pretty printed string
      let toFormattedString (x : 'a) = sprintf "%A" x
      
      let sf1 = Printf.StringFormat<string -> string>
      let sf2 = Printf.StringFormat<string -> string -> string>
      let sf3 = Printf.StringFormat<string -> string -> string -> string>
      let sf4 = Printf.StringFormat<string -> string -> string -> string -> string>
   
  open MessageHelpers
  
  [<AutoOpen>]
  module ValidationError =
      
      let private greaterThan = sf3 "Field '%s' must be greater than %s, but found %s"
      let private lessThan = sf3 "Field '%s' must be less than %s, but found %s"
      let private greaterThanEqual = sf3 "Field '%s' must be greater than or equal to %s, but found %s"
      let private lessThanEqual = sf3 "Field '%s' must be less than or equal to %s, but found %s"
      let private notBlank = sf1 "Field '%s' must not be blank"
      let private regexMatch = sf2 "Field '%s' must match Regex expression: %s"
      let private keyNotFound = sf1 "Key not found: %s"
      
      type T = 
          | GreaterThan of fieldName : string * lowerLimit : string * value : string
          | LessThan of fieldName : string * upperLimit : string * value : string
          | GreaterThanEqual of fieldName : string * lowerLimit : string * value : string
          | LessThanEqual of fieldName : string * lowerLimit : string * value : string
          | NotBlank of fieldName : string
          | RegexMatch of fieldName : string * regexExpr : string
          | KeyNotFound of key : string
          override this.ToString() = sprintf "%A" this
          interface IMessage with
              member this.LogProperty() = (MessageKeyword.Default, MessageLevel.Nothing)
              member this.OperationMessage() = 
                  match this with
                  | GreaterThan(fn, ll, v) -> sprintf greaterThan fn ll v
                  | LessThan(fn, ul, v) -> sprintf lessThan fn ul v
                  | GreaterThanEqual(fn, ll, v) -> sprintf greaterThanEqual fn ll v
                  | LessThanEqual(fn, ul, v) -> sprintf lessThanEqual fn ul v
                  | NotBlank(fn) -> sprintf notBlank fn
                  | RegexMatch(fn, re) -> sprintf regexMatch fn re
                  | KeyNotFound(key) -> sprintf keyNotFound key
                  |> caseToMsg this
  
  [<AutoOpen>]
  module AnalysisMessage =
      let private tokenizerNotFound = sf2 "Tokenizer with the name %s does not exist. Analyzer Name: %s"
      let private unableToInitializeTokenizer = sf4 "Tokenizer with the name %s cannot be initialized. Analyzer Name: %s. Error: %s. Exception: %s"
      let private filterNotFound = sf2 "Filter with the name %s does not exist. Analyzer Name: %s"
      let private unableToInitializeFilter = sf4 "Filter with the name %s cannot be initialized. Analyzer Name: %s. Error: %s. Exception: %s"
      let private analyzerBuilder = sf3 "The analyzer '%s' threw an exception while building: %s; \n%s"
      let private analyzerNotFound = sf1 "The analyzer '%s' was not found"
  
      type T = 
          | TokenizerNotFound of analyzerName : string * tokenizerName : string
          | UnableToInitializeTokenizer of analyzerName : string * tokenizerName : string * message : string * ``exception`` : string
          | FilterNotFound of analyzerName : string * filterName : string
          | UnableToInitializeFilter of analyzerName : string * filterName : string * message : string * ``exception`` : string
          | AnalyzerBuilder of analyzerName : string * message : string * ``exception`` : string
          | AnalyzerNotFound of analyzerName : string
          interface IMessage with
              member this.LogProperty() = (MessageKeyword.Node, MessageLevel.Verbose)
              member this.OperationMessage() = 
                  match this with
                  | TokenizerNotFound(an, tn) -> sprintf tokenizerNotFound tn an
                  | UnableToInitializeTokenizer(an, tn, m, exp) -> sprintf unableToInitializeTokenizer tn an m exp
                  | FilterNotFound(an, fn) -> sprintf filterNotFound fn an
                  | UnableToInitializeFilter(an, fn, m, exp) -> sprintf unableToInitializeFilter fn an m exp
                  | AnalyzerBuilder(an, m, e) -> sprintf analyzerBuilder an m e
                  | AnalyzerNotFound(a) -> sprintf analyzerNotFound a
                  |> caseToMsg this
  
  [<AutoOpen>]
  module BuilderError =
      let private invalidPropertyName = sf2 "Property name is invalid. Expected '%s' but found '%s'"
      let private analyzerIsMandatory = sf1 "Analyzer is mandatory for field '%s'"
      let private duplicateFieldValue = sf2 "A duplicate entry (%s) has been found in the group '%s'"
      let private scriptNotFound = sf2 "The script '%s' was not found against the field '%s'"
      let private resourceNotFound = sf2 "The resource '%s' of type %s was not found"
      let private unSupportedSimilarity = sf1 "Unsupported similarity: %s"
      let private unSupportedIndexVersion = sf1 "Unsupported index version: %s"
      let private unsupportedDirectoryType = sf1 "Unsupported directory type: %s"
      let private unSupportedFieldType = sf2 "Unsupported field type '%s' for field '%s'"
      let private scriptCannotBeCompiled = sf2 "Script '%s' cannot be compiled: \n%s"
      let private analyzerNotSupportedForFieldType = sf2 "Analyzer '%s' not supported for field '%s'"
      
      type T = 
          | InvalidPropertyName of fieldName : string * value : string
          | AnalyzerIsMandatory of fieldName : string
          | DuplicateFieldValue of groupName : string * fieldName : string
          | ScriptNotFound of scriptName : string * fieldName : string
          | ResourceNotFound of resourceName : string * resourceType : string
          | UnSupportedSimilarity of similarityName : string
          | UnSupportedIndexVersion of indexVersion : string
          | UnsupportedDirectoryType of directoryType : string
          | UnSupportedFieldType of fieldName : string * fieldType : string
          | ScriptCannotBeCompiled of scriptName : string * error : string
          | AnalyzerNotSupportedForFieldType of fieldName : string * analyzerName : string
          interface IMessage with
              member this.LogProperty() = (MessageKeyword.Index, MessageLevel.Error)
              member this.OperationMessage() = 
                  match this with
                  | InvalidPropertyName(fn, v) -> sprintf invalidPropertyName fn v
                  | AnalyzerIsMandatory(fn) -> sprintf analyzerIsMandatory fn
                  | DuplicateFieldValue(gn, fn) -> sprintf duplicateFieldValue fn gn
                  | ScriptNotFound(sn, fn) -> sprintf scriptNotFound sn fn
                  | ResourceNotFound(rn, rt) -> sprintf resourceNotFound rn rt
                  | UnSupportedSimilarity(s) -> sprintf unSupportedSimilarity s
                  | UnSupportedIndexVersion(i) -> sprintf unSupportedIndexVersion i
                  | UnsupportedDirectoryType(d) -> sprintf unsupportedDirectoryType d
                  | UnSupportedFieldType(fn, ft) -> sprintf unSupportedFieldType fn ft
                  | ScriptCannotBeCompiled(sn, e) -> sprintf scriptCannotBeCompiled sn e
                  | AnalyzerNotSupportedForFieldType(f, a) -> sprintf analyzerNotSupportedForFieldType f a
                  |> caseToMsg this
  
  type SearchMessage = 
      | SearchError of ``exception`` : string
  