Merge pull request 'dev' (#1) from dev into master

Reviewed-on: #1
This commit is contained in:
Alexander Zhirov 2023-04-28 08:35:52 +00:00
commit 31b67389cd
7 changed files with 145 additions and 68 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
.dub .dub
*.o *.o
lib lib
bin
test.log

View File

@ -1,5 +1,13 @@
# Changelog # Changelog
## [v0.3.0](https://git.zhirov.kz/dlang/singlog/compare/v0.2.1...v0.3.0) (2023.04.28)
- Minor changes
### New
- Windows OS Logging support
## [v0.2.1](https://git.zhirov.kz/dlang/singlog/compare/v0.2.0...v0.2.1) (2023.03.29) ## [v0.2.1](https://git.zhirov.kz/dlang/singlog/compare/v0.2.0...v0.2.1) (2023.03.29)
### New ### New

View File

@ -1,9 +1,11 @@
# singlog ![singlog](singlog.png)
[![license](https://img.shields.io/github/license/AlexanderZhirov/singlog.svg?sort=semver&style=for-the-badge&color=green)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html) [![license](https://img.shields.io/github/license/AlexanderZhirov/singlog.svg?sort=semver&style=for-the-badge&color=green)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
[![main](https://img.shields.io/badge/dynamic/json.svg?label=git.zhirov.kz&style=for-the-badge&url=https://git.zhirov.kz/api/v1/repos/dlang/singlog/tags&query=$[0].name&color=violet)](https://git.zhirov.kz/dlang/singlog) [![main](https://img.shields.io/badge/dynamic/json.svg?label=git.zhirov.kz&style=for-the-badge&url=https://git.zhirov.kz/api/v1/repos/dlang/singlog/tags&query=$[0].name&color=violet)](https://git.zhirov.kz/dlang/singlog)
[![githab](https://img.shields.io/github/v/tag/AlexanderZhirov/singlog.svg?sort=semver&style=for-the-badge&color=blue&label=github)](https://github.com/AlexanderZhirov/singlog) [![githab](https://img.shields.io/github/v/tag/AlexanderZhirov/singlog.svg?sort=semver&style=for-the-badge&color=blue&label=github)](https://github.com/AlexanderZhirov/singlog)
[![dub](https://img.shields.io/dub/v/singlog.svg?sort=semver&style=for-the-badge&color=orange)](https://code.dlang.org/packages/singlog) [![dub](https://img.shields.io/dub/v/singlog.svg?sort=semver&style=for-the-badge&color=orange)](https://code.dlang.org/packages/singlog)
[![linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black)](https://www.linux.org/)
[![windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge&logo=windows&logoColor=white)](https://support.microsoft.com/en-US/windows)
Singleton for simple logging Singleton for simple logging
@ -12,19 +14,27 @@ Singleton for simple logging
```d ```d
import singlog; import singlog;
void main() void main(string[] argv) {
{ log.output(log.SYSLOG | log.STDOUT | log.FILE) // write to syslog, standard output stream and file
log.level(log.DEBUG); .name(argv[0]) // program name as an identifier (for Windows OS)
// write to syslog and file .level(log.DEBUGGING) // logging level
log.output(log.SYSLOG | log.FILE); .file("./test.log"); // the path to the log file
log.file("./file.log");
log.warning("Hello, World!"); log.e("This is an error message");
log.w("The same thing"); log.error("And this is also an error message");
log.w("This is a warning message");
log.i("This is an information message");
} }
``` ```
## Examples ## Examples
Setting the name of the logged program (it matters for Windows OS):
```d
log.name("My program");
```
Setting the error output level: Setting the error output level:
```d ```d
@ -42,7 +52,6 @@ Assigning a target output:
```d ```d
log.output(log.SYSLOG); log.output(log.SYSLOG);
log.output(log.STDOUT); log.output(log.STDOUT);
``` ```
Setup and allowing writing to a file: Setup and allowing writing to a file:
@ -64,6 +73,6 @@ log.i("Information message") => log.information("Information message");
log.d("Debugging message") => log.debugging("Debugging message"); log.d("Debugging message") => log.debugging("Debugging message");
``` ```
## Dub ## DUB
Add a dependency on `"singlog": "~>0.2.1"`. Add a dependency on `"singlog": "~>0.3.0"`.

View File

@ -7,9 +7,22 @@
"license": "GPL-2.0", "license": "GPL-2.0",
"copyright": "© Alexander Zhirov, 2023", "copyright": "© Alexander Zhirov, 2023",
"description": "Singleton for simple logging", "description": "Singleton for simple logging",
"targetType": "library",
"targetPath": "lib",
"targetName": "singlog", "targetName": "singlog",
"configurations": [
{
"name": "library",
"targetType": "library",
"targetPath": "lib"
},
{
"name": "test",
"targetType": "executable",
"targetPath": "bin",
"targetName": "app",
"importPaths": ["source","tests"],
"sourcePaths": ["tests"]
}
],
"dependencies": { "dependencies": {
"datefmt": "~>1.0.4" "datefmt": "~>1.0.4"
} }

BIN
singlog.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,9 +1,13 @@
module singlog; module singlog;
import core.sys.posix.syslog; version(Windows)
import core.sys.windows.windows;
else
import core.sys.posix.syslog;
import std.string;
import std.stdio; import std.stdio;
import std.conv; import std.conv;
import std.meta;
import std.file; import std.file;
import std.datetime; import std.datetime;
import datefmt; import datefmt;
@ -14,6 +18,8 @@ alias log = Log.msg;
Singleton for simple logging Singleton for simple logging
--- ---
// Setting the name of the logged program
log.name("My program");
// Setting the error output level // Setting the error output level
log.level(log.DEBUG); log.level(log.DEBUG);
log.level(log.ALERT); log.level(log.ALERT);
@ -28,8 +34,6 @@ alias log = Log.msg;
log.output(log.FILE); log.output(log.FILE);
// Setup and allowing writing to a file // Setup and allowing writing to a file
log.file("./file.log"); log.file("./file.log");
log.fileOn();
log.fileOff();
// Output of messages to the log // Output of messages to the log
log.alert("Alert message"); log.alert("Alert message");
log.critical("Critical message"); log.critical("Critical message");
@ -40,57 +44,87 @@ alias log = Log.msg;
log.debugging("Debugging message"); log.debugging("Debugging message");
--- ---
+/ +/
class Log class Log {
{ private:
private static Log log; static Log log;
private string path; string path;
private bool writeToFile = true; string nameProgram = "singlog";
private static SysTime time; bool writeToFile = true;
this() {}
// Target output version(Windows) {
enum { public enum {
DEBUGGING = 0,
ALERT = 1,
CRITICAL = 1,
ERROR = 1,
WARNING = 2,
NOTICE = 3,
INFORMATION = 3,
}
WORD[] sysLevel = [
EVENTLOG_SUCCESS,
EVENTLOG_ERROR_TYPE,
EVENTLOG_WARNING_TYPE,
EVENTLOG_INFORMATION_TYPE
];
void syslog(WORD priority, LPCSTR message) {
HANDLE handleEventLog = RegisterEventSourceA(NULL, this.nameProgram.toStringz());
if (handleEventLog == NULL)
return;
ReportEventA(handleEventLog, priority, 0, 0, NULL, 1, 0, &message, NULL);
DeregisterEventSource(handleEventLog);
}
} else version(Posix) {
public enum {
DEBUGGING = 0,
ALERT = 1,
CRITICAL = 2,
ERROR = 3,
WARNING = 4,
NOTICE = 5,
INFORMATION = 6
}
int[] sysLevel = [
LOG_DEBUG,
LOG_ALERT,
LOG_CRIT,
LOG_ERR,
LOG_WARNING,
LOG_NOTICE,
LOG_INFO
];
}
public enum {
SYSLOG = 1, SYSLOG = 1,
STDOUT = 2, STDOUT = 2,
FILE = 4 FILE = 4
} }
// Message output level
enum {
DEBUG = 0,
CRIT = 1,
ERR = 2,
WARNING = 3,
NOTICE = 4,
INFO = 5,
ALERT = 6
}
int msgOutput = STDOUT; int msgOutput = STDOUT;
int msgLevel = INFO; int msgLevel = INFORMATION;
private this() {} void writeLog(string message, int msgLevel) {
private void writeLog(string message, int msgLevel, int priority)
{
if (this.msgLevel > msgLevel) if (this.msgLevel > msgLevel)
return; return;
if (this.msgOutput & 1) if (this.msgOutput & 1)
syslog(priority, (message ~ "\0").ptr); syslog(sysLevel[msgLevel], message.toStringz());
if (this.msgOutput & 2) if (this.msgOutput & 2)
writeln(message); writeln(message);
if (this.msgOutput & 4) if (this.msgOutput & 4)
writeFile(message); writeFile(message);
} }
private void writeFile(string message) void writeFile(string message) {
{
if (!this.writeToFile) if (!this.writeToFile)
return; return;
if (this.path.exists) if (!this.path.exists) {
this.writeToFile = true;
else
{
this.writeToFile = false; this.writeToFile = false;
this.warning("The log file does not exist: " ~ this.path); this.warning("The log file does not exist: " ~ this.path);
} }
@ -103,16 +137,16 @@ class Log
} catch (Exception e) { } catch (Exception e) {
this.writeToFile = false; this.writeToFile = false;
this.error("Unable to open the log file " ~ this.path); this.error("Unable to open the log file " ~ this.path);
this.critical(e); this.information(e);
return; return;
} }
try { try {
file.writeln(this.time.format("%Y.%m.%d %H:%M:%S: ") ~ message); file.writeln(Clock.currTime().format("%Y.%m.%d %H:%M:%S: ") ~ message);
} catch (Exception e) { } catch (Exception e) {
this.writeToFile = false; this.writeToFile = false;
this.error("Unable to write to the log file " ~ this.path); this.error("Unable to write to the log file " ~ this.path);
this.critical(e); this.information(e);
return; return;
} }
@ -121,33 +155,31 @@ class Log
} catch (Exception e) { } catch (Exception e) {
this.writeToFile = false; this.writeToFile = false;
this.error("Unable to close the log file " ~ this.path); this.error("Unable to close the log file " ~ this.path);
this.critical(e); this.information(e);
return; return;
} }
} }
@property static Log msg() public:
{ @property static Log msg() {
if (this.log is null) if (this.log is null)
{
this.log = new Log; this.log = new Log;
this.time = Clock.currTime();
}
return this.log; return this.log;
} }
void output(int msgOutput) { this.msgOutput = msgOutput; } Log output(int msgOutput) { this.msgOutput = msgOutput; return this.log; }
void level(int msgLevel) { this.msgLevel = msgLevel; } Log name(string nameProgram) { this.nameProgram = nameProgram; return this.log; }
void file(string path) { this.path = path; } Log file(string path) { this.path = path; return this.log; }
Log level(int msgLevel) { this.msgLevel = msgLevel; return this.log; }
void alert(T)(T message) { writeLog(message.to!string, ALERT, LOG_ALERT); } void alert(T)(T message) { writeLog(message.to!string, ALERT); }
void critical(T)(T message) { writeLog(message.to!string, CRIT, LOG_CRIT); } void critical(T)(T message) { writeLog(message.to!string, CRITICAL); }
void error(T)(T message) { writeLog(message.to!string, ERR, LOG_ERR); } void error(T)(T message) { writeLog(message.to!string, ERROR); }
void warning(T)(T message) { writeLog(message.to!string, WARNING, LOG_WARNING); } void warning(T)(T message) { writeLog(message.to!string, WARNING); }
void notice(T)(T message) { writeLog(message.to!string, NOTICE, LOG_NOTICE); } void notice(T)(T message) { writeLog(message.to!string, NOTICE); }
void information(T)(T message) { writeLog(message.to!string, INFO, LOG_INFO); } void information(T)(T message) { writeLog(message.to!string, INFORMATION); }
void debugging(T)(T message) {writeLog(message.to!string, DEBUG, LOG_DEBUG); } void debugging(T)(T message) { writeLog(message.to!string, DEBUG); }
alias a = alert; alias a = alert;
alias c = critical; alias c = critical;

13
tests/test.d Normal file
View File

@ -0,0 +1,13 @@
import singlog;
void main(string[] argv) {
log.output(log.SYSLOG | log.STDOUT | log.FILE) // write to syslog, standard output stream and file
.name(argv[0]) // program name as an identifier (for Windows OS)
.level(log.DEBUGGING) // logging level
.file("./test.log"); // the path to the log file
log.e("This is an error message");
log.error("And this is also an error message");
log.w("This is a warning message");
log.i("This is an information message");
}