Data and Files

Logging to a Database and Sending Email with GPAL

Complete Program

The whole workflow: define a database target for logging, build a logger that writes to it, publish a few events for it to record, write the settings out through the converter, then configure and send an email.

using GenerallyPositive;

using static GenerallyPositive.Enums;


GPALDatabase database = (GPALDatabase)GPAL.Database

.WithServerName("MYSERVER\SQLEXPRESS")

.WithDatabaseName("GPAL")

.WithDatabaseType(DatabaseType.SQLServer)

.WithCreateAs("Insert Into TestInput (SearchTerm) Values (@SearchTerm)")

.WithNVarCharParameter("SearchTerm");


IGPALGrid<string> grid = GPAL.Grid.ToGPALObject();


GPAL.WithPublishToDebug().WithAutoUpdateWebDriver();


// the logger writes what GPAL publishes, so it is built and then handed to GPAL

IGPALLogger gPALLogger = GPAL.Logger.WithDatabase(database).ToGPALObject();


GPAL.WithPublishToLogger(gPALLogger);


// every published event is an entry from here on

GPAL.PublishSimpleEvent(GPALEventType.NOTICE, "Log This");

GPAL.PublishSimpleEvent(GPALEventType.CAUTION, "AND, THIS");


// a grid or a class is a file, which is what the converter is for

GPAL.Converter.WithInput(GPAL.GPALSettings).SaveTo(ref grid);

GPAL.Converter.WithInput(grid).SaveTo((GPALFile)"c:\logs\settings.csv");


IGPALMail gPALMail = GPAL.Mail

.WithSMTPServerName("smtp.example.com")

.WithSMTPPortNum(587)

.ToGPALObject();


gPALMail

.WithFromEmailAddress("reports@example.com")

.WithCcEmailAddress("cc@example.com").WithName("CC")

.WithBccEmailAddress("bcc@example.com").WithName("BCC")

.WithToEmailAddress("recipient@example.com").WithName("Recipient")

.WithSubject("Run Complete")

.Send();

Define a Database Target

GPAL.Database describes a SQL connection and, optionally, an insert statement for new rows. WithCreateAs gives the parameterized SQL, and WithNVarCharParameter declares the type of each parameter the SQL names. This same GPALDatabase object can be reused anywhere GPAL needs database access - here, as a logging destination.

GPALDatabase database = (GPALDatabase)GPAL.Database

.WithServerName("MYSERVER\SQLEXPRESS")

.WithDatabaseName("GPAL")

.WithDatabaseType(DatabaseType.SQLServer)

.WithCreateAs("Insert Into TestInput (SearchTerm) Values (@SearchTerm)")

.WithNVarCharParameter("SearchTerm");

Log Published Events

WithDatabase points the logger at the database object instead of a file, and ToGPALObject() finalizes it into an IGPALLogger. GPAL.WithPublishToLogger hands it to GPAL, and from then on every published event is written to the configured log destination; nothing calls the logger directly. WithLogEventTypes picks which event types it writes, and WithDelimiter sets the character written between the fields on a line.

// the logger is told where entries go, then handed to GPAL so published events reach it

IGPALLogger gPALLogger = GPAL.Logger.WithDatabase(database).ToGPALObject();


GPAL.WithPublishToLogger(gPALLogger);


// nothing calls the logger directly. a workflow raises events and the logger writes them,

// which is what makes GPAL's own events and the workflow's own land in the same place

GPAL.PublishSimpleEvent(GPALEventType.NOTICE, "Log This");

GPAL.PublishSimpleEvent(GPALEventType.CAUTION, "AND, THIS");


// which types the logger writes, when all of them is more than you want

GPAL.Logger

.WithDatabase(database)

.WithLogEventTypes(GPALEventType.WARNING | GPALEventType.ERROR | GPALEventType.EXCEPTION)

.ToGPALObject();

NOTE

Converting GPAL.GPALSettings to a grid and saving it, as the next section does, captures the full configuration GPAL was running with at that moment - handy for reproducing an issue later, since you know exactly what driver locations, automation engines, and flags were in effect.

Convert Settings Into a Grid and Save It

GPAL.Converter.WithInput().SaveTo() turns a settings object (or any supported source) into an IGPALGrid by reference. A logger does not take a grid, so the converter writes the grid out to a file, and the NOTICE that follows records in the log that it happened.

IGPALGrid<string> grid = GPAL.Grid.ToGPALObject();


// a grid is not a log entry. the converter is what writes one out, and the logger records

// that it happened

GPAL.Converter.WithInput(GPAL.GPALSettings).SaveTo(ref grid);

GPAL.Converter.WithInput(grid).SaveTo((GPALFile)"c:\logs\settings.csv");


GPAL.PublishSimpleEvent(GPALEventType.NOTICE, $"Settings written, [{grid.Count()}] rows");

Send an Email with To, CC, and BCC

GPAL.Mail is configured the same way as every other subsystem: With* methods set the SMTP server, port, sender, and recipients, then ToGPALObject() returns an IGPALMail ready to send. WithName attaches a display name to whichever address was most recently set with WithCcEmailAddress, WithBccEmailAddress, or WithToEmailAddress.

IGPALMail gPALMail = GPAL.Mail

.WithSMTPServerName("smtp.example.com")

.WithSMTPPortNum(587)

.ToGPALObject();


gPALMail

.WithFromEmailAddress("reports@example.com")

.WithCcEmailAddress("cc@example.com").WithName("CC")

.WithBccEmailAddress("bcc@example.com").WithName("BCC")

.WithToEmailAddress("recipient@example.com").WithName("Recipient")

.WithSubject("Run Complete")

.Send();

WARNING

Each WithName call attaches a display name to whichever WithToEmailAddress, WithCcEmailAddress, or WithBccEmailAddress call came immediately before it. Order matters - if you set multiple recipients, call WithName right after each one.

💬 Ask GPAL