Skip to content

Commit

Permalink
📝 Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
v20100v committed Dec 16, 2024
1 parent 86adab8 commit ab279ab
Show file tree
Hide file tree
Showing 16 changed files with 738 additions and 241 deletions.
123 changes: 72 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,29 @@
 [![Want to support me? Offer me a coffee!](https://img.shields.io/badge/Want%20to%20support%20me%3F%20Offer%20me%20a%20coffee%21-donate-informational.svg)](https://www.buymeacoffee.com/vincent.blain)

> VBA Monologger is an advanced and flexible logging solution for VBA (*Visual Basic for Applications*) ecosystem. It is largely inspired by the [Monolog](https://github.com/Seldaek/monolog) library in PHP, which itself is inspired by the [Logbook](https://logbook.readthedocs.io/en/stable/) library in Python.
>
> [Go to documentation](https://6i-software.github.io/vba-monologger/)
## Introduction


## Preamble

VBA provides developers with the ability to automate tasks, interact with the features of
Microsoft Office applications, and even create applications with a graphical user interface (`Userform`). However, compared to other development ecosystems, VBA only offers a rudimentary logging solution, limited to the `Debug.Print` function, which writes to the Excel console (a.k.a. the Excel immediate window).
VBA provides developers with the ability to automate tasks, interact with the features of Microsoft Office applications, and even create applications with a graphical user interface (`Userform`). However, compared to other development ecosystems, VBA only offers a rudimentary logging solution, limited to the `Debug.Print` function, which writes to the Excel console (a.k.a. the Excel immediate window).

The *VBA Monologger* library project was born out of the need for a more advanced and flexible logging solution in the VBA ecosystem. It is (heavily) inspired by the PSR-3 standard in the PHP ecosystem and its most recognized implementation, the Monolog library. The goal of this library is to provide similar features and capabilities, particularly by offering a modular architecture that can easily adapt to different use cases. The main idea is for each developer to easily configure and customize their own logging system according to their needs.


## Features

- Customize the logging format to define how log messages are structured and displayed - see [formatter](https://6i-software.github.io/vba-monologger/under-the-hood/formatter.html).
- Specify the destination where logs should be viewed (*e.g.*, VBA console *a.k.a* Excel's immediate window, Windows console (cmd.exe) with ANSI color support, file...) and configure the conditions under which logging events are triggered based on specific criteria - see [handler](https://6i-software.github.io/vba-monologger/under-the-hood/handler.html).
- Manages 8 standard severity levels to classify the importance of log messages, following the [PSR-3](https://www.php-fig.org/psr/psr-3/) standard - see [log severity levels](https://6i-software.github.io/vba-monologger/under-the-hood/log-severity-levels.html)
- Enrich log records with pre-processors, enabling the addition of context, transformation of data, or customization of log entries to suit specific needs (*e.g.* add CPU or memory usage, generate a UID for each session, add tags... and more) - see [pre-processor](https://6i-software.github.io/vba-monologger/under-the-hood/pre-processor.html).
- Use the provided loggers in the VBAMonologger factory (*e.g. `LoggerConsoleVBA`, `LoggerConsole` or `LoggerFile`*) for basic usage, or create your own custom logging system - see [logger](https://6i-software.github.io/vba-monologger/under-the-hood/logger.html).
**In VBA Monologger, the logger is the central component of this library, acting as the primary interface for recording, categorizing, and managing log messages throughout an application**. It provides developers with a highly configurable and flexible tool for implementing custom logging logic tailored to their specific needs. By using a logger, applications can systematically capture events and system states, facilitating both real-time monitoring and historical analysis of system behavior.

The logger is designed to handle multiple logging levels, directing each log entry to the appropriate handlers (i.e. appropriate destinations) and applying the correct formatting to messages. It also supports the use of various pre-processors, which can enrich log messages with extra contextual information, allowing for complex logging logic while keeping code readable and straightforward.

Main features:

- Customize the logging format to define how log messages are structured and displayed.
- Specify the destination where logs should be viewed (*e.g.*, VBA console *a.k.a* Excel's immediate window, Windows console (cmd.exe) with ANSI color support, file...) and configure the conditions under which logging events are triggered based on specific criteria.
- Manages 8 standard severity levels to classify the importance of log messages, following the [PSR-3](https://www.php-fig.org/psr/psr-3/) standard.
- Enrich log records with pre-processors, enabling the addition of context, transformation of data, or customization of log entries to suit specific needs (*e.g.* add CPU or memory usage, generate a UID for each session, add tags... and more).
- Use the provided loggers in the VBAMonologger factory (*e.g. `LoggerConsoleVBA`, `LoggerConsole` or `LoggerFile`*) for basic usage, or create your own custom logging system.
- Easily develop your own custom formatter, handler, and pre-processors to tailor the logging system to your specific needs. By creating unique formatting styles, specialized handlers, and custom pre-processing logic, you can enhance the functionality and flexibility of your logging setup, ensuring it meets the precise requirements of your applications and workflows.


Expand All @@ -30,90 +36,105 @@ Please refer to the documentation for details on how to install and use VBA Mono
> [Go to the website documentation](https://6i-software.github.io/vba-monologger/)

## Basic usages
## Quick start

### Manual installation

1. Download the VBA Monologger Excel Add-in (.xlam file) to your computer: [6i_VBA-Monologger.xlam](https://github.com/6i-software/vba-monologger/raw/refs/heads/main/src/6i_VBA-Monologger.xlam)
2. Put this xlam file into a folder trusted by Excel, and add it as a reference in your VBA project through *Tools > References* in the VBA editor.

### Log output to VBA Console

To install the VBAMonologger library, simply download the `6i-VBAMonologger.xlam` file and add it as a reference in your project. Next, use the factory to create an instance of a logger preconfigured with default handler, formatter, and pre-processors, as shown below:
In VBA Monologger, we use a factory in order to simplify and standardize the creation of objects, such as loggers, by encapsulating the logic needed to initialize them. The factory pattern abstracts the object creation process, which can be particularly useful. So to instantiate your first logger that output logs into the VBA console, just use the method `VBAMonologger.Factory.createLoggerConsoleVBA()`, as shown below. It provides an instance of a logger preconfigured with default handler, formatter, and pre-processors.

```vbscript
Public Sub howto_use_loggerConsoleVBA()
' Create a logger instance for output log into VBA console (Excel's immediate window)
Dim Logger As VBAMonologger.LoggerInterface
Set Logger = VBAMonologger.Factory.createLoggerConsoleVBA("App")

' Logs message for each severity levels
Logger.trace "Authentication function call for user 'Bob Morane'." ' The 'debug' method exposes presents in PSR-3 is rename into 'trace' in order to be compatible in VBA ecosystem
' Use the logger for each severity levels
Logger.trace "Authentication function call for user 'Bob Morane'."
Logger.info "User 'UltraVomit' has logged in successfully."
Logger.notice "Process completed successfully with minor issues."
Logger.warning "The user 'Beetlejuice' should not be called more than 3 times."
Logger.error "An error occurred when the user 'DeadRobotZombieCopFromOuterspace' tried to read the dashboard file."
Logger.critical "System is in an unstable state. Unable to authenticate the user 'Skjalg Skagen'."
Logger.warning "'Beetlejuice' should not be called more than 3 times."
Logger.error "An error occurred with the user 'DRZCFOS2'."
Logger.critical "System is in an unstable state."
Logger.alert "Action required: unable to generate the dashboard."
Logger.emergency "A critical failure occurred in the application for moving files."
Logger.emergency "A critical failure occurred in the application."
End Sub
```

You can see result in the VBA console (a.k.a. Excel's Immediate Windows).

![VBAMonologger-output-VBAConsole.png](docs/src/assets/VBAMonologger-output-VBAConsole.png)
![VBAMonologger-output-VBAConsole.png](docs/src/getting-started/VBAMonologger-output-VBAConsole.png)

> Note: If the console is not visible in Excel Visual basidc IDE, go to the menu and select *View > Immediate Window*. Alternatively, you can press <kbd>Ctrl</kbd> + <kbd>G</kbd> to quickly open it.
As you can see, in the signature of this factory's method, it is possible to set the name the logger (channel) and to load a custom formatter.

```vbscript
Public Function createLoggerConsoleVBA( _
Optional ByVal paramLoggerName As String = vbNullString, _
Optional ByRef paramFormatter As VBAMonologger.FormatterInterface = Nothing _
) As VBAMonologger.Logger
```

### Log output to file

By default, the logger file writes logs to the `./var/log/logfile_xxxx-yy-zz.log` file, relative to the path of the workbook. You can change the name and the folder of the file into the `HandlerFile`. To ensure compatibility with special and multilingual characters in this Handler, the UTF-8 encoding is preferred.
### Log output to Windows console

```vbscript
Public Sub howto_use_loggerConsoleVBA()
' Create a logger instance for output log into VBA console (Excel's immediate window)
Dim Logger As VBAMonologger.LoggerInterface
Set Logger = VBAMonologger.Factory.createLoggerConsoleVBA("App")

' Logs message for each severity levels
(...)
End Sub
```
If you prefer to display your logs outside the Excel VBA IDE, you can output them directly to the Windows Console (cmd.exe).

The factory can create a dedicated logger for Windows Console with `VBAMonologger.Factory.createLoggerConsole()` method. It handles log messages by streaming them to the Windows console using an HTTP-based client/server architecture. The client sends log records as HTTP requests to the server, and the server processes these requests, displaying the log messages directly in the console output. This logger features a formatter that supports ANSI colors `VBAMonologger.Formatter.FormatterANSIcoloredLine`.

### Log output to Windows console (cmd.exe)
It also includes the pre-processors placeholders according to PSR-3 rules. It allows to use placeholders in log message that will be replaced with value provided in the log record context.

By default, the logger Windows console created with the factory includes a formatter that supports ANSI colors, and more. It also includes the pre-processors placeholders according to PSR-3 rules. It allows to use placeholders in log message that will be replaced with value provided in the log record context.

```vbscript
Public Sub howto_use_loggerConsole()
Public Sub howto_use_logger_console()
Dim Logger As VBAMonologger.LoggerInterface
Set Logger = VBAMonologger.Factory.createLoggerConsole("App")

' Logs message for each severity levels

' Use the logger for each severity levels
Logger.trace "Authentication function call for user 'Bob Morane'."
(...)
End Sub
```

![VBAMonologger-output-WindowsConsole.png](docs/src/assets/VBAMonologger-output-WindowsConsole.png)
When you execute this code, it launches a `cmd.exe`, and you can view the results in it. The formatter's configuration allows you to customize the color scheme.

![VBAMonologger-output-WindowsConsole.png](docs/src/getting-started/VBAMonologger-output-WindowsConsole.png)


### Log output to file

You can send logs into a file with the default logger file provided by factory's method `VBAMonologger.Factory.createLoggerFile()`. By default, this logger writes logs to the `./var/log/logfile_yyyy-mm-dd.log` file, relative to the path of the workbook. To ensure compatibility with special and multilingual characters, the UTF-8 encoding is preferred.

### Use placeholders with context data into log message
```vbscript
Public Function createLoggerFile( _
Optional ByVal paramLoggerName As String = vbNullString, _
Optional ByRef paramFormatter As FormatterInterface = Nothing, _
Optional ByVal paramLogFileName As String = vbNullString, _
Optional ByVal paramLogFileFolder As String = vbNullString _
) As VBAMonologger.Logger
```

By default, all loggers create with the factory includes the pre-processors placeholders. It is used to dynamically insert specific contextual data into logging messages, allowing for more detailed and contextualized log records. You can choose to display (or not) the context data, either on a single line or across multiple lines, formatted as pretty JSON with whitespace.
Here’s an example with a custom name and custom folder of the log file.

```vbscript
Public Sub howto_use_context()
```vbscript
Public Sub howto_change_logger_file_name_and_folder()
Dim Logger As VBAMonologger.LoggerInterface
Set Logger = VBAMonologger.Factory.createLoggerConsole("App")

Dim context As Object: Set context = CreateObject("Scripting.Dictionary")
context.Add "UserName", "Bob Morane"
context.Add "UserID", 342527
Set Logger = VBAMonologger.Factory.createLoggerFile( _
paramLoggerName:= "App", _
paramLogFileName:="my-log-file___"&format(Now, "yyyy-mm-dd") & ".log", _
paramLogFileFolder:=ThisWorkbook.Path & "\logs" _
)

Logger.trace "Authentication function call for user '{UserName}' with id '{UserID}'.", context
' Logs message for each severity levels
Logger.trace "Authentication function call for user 'Bob Morane'."
(...)
End Sub
```

![VBAMonologger-output-placeholders.png](docs/src/assets/VBAMonologger-output-placeholders.png)


![VBAMonologger-output-File.png](docs/src/getting-started/VBAMonologger-output-File.png)


## About
Expand Down
7 changes: 6 additions & 1 deletion docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,12 @@ nav:
- Getting started:
- Introduction: getting-started/introduction.md
- Install: getting-started/install.md
- Basic usages: getting-started/basic-usages.md
- Quick start: getting-started/quick-start.md
- Usages:
- "Set the logger's name": getting-started/usages/channel.md
- "Use placeholders": getting-started/usages/placeholders.md
- "Add a custom formatter": getting-started/usages/add-custom-formatter.md
- "Add a pre-processor": getting-started/usages/add-pre-processor.md
- Creating your logger: getting-started/creating-custom-logger.md
- Under the hood:
- under-the-hood/index.md
Expand Down
65 changes: 30 additions & 35 deletions docs/overrides/welcome.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,24 @@

{% set class = "md-header" %}
{% if "navigation.tabs.sticky" in features %}
{% set class = class ~ " md-header--shadow md-header--lifted" %}
{% set class = class ~ " md-header--shadow md-header--lifted" %}
{% elif "navigation.tabs" not in features %}
{% set class = class ~ " md-header--shadow" %}
{% set class = class ~ " md-header--shadow" %}
{% endif %}
<header class="{{ class }}" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="{{ lang.t('header') }}">
<a href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" title="{{ config.site_name | e }}" class="md-header__button md-logo" aria-label="{{ config.site_name }}" data-md-component="logo">
<a href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" title="{{ config.site_name | e }}"
class="md-header__button md-logo" aria-label="{{ config.site_name }}" data-md-component="logo">
{% include "partials/logo.html" %}
</a>
<label class="md-header__button md-icon" for="__drawer">
{% set icon = config.theme.icon.menu or "material/menu" %}
{% include ".icons/" ~ icon ~ ".svg" %}
</label>
</label>
{% if config.theme.palette %}
{% if not config.theme.palette is mapping %}
{% include "partials/palette.html" %}
{% endif %}
{% if not config.theme.palette is mapping %}
{% include "partials/palette.html" %}
{% endif %}
{% endif %}

<div class="md-header__title" data-md-component="header-title">
Expand All @@ -31,24 +32,22 @@
</span>
</div>
</div>
</div>
</div>

{% if not config.theme.palette is mapping %}
{% include "partials/javascripts/palette.html" %}
{% include "partials/javascripts/palette.html" %}
{% endif %}
</nav>
</header>

{% endblock %}



<!-- Render landing page under block tabs -->
{% block tabs %}

<!-- Additional styles for landing page -->
<style>

/* Application header should be static for the landing page */
.md-header {
position: initial;
Expand All @@ -63,31 +62,17 @@
.md-content {
display: none;
}

/* Hide table of contents */
@media screen and (min-width: 60em) {
.md-sidebar--secondary {
display: none;
}
}

/* Hide navigation */
@media screen and (min-width: 76.25em) {
.md-sidebar--primary {
display: none;
}
}


.custom-hero {
margin-top:3%;
margin-left:6%;
margin-right:6%;
margin-top: 3%;
margin-left: 6%;
margin-right: 6%;
}

.custom-hero-content p {
max-width: 400px;
}

.decoration {
background: linear-gradient(
to bottom,
Expand All @@ -96,6 +81,13 @@
);
height: 20vh;
}

@media screen and (min-width: 76.25em) {
/* Hide table of contents */
/* .md-sidebar--secondary { display: none; } */
/* Hide navigation */
.md-sidebar--primary { display: none;}
}
</style>

<!-- Hero for landing page -->
Expand All @@ -104,7 +96,7 @@
<section class="custom-landing-container">

<div class="decoration"></div>

<div class="md-grid md-typeset">
<div class="custom-hero">
<!-- Hero image -->
Expand All @@ -116,10 +108,13 @@
<div class="custom-hero-content">
<h1>Log smarter, debug faster in VBA</h1>
<p>{{ config.site_description }} Set up in two minutes.</p>
<a href="{{ 'getting-started/introduction.html' | url }}" title="Set up in two minutes!" class="md-button md-button--primary">
<a href="{{ 'getting-started/introduction.html' | url }}" title="Set up in two minutes!"
class="md-button md-button--primary">
Get started
</a>
<a href="{{ 'under-the-hood/' | url }}" title="To understand and learn what's happening with each compontents of this library" class="md-button">
<a href="{{ 'under-the-hood/' | url }}"
title="To understand and learn what's happening with each compontents of this library"
class="md-button">
Learn more
</a>
</div>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/src/getting-started/VBAMonologger-output-VBAConsole.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/src/getting-started/VBAMonologger-output-WindowsConsole.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit ab279ab

Please sign in to comment.