ISEPOS-2280 Added base loggers scripts #1

Open
ymlesni wants to merge 8 commits from ymlesni/shared-snippets:feature/ISEPOS-2280-mechanizm-raportowania-informacji-z-aplikacji-do-pliku-z-logami into main
3 changed files with 89 additions and 50 deletions
Showing only changes of commit 039cfe081e - Show all commits

View File

@ -34,10 +34,15 @@
%
% delete() - Destructor method that closes the file identifier when the logger is deleted.
%
% Example usage:
% Example Usage:
% logger = base_logger.getInstance();
% logger.info('This is an info message');
% logger.error('This is an error message');
% logger.info('Some info')
%
Outdated
Review

Can we put here an example with error object? So that the stack trace of the exception gets logged.

Can we put here an example with error object? So that the stack trace of the exception gets logged.

Base logger has been enchanced and example for error logging has been added.

Base logger has been enchanced and example for error logging has been added.
% try
% error('Simulated error for stack trace logging');
% catch err
% logger.error('An error occurred:', err);
% end
%
% See also: fopen, fclose, dbstack, fprintf
@ -58,14 +63,14 @@ classdef base_logger < handle
methods(Access=private)
function this = base_logger()
this.fid = fopen(getenv("DEFAULT_LOG_PATH"), 'a');
this.fid = fopen(getenv("APP_LOG_FILE"), 'a');
if this.fid == -1
error('Failed to open log file: application.log');
error('Failed to open log file');
asia marked this conversation as resolved Outdated
Outdated
Review

Can we use a different name? Something that we would consider a log file at first glance ('fallbackPath' is something I wouldn't) - if we don't want to make it too simple, to avoid name collision with other things, maybe e.g. base-app-log.log or base-logger-log.log or something like that

Can we use a different name? Something that we would consider a log file at first glance ('fallbackPath' is something I wouldn't) - if we don't want to make it too simple, to avoid name collision with other things, maybe e.g. base-app-log.log or base-logger-log.log or something like that
end
end
function log(this, level, message)
current_time = datetime('now', 'Format', 'yyyy-MM-dd HH:mm:ss');
function log(this, level, varargin)
current_time = datestr(now, 'yyyy-mm-dd HH:MM:SS');
stack = dbstack('-completenames');
if length(stack) > 2
script_name = stack(3).name;
@ -73,33 +78,48 @@ classdef base_logger < handle
script_name = 'Unknown';
end
if this.fid ~= -1
fprintf(this.fid, '%s %s %s %s\n', char(current_time), level, script_name, message);
else
error('File identifier is invalid. Cannot write to log.');
message = "";
for i = 1:numel(varargin)
if isa(varargin{i}, 'MException')
message = sprintf('%sError: %s\n', message, varargin{i}.message);
for j = 1:length(varargin{i}.stack)
message = sprintf('%s at %s (line %d)\n', message, varargin{i}.stack(j).name, varargin{i}.stack(j).line);
end
elseif isnumeric(varargin{i}) || isenum(varargin{i}) || islogical(varargin{i})
message = strcat(message, string(varargin{i}));
elseif ischar(varargin{i}) || isstring(varargin{i})
message = strcat(message, varargin{i});
else
message = strcat(message, 'Unsupported data type');
end
if i < numel(varargin)
message = strcat(message, ", ");
end
end
fprintf(this.fid, '%s %s %s %s\n', current_time, level, script_name, message);
end
end
methods(Access=public)
function trace(this, message)
this.log("TRACE", message);
function trace(this, varargin)
this.log('TRACE', varargin{:});
end
function debug(this, message)
this.log("DEBUG", message);
function debug(this, varargin)
this.log('DEBUG', varargin{:});
end
function info(this, message)
this.log("INFO", message);
function info(this, varargin)
this.log('INFO', varargin{:});
end
function warning(this, message)
this.log("WARNING", message);
function warning(this, varargin)
this.log('WARNING', varargin{:});
end
function error(this, message)
this.log("ERROR", message);
function error(this, varargin)
this.log('ERROR', varargin{:});
end
function delete(this)

View File

@ -34,19 +34,24 @@
%
% delete() - Destructor method that closes the file identifier when the logger is deleted.
%
% Example usage:
% Example Usage:
% logger = base_logger.getInstance();
% logger.info('This is an info message');
% logger.error('This is an error message');
% logger.info('Some info')
%
% try
% error('Simulated error for stack trace logging');
% catch err
% logger.error('An error occurred:', err);
% end
%
% See also: fopen, fclose, dbstack, fprintf
classdef base_logger < handle
properties(Access=private)
properties
fid;
end
methods(Static, Access = public)
methods(Static)
function obj = getInstance()
persistent instance;
if isempty(instance)
@ -56,15 +61,15 @@ classdef base_logger < handle
end
end
methods(Access=private)
methods
function this = base_logger()
this.fid = fopen(getenv("DEFAULT_LOG_PATH"), 'a');
this.fid = fopen(getenv("APP_LOG_FILE"), 'a');
if this.fid == -1
error('Failed to open log file: application.log');
error('Failed to open log file');
end
end
function log(this, level, message)
function log(this, level, varargin)
current_time = strftime('%Y-%m-%d %H:%M:%S', localtime(time()));
stack = dbstack('-completenames');
if length(stack) > 2
@ -73,33 +78,47 @@ classdef base_logger < handle
script_name = 'Unknown';
end
if this.fid ~= -1
fprintf(this.fid, '%s %s %s %s\n', char(current_time), level, script_name, message);
message = sprintf('');
for i = 1:numel(varargin)
if isstruct(varargin{i}) && isfield(varargin{i}, 'message') && isfield(varargin{i}, 'stack')
error_info = varargin{i};
message = sprintf('%sError: %s\n', message, error_info.message);
for j = 1:length(error_info.stack)
message = sprintf('%s at %s (line %d)\n', message, error_info.stack(j).name, error_info.stack(j).line);
end
elseif isnumeric(varargin{i}) || islogical(varargin{i})
message = sprintf('%s%s', message, num2str(varargin{i}));
elseif ischar(varargin{i}) || isstring(varargin{i})
message = sprintf('%s%s', message, varargin{i});
else
error('File identifier is invalid. Cannot write to log.');
message = sprintf('%sUnsupported data type', message);
end
if i < numel(varargin)
message = sprintf('%s, ', message);
end
end
methods(Access=public)
function trace(this, message)
this.log("TRACE", message);
fprintf(this.fid, '%s %s %s %s\n', current_time, level, script_name, message);
end
function debug(this, message)
this.log("DEBUG", message);
function trace(this, varargin)
this.log('TRACE', varargin{:});
end
function info(this, message)
this.log("INFO", message);
function debug(this, varargin)
this.log('DEBUG', varargin{:});
end
function warning(this, message)
this.log("WARNING", message);
function info(this, varargin)
this.log('INFO', varargin{:});
end
function error(this, message)
this.log("ERROR", message);
function warning(this, varargin)
this.log('WARNING', varargin{:});
end
function error(this, varargin)
this.log('ERROR', varargin{:});
end
function delete(this)

View File

@ -46,7 +46,7 @@ def getDefaultLogger(name):
"""
Outdated
Review

Maybe just put here some placeholder meaning that this is a code that may produce an error

Maybe just put here some placeholder meaning that this is a code that may produce an error

Ok, I will do the same for Matlab and Octave versions.

Ok, I will do the same for Matlab and Octave versions.
logger = logging.getLogger(name)
if not logger.hasHandlers():
Outdated
Review

We have except Exception as e but the e is not used anywhere... is this correct?

We have `except Exception as e` but the `e` is not used anywhere... is this correct?

Maybe it is good to use here the logger.exception() (doc) method as a showcase.

Maybe it is good to use here the `logger.exception()` ([doc](https://docs.python.org/3/library/logging.html#logging.Logger.exception)) method as a showcase.

e could be used to process exception further, but it is not necessary for example, I will remove it.
Would adding logger.exception() as a additional option be a good idea (to still showcase how to log exception at chosen log level)? For now I will change to logger.exception().

`e` could be used to process exception further, but it is not necessary for example, I will remove it. Would adding `logger.exception()` as a additional option be a good idea (to still showcase how to log exception at chosen log level)? For now I will change to `logger.exception()`.
file_handler = logging.FileHandler(os.environ['DEFAULT_LOG_PATH'], mode='a')
file_handler = logging.FileHandler(os.environ['APP_LOG_FILE'], mode='a')
formatter = logging.Formatter('%(asctime)s,%(msecs)d %(levelname)s %(name)s %(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)