Core Concepts

GPAL.Logger: Turning Events Into Files

The Event System says GPAL never writes logs on its own. GPAL.Logger is the built-in, opt-in tool for when you decide you do want a log. One fluent chain configures where entries go and in what format, then every .Log() call writes one more entry there.

What It Is

GPAL.Logger is a small fluent wrapper that writes whatever you pass to .Log() to a destination you configure once. By default it writes to a file in the current working directory, but WithRootDirectory and WithFilename point it wherever you like. Because writing is done through GPALConverter under the hood, the file extension you give WithFilename decides the output format -- .log or .txt for plain lines, .csv for delimited rows, .json or .xml if you'd rather log structured data. Each entry is automatically prefixed with a timestamp and the name of the method that called .Log(), so you don't have to add that yourself. WithLogType(LogType.INFO | WARNING | ERROR | EXCEPTION) tags the next entry with a severity level -- it applies to a single .Log() call and then resets back to INFO.

GPAL.Logger

.WithRootDirectory(@"C:Logs")

.WithFilename("automation.log")

.Log("Login step completed");

// Tag a single entry as a warning - resets to INFO afterward

GPAL.Logger

.WithRootDirectory(@"C:Logs")

.WithFilename("automation.log")

.WithLogType(LogType.WARNING)

.Log("Retry limit reached, continuing");

Organizing Log Files: Directories and Filenames

Long-running or repeated automations generate a lot of log entries, so GPAL.Logger can split them across files automatically. WithDirectoryStructure builds a date-based folder hierarchy under your root directory (YMD for year/month/day folders, YMDH to add an hour folder, Julian for a day-of-year folder, and several other combinations). The folders are created for you the first time they're needed. WithFilenamePattern appends a timestamp to the filename itself (YMD for one file per day, YMDHMS for one file per run, and so on), so a single configured logger naturally rotates into a new file as time passes.

GPAL.Logger

.WithRootDirectory(@"C:Logs")

.WithDirectoryStructure(DirectoryStructure.YMD)

.WithFilenamePattern(FilenamePattern.YMDHMS)

.WithFilename("automation.log")

.WithLoggingFormat(LogDateFormat.YMD_HMS)

.Log("Run started");

// Writes to, e.g.:

// C:Logs2026612automation_20260612091500.log

TIP

WithLoggingFormat(LogDateFormat) sets the format of the timestamp written at the start of each log entry. WithFilenamePattern is separate. It controls the timestamp appended to the filename for file rotation. The two are independent and commonly used together.

Logging to a Database Instead of a File

WithDatabase(GPALDatabase) redirects .Log() entirely. Instead of writing to a file, each entry is saved as a row via GPALConverter.SaveTo(database), using whatever table the GPALDatabase object was configured with. This is useful when several processes or machines need to log to one shared, queryable place rather than separate local files.

var auditLog = GPAL.Database

.WithConnectionString("...")

.WithTableName("AutomationLog")

.ToGPALObject();

GPAL.Logger

.WithDatabase(auditLog)

.Log("Invoice batch completed");

TIP

If GPAL.Logger can't write an entry (bad path, unreachable database, and so on), it doesn't throw. It reports the problem on the GPAL.InformationHandler/ExceptionHandler channels from The Event System, just like everything else in GPAL.