liveBook · Manning

Monitoring

As explained in Functional Design and Architecture: Examples in Haskell

Logging is the recording of runtime events and diagnostic information produced by software.

Logging records runtime events and diagnostic information so an application can expose what it is doing without coupling business logic to a particular output mechanism. A useful subsystem accepts a message and level, selects a destination, and supports interchangeable implementations. section 10.1 section 10.1.1

A practical logging design separates policy from implementation:

  • Expose an interface containing message and level rather than filenames or other destination-specific details. section 10.1.1
  • Allow file, console, or external aggregation destinations through multiple implementations. section 10.1
  • Choose synchronous or asynchronous delivery and structured or unstructured formatting according to application needs. section 10.1
  • Represent logging as a free-monadic language when business actions need logging without directly performing effects. section 10.1.1

Logging inside transactional state

Logging directly from STM can repeat messages when a transaction restarts. A safer design interprets transactional logging into a concurrent log buffer, commits the state action, then flushes the entries through the real logger. This keeps logging out of business return values and preserves levels without requiring callers to remember ad hoc flushing. section 10.2.2

Listing 10.1 Logger in C#
public interface ILogger {                                #1
  void logMessage(int logLevel, string message);
};
  
public class FileLogger : ILogger {                       #2
  private int _logLevel;
  private string _file;
    
  public FileLogger(int logLevel, string file) {
    _logLevel = logLevel;
    _file = file;
  }
  
  public void logMessage(int logLevel, string message) {
    if (logLevel <= _logLevel)                            #3
      using (StreamWriter log = File.AppendText(_file)) { #4
        log.WriteLine(message);
      }
  }
};

The annotated C# listing contrasts a small implementation-neutral logger interface with a file logger that filters by level and appends messages to a file. section 10.1.1

How Functional Design and Architecture: Examples in Haskell covers it

How deep it goes
Explains interfaces, destinations, levels, delivery modes, formatting, interpreters, and STM buffering through implementation examples.
Examples
Uses C# file logging, console interpretation, meteor generation, smart-house interpreters, and delayed STM log flushing.
What you can do after
Build it from scratch as an abstract logger, concrete destination, free-monadic interface, or transaction-safe delayed logger.
How it connects
Connects logging with interfaces, SOLID, free monads, interpreters, application state, concurrency, and STM transactions.

Also explained in

Compare how 40 books explain monitoring →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Design and Architecture: Examples in Haskell. The section links point to the parts of the book it draws on.