Compare commits
No commits in common. "e019422dd199d744e04b9458eeaa6ad80f88253e" and "5dd910b683c701d3d3590de799996aef35d8558e" have entirely different histories.
e019422dd1
...
5dd910b683
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,17 +1,5 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [v0.4.0](https://git.zhirov.kz/dlang/singlog/compare/v0.3.2...v0.4.0) (2023.06.07)
|
|
||||||
|
|
||||||
- Part of the code has been changed/rewritten
|
|
||||||
|
|
||||||
### New
|
|
||||||
|
|
||||||
- Color output of messages to the terminal and console
|
|
||||||
|
|
||||||
### Bug fixes
|
|
||||||
|
|
||||||
- In Windows, unicode messages are output without distortion to the system log and console (thanks [Adam D. Ruppe](https://arsdnet.net/))
|
|
||||||
|
|
||||||
## [v0.3.2](https://git.zhirov.kz/dlang/singlog/compare/v0.3.1...v0.3.2) (2023.06.01)
|
## [v0.3.2](https://git.zhirov.kz/dlang/singlog/compare/v0.3.1...v0.3.2) (2023.06.01)
|
||||||
|
|
||||||
- Printing information about the type of the logged message to the standard output stream and file
|
- Printing information about the type of the logged message to the standard output stream and file
|
||||||
|
|
26
README.md
26
README.md
|
@ -16,37 +16,25 @@ import singlog;
|
||||||
|
|
||||||
void main(string[] argv) {
|
void main(string[] argv) {
|
||||||
log.output(log.SYSLOG | log.STDOUT | log.FILE) // write to syslog, standard output stream and file
|
log.output(log.SYSLOG | log.STDOUT | log.FILE) // write to syslog, standard output stream and file
|
||||||
.program(argv[0]) // program name as an identifier (for Windows OS)
|
.name(argv[0]) // program name as an identifier (for Windows OS)
|
||||||
.level(log.DEBUGGING) // logging level
|
.level(log.DEBUGGING) // logging level
|
||||||
.color(true) // color text output
|
|
||||||
.file("./test.log"); // the path to the log file
|
.file("./test.log"); // the path to the log file
|
||||||
|
|
||||||
log.i("This is an information message");
|
|
||||||
log.n("This is a notice message");
|
|
||||||
log.w("This is a warning message");
|
|
||||||
log.e("This is an error message");
|
log.e("This is an error message");
|
||||||
log.c("This is a critical message");
|
log.error("And this is also an error message");
|
||||||
log.a("This is an alert message");
|
log.w("This is a warning message");
|
||||||
log.d("This is a debug message");
|
log.i("This is an information message");
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
![output](tests/terminal.png)
|
![output](tests/output.png)
|
||||||
|
|
||||||
![output](tests/cmd.png)
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
Setting the name of the logged program (it matters for Windows OS):
|
Setting the name of the logged program (it matters for Windows OS):
|
||||||
|
|
||||||
```d
|
```d
|
||||||
log.program("My program");
|
log.name("My program");
|
||||||
```
|
|
||||||
|
|
||||||
Setting the status of color text output (`false` by default):
|
|
||||||
|
|
||||||
```d
|
|
||||||
log.color(true);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Setting the error output level:
|
Setting the error output level:
|
||||||
|
@ -89,4 +77,4 @@ log.d("Debugging message") => log.debugging("Debugging message");
|
||||||
|
|
||||||
## DUB
|
## DUB
|
||||||
|
|
||||||
Add a dependency on `"singlog": "~>0.4.0"`.
|
Add a dependency on `"singlog": "~>0.3.2"`.
|
||||||
|
|
2
dub.json
2
dub.json
|
@ -18,7 +18,7 @@
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"targetType": "executable",
|
"targetType": "executable",
|
||||||
"targetPath": "bin",
|
"targetPath": "bin",
|
||||||
"targetName": "test",
|
"targetName": "app",
|
||||||
"importPaths": ["source","tests"],
|
"importPaths": ["source","tests"],
|
||||||
"sourcePaths": ["tests"]
|
"sourcePaths": ["tests"]
|
||||||
}
|
}
|
||||||
|
|
207
source/singlog.d
207
source/singlog.d
|
@ -2,7 +2,7 @@ module singlog;
|
||||||
|
|
||||||
version(Windows)
|
version(Windows)
|
||||||
import core.sys.windows.windows;
|
import core.sys.windows.windows;
|
||||||
else version(Posix)
|
else
|
||||||
import core.sys.posix.syslog;
|
import core.sys.posix.syslog;
|
||||||
|
|
||||||
import std.string;
|
import std.string;
|
||||||
|
@ -19,9 +19,7 @@ alias log = Log.msg;
|
||||||
|
|
||||||
---
|
---
|
||||||
// Setting the name of the logged program
|
// Setting the name of the logged program
|
||||||
log.program("My program");
|
log.name("My program");
|
||||||
// Setting the status of color text output
|
|
||||||
log.color(true);
|
|
||||||
// Setting the error output level
|
// Setting the error output level
|
||||||
log.level(log.DEBUGGING);
|
log.level(log.DEBUGGING);
|
||||||
log.level(log.ALERT);
|
log.level(log.ALERT);
|
||||||
|
@ -48,107 +46,40 @@ alias log = Log.msg;
|
||||||
+/
|
+/
|
||||||
class Log {
|
class Log {
|
||||||
private:
|
private:
|
||||||
static Log _log;
|
static Log log;
|
||||||
string _path;
|
string path;
|
||||||
wstring _name = "singlog";
|
string nameProgram = "singlog";
|
||||||
bool _writeToFile = true;
|
bool writeToFile = true;
|
||||||
bool _ccolor = false;
|
|
||||||
|
|
||||||
this() {}
|
this() {}
|
||||||
|
|
||||||
version(Windows) {
|
version(Windows) {
|
||||||
int[] _sysPriority = [0, 1, 1, 1, 2, 3, 3];
|
public enum {
|
||||||
|
DEBUGGING = 0,
|
||||||
WORD[] _sysPriorityOS = [
|
ALERT = 1,
|
||||||
|
CRITICAL = 1,
|
||||||
|
ERROR = 1,
|
||||||
|
WARNING = 2,
|
||||||
|
NOTICE = 3,
|
||||||
|
INFORMATION = 3,
|
||||||
|
}
|
||||||
|
WORD[] sysLevel = [
|
||||||
EVENTLOG_SUCCESS,
|
EVENTLOG_SUCCESS,
|
||||||
EVENTLOG_ERROR_TYPE,
|
EVENTLOG_ERROR_TYPE,
|
||||||
EVENTLOG_WARNING_TYPE,
|
EVENTLOG_WARNING_TYPE,
|
||||||
EVENTLOG_INFORMATION_TYPE
|
EVENTLOG_INFORMATION_TYPE
|
||||||
];
|
];
|
||||||
|
|
||||||
void writesyslog(string message, WORD priority) {
|
void syslog(WORD priority, LPCSTR message) {
|
||||||
import std.utf: toUTF16z;
|
HANDLE handleEventLog = RegisterEventSourceA(NULL, this.nameProgram.toStringz());
|
||||||
auto wMessage = message.toUTF16z();
|
|
||||||
HANDLE handleEventLog = RegisterEventSourceW(NULL, this._name.ptr);
|
|
||||||
|
|
||||||
if (handleEventLog == NULL)
|
if (handleEventLog == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ReportEventW(handleEventLog, priority, 0, 0, NULL, 1, 0, &wMessage, NULL);
|
ReportEventA(handleEventLog, priority, 0, 0, NULL, 1, 0, &message, NULL);
|
||||||
DeregisterEventSource(handleEventLog);
|
DeregisterEventSource(handleEventLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
WORD[] _color = [
|
|
||||||
FOREGROUND_GREEN, // green
|
|
||||||
FOREGROUND_BLUE, // blue
|
|
||||||
FOREGROUND_RED | FOREGROUND_BLUE, // magenta
|
|
||||||
FOREGROUND_RED, // red
|
|
||||||
FOREGROUND_RED | FOREGROUND_GREEN, // yellow
|
|
||||||
FOREGROUND_BLUE | FOREGROUND_GREEN, // cyan
|
|
||||||
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN // white
|
|
||||||
];
|
|
||||||
|
|
||||||
void colorTextOutput(string time, wstring message, int priority) {
|
|
||||||
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
CONSOLE_SCREEN_BUFFER_INFO defaultConsole;
|
|
||||||
GetConsoleScreenBufferInfo(handle, &defaultConsole);
|
|
||||||
|
|
||||||
writef("%s ", time);
|
|
||||||
SetConsoleTextAttribute(handle, this._color[priority] | FOREGROUND_INTENSITY);
|
|
||||||
write(this._type[priority]);
|
|
||||||
SetConsoleTextAttribute(handle, this._color[priority]);
|
|
||||||
WriteConsoleW(handle, message.ptr, cast(DWORD)message.length, NULL, NULL);
|
|
||||||
SetConsoleTextAttribute(handle, defaultConsole.wAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void defaultTextOutput(string time, wstring message, int priority) {
|
|
||||||
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
writef("%s %s", time, this._type[priority]);
|
|
||||||
WriteConsoleW(handle, message.ptr, cast(DWORD)message.length, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void writestdout(string time, string message, int priority) {
|
|
||||||
wstring wMessage = " %s\n".format(message).to!wstring;
|
|
||||||
this._ccolor ?
|
|
||||||
colorTextOutput(time, wMessage, priority) :
|
|
||||||
defaultTextOutput(time, wMessage, priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else version(Posix) {
|
} else version(Posix) {
|
||||||
int[] _sysPriority = [0, 1, 2, 3, 4, 5, 6];
|
|
||||||
|
|
||||||
int[] _sysPriorityOS = [
|
|
||||||
LOG_DEBUG,
|
|
||||||
LOG_ALERT,
|
|
||||||
LOG_CRIT,
|
|
||||||
LOG_ERR,
|
|
||||||
LOG_WARNING,
|
|
||||||
LOG_NOTICE,
|
|
||||||
LOG_INFO
|
|
||||||
];
|
|
||||||
|
|
||||||
string[] _color = [
|
|
||||||
"\x1b[1;32m%s\x1b[0;32m %s\x1b[0;0m", // green
|
|
||||||
"\x1b[1;34m%s\x1b[0;34m %s\x1b[0;0m", // blue
|
|
||||||
"\x1b[1;35m%s\x1b[0;35m %s\x1b[0;0m", // magenta
|
|
||||||
"\x1b[1;31m%s\x1b[0;31m %s\x1b[0;0m", // red
|
|
||||||
"\x1b[1;33m%s\x1b[0;33m %s\x1b[0;0m", // yellow
|
|
||||||
"\x1b[1;36m%s\x1b[0;36m %s\x1b[0;0m", // cyan
|
|
||||||
"\x1b[1;97m%s\x1b[0;97m %s\x1b[0;0m", // white
|
|
||||||
];
|
|
||||||
|
|
||||||
void writestdout(string time, string message, int priority) {
|
|
||||||
writefln("%s %s",
|
|
||||||
time,
|
|
||||||
(this._ccolor ? this._color[priority] : "%s %s").format(this._type[priority], message)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void writesyslog(string message, int priority) {
|
|
||||||
syslog(priority, message.toStringz());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum {
|
public enum {
|
||||||
DEBUGGING = 0,
|
DEBUGGING = 0,
|
||||||
ALERT = 1,
|
ALERT = 1,
|
||||||
|
@ -158,16 +89,16 @@ version(Windows) {
|
||||||
NOTICE = 5,
|
NOTICE = 5,
|
||||||
INFORMATION = 6
|
INFORMATION = 6
|
||||||
}
|
}
|
||||||
|
int[] sysLevel = [
|
||||||
string[] _type = [
|
LOG_DEBUG,
|
||||||
"[DEBUG]:",
|
LOG_ALERT,
|
||||||
"[ALERT]:",
|
LOG_CRIT,
|
||||||
"[CRITICAL]:",
|
LOG_ERR,
|
||||||
"[ERROR]:",
|
LOG_WARNING,
|
||||||
"[WARNING]:",
|
LOG_NOTICE,
|
||||||
"[NOTICE]:",
|
LOG_INFO
|
||||||
"[INFO]:"
|
|
||||||
];
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public enum {
|
public enum {
|
||||||
SYSLOG = 1,
|
SYSLOG = 1,
|
||||||
|
@ -175,49 +106,48 @@ version(Windows) {
|
||||||
FILE = 4
|
FILE = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
int _output = STDOUT;
|
int msgOutput = STDOUT;
|
||||||
int _priority = INFORMATION;
|
int msgLevel = INFORMATION;
|
||||||
|
|
||||||
void writelog(string message, int priority) {
|
void writeLog(string message, string type, int msgLevel) {
|
||||||
string time;
|
if (this.msgLevel > msgLevel)
|
||||||
if (this._priority > priority)
|
|
||||||
return;
|
return;
|
||||||
if (this._output & 1)
|
if (this.msgOutput & 1)
|
||||||
writesyslog(message, _sysPriorityOS[_sysPriority[priority]]);
|
syslog(sysLevel[msgLevel], message.toStringz());
|
||||||
if (this._output & 6)
|
if (this.msgOutput & 6)
|
||||||
time = Clock.currTime().format("%Y.%m.%d %H:%M:%S");
|
message = format("%s [%s]: %s", Clock.currTime().format("%Y.%m.%d %H:%M:%S"), type, message);
|
||||||
if (this._output & 2)
|
if (this.msgOutput & 2)
|
||||||
writestdout(time, message, priority);
|
writeln(message);
|
||||||
if (this._output & 4)
|
if (this.msgOutput & 4)
|
||||||
writefile(time, message, priority);
|
writeFile(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writefile(string time, string message, int priority) {
|
void writeFile(string message) {
|
||||||
if (!this._writeToFile)
|
if (!this.writeToFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!this._path.exists) {
|
if (!this.path.exists) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
File file;
|
File file;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
file = File(this._path, "a+");
|
file = File(this.path, "a+");
|
||||||
this._writeToFile = true;
|
this.writeToFile = true;
|
||||||
} 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.information(e);
|
this.information(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
file.writefln("%s %s %s", time, this._type[priority], message);
|
file.writeln(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.information(e);
|
this.information(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -225,8 +155,8 @@ version(Windows) {
|
||||||
try {
|
try {
|
||||||
file.close();
|
file.close();
|
||||||
} 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.information(e);
|
this.information(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -234,25 +164,24 @@ version(Windows) {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@property static Log msg() {
|
@property static Log msg() {
|
||||||
if (this._log is null)
|
if (this.log is null)
|
||||||
this._log = new Log;
|
this.log = new Log;
|
||||||
|
|
||||||
return this._log;
|
return this.log;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log output(int outs) { this._output = outs; return this._log; }
|
Log output(int msgOutput) { this.msgOutput = msgOutput; return this.log; }
|
||||||
Log program(string name) { this._name = name.to!wstring; return this._log; }
|
Log name(string nameProgram) { this.nameProgram = nameProgram; return this.log; }
|
||||||
Log file(string path) { this._path = path; return this._log; }
|
Log file(string path) { this.path = path; return this.log; }
|
||||||
Log level(int priority) { this._priority = priority; return this._log; }
|
Log level(int msgLevel) { this.msgLevel = msgLevel; return this.log; }
|
||||||
Log color(bool condition) { this._ccolor = condition; return this._log; }
|
|
||||||
|
|
||||||
void alert(T)(T message) { writelog(message.to!string, ALERT); }
|
void alert(T)(T message) { writeLog(message.to!string, "ALERT", ALERT); }
|
||||||
void critical(T)(T message) { writelog(message.to!string, CRITICAL); }
|
void critical(T)(T message) { writeLog(message.to!string, "CRITICAL", CRITICAL); }
|
||||||
void error(T)(T message) { writelog(message.to!string, ERROR); }
|
void error(T)(T message) { writeLog(message.to!string, "ERROR", ERROR); }
|
||||||
void warning(T)(T message) { writelog(message.to!string, WARNING); }
|
void warning(T)(T message) { writeLog(message.to!string, "WARNING", WARNING); }
|
||||||
void notice(T)(T message) { writelog(message.to!string, NOTICE); }
|
void notice(T)(T message) { writeLog(message.to!string, "NOTICE", NOTICE); }
|
||||||
void information(T)(T message) { writelog(message.to!string, INFORMATION); }
|
void information(T)(T message) { writeLog(message.to!string, "INFORMATION", INFORMATION); }
|
||||||
void debugging(T)(T message) { writelog(message.to!string, DEBUGGING); }
|
void debugging(T)(T message) { writeLog(message.to!string, "DEBUGGING", DEBUGGING); }
|
||||||
|
|
||||||
alias a = alert;
|
alias a = alert;
|
||||||
alias c = critical;
|
alias c = critical;
|
||||||
|
|
BIN
tests/cmd.png
BIN
tests/cmd.png
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
Before Width: | Height: | Size: 51 KiB |
12
tests/test.d
12
tests/test.d
|
@ -2,16 +2,12 @@ import singlog;
|
||||||
|
|
||||||
void main(string[] argv) {
|
void main(string[] argv) {
|
||||||
log.output(log.SYSLOG | log.STDOUT | log.FILE) // write to syslog, standard output stream and file
|
log.output(log.SYSLOG | log.STDOUT | log.FILE) // write to syslog, standard output stream and file
|
||||||
.program(argv[0]) // program name as an identifier (for Windows OS)
|
.name(argv[0]) // program name as an identifier (for Windows OS)
|
||||||
.level(log.DEBUGGING) // logging level
|
.level(log.DEBUGGING) // logging level
|
||||||
.color(true) // color text output
|
|
||||||
.file("./test.log"); // the path to the log file
|
.file("./test.log"); // the path to the log file
|
||||||
|
|
||||||
log.i("This is an information message");
|
|
||||||
log.n("This is a notice message");
|
|
||||||
log.w("This is a warning message");
|
|
||||||
log.e("This is an error message");
|
log.e("This is an error message");
|
||||||
log.c("This is a critical message");
|
log.error("And this is also an error message");
|
||||||
log.a("This is an alert message");
|
log.w("This is a warning message");
|
||||||
log.d("This is a debug message");
|
log.i("This is an information message");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue