Better logs

Now log are managed by the std log, did a custom log to print either
into a file or into the default io strout.

The plan is to create a scope in each file and log depending of stuff,
can also use it in library I think, if should still base by the custom
function.

Next step is logging a lot of stuff a bit everywhere.
This commit is contained in:
Adrien Bouvais 2024-10-26 17:30:58 +02:00
parent 9d39d47c3b
commit c5f931cf04
3 changed files with 121 additions and 102 deletions

View File

@ -100,61 +100,6 @@ pub const FileEngine = struct {
}
};
// --------------------Logs--------------------
// Make a lib out of it I think, like ZipponData, a ZipponLog
const Level = enum {
Debug,
Info,
Warning,
Error,
Critical,
};
pub fn resetLog(self: FileEngine, file_name: []const u8) void {
const path = std.fmt.allocPrint(self.allocator, "{s}/LOG/{s}.log", .{ self.path_to_ZipponDB_dir, file_name }) catch return;
defer self.allocator.free(path);
std.fs.cwd().deleteFile(path) catch {};
_ = std.fs.cwd().createFile(path, .{}) catch return;
}
pub fn createLog(self: FileEngine, file_name: []const u8) void {
const path = std.fmt.allocPrint(self.allocator, "{s}/LOG/{s}.log", .{ self.path_to_ZipponDB_dir, file_name }) catch return;
defer self.allocator.free(path);
_ = std.fs.cwd().createFile(path, .{}) catch return;
}
pub fn log(self: FileEngine, file_name: []const u8, level: Level, comptime format: []const u8, args: anytype) void {
const path = std.fmt.allocPrint(self.allocator, "{s}/LOG/{s}.log", .{ self.path_to_ZipponDB_dir, file_name }) catch return;
defer self.allocator.free(path);
const file = std.fs.cwd().openFile(path, .{ .mode = .write_only }) catch return;
defer file.close();
file.seekFromEnd(0) catch return;
const writer = file.writer();
const now = DateTime.now();
// TODO: Use a format to add the 0 to be 00:00 and not 0:0
var date_format_buffer = std.ArrayList(u8).init(self.allocator);
defer date_format_buffer.deinit();
now.format("YYYY/MM/DD-HH:mm:ss.SSSS", date_format_buffer.writer()) catch return;
writer.print("Time: {s} - ", .{date_format_buffer.items}) catch return;
switch (level) {
.Debug => writer.print("Debug - ", .{}) catch return,
.Info => writer.print("Info - ", .{}) catch return,
.Warning => writer.print("Warning - ", .{}) catch return,
.Error => writer.print("Error - ", .{}) catch return,
.Critical => writer.print("Critical - ", .{}) catch return,
}
writer.print(format, args) catch return;
writer.writeByte('\n') catch return;
}
// --------------------Other--------------------
pub fn readSchemaFile(allocator: Allocator, sub_path: []const u8, buffer: []u8) FileEngineError!usize {
@ -234,9 +179,14 @@ pub const FileEngine = struct {
path_buff = std.fmt.allocPrint(self.allocator, "{s}/LOG", .{self.path_to_ZipponDB_dir}) catch return FileEngineError.MemoryError;
cwd.makeDir(path_buff) catch |err| switch (err) {
error.PathAlreadyExists => {},
error.PathAlreadyExists => return,
else => return FileEngineError.CantMakeDir,
};
self.allocator.free(path_buff);
path_buff = std.fmt.allocPrint(self.allocator, "{s}/LOG/log", .{self.path_to_ZipponDB_dir}) catch return FileEngineError.MemoryError;
_ = cwd.createFile(path_buff, .{}) catch return FileEngineError.CantMakeFile;
}
/// Request a path to a schema file and then create the struct folder

View File

@ -2,6 +2,7 @@ const std = @import("std");
const Allocator = std.mem.Allocator;
// TODO: Clean that
const DateTime = @import("types/date.zig").DateTime;
const FileEngine = @import("fileEngine.zig").FileEngine;
const cliTokenizer = @import("tokenizers/cli.zig").Tokenizer;
const cliToken = @import("tokenizers/cli.zig").Token;
@ -25,6 +26,48 @@ const State = enum {
end,
};
const log_allocator = std.heap.page_allocator;
var log_buff: [1024]u8 = undefined;
var log_path: []const u8 = undefined;
const log = std.log.scoped(.cli);
pub const std_options = .{
.logFn = myLog,
};
pub fn myLog(
comptime message_level: std.log.Level,
comptime scope: @Type(.EnumLiteral),
comptime format: []const u8,
args: anytype,
) void {
const level_txt = comptime message_level.asText();
const prefix = if (scope == .default) " - " else "(" ++ @tagName(scope) ++ ") - ";
const potential_file: ?std.fs.File = std.fs.cwd().openFile(log_path, .{ .mode = .write_only }) catch null;
const now = DateTime.now();
var date_format_buffer = std.ArrayList(u8).init(log_allocator);
defer date_format_buffer.deinit();
now.format("YYYY/MM/DD-HH:mm:ss.SSSS", date_format_buffer.writer()) catch return;
if (potential_file) |file| {
file.seekFromEnd(0) catch return;
const writer = file.writer();
writer.print("{s}{s}Time: {s} - ", .{ level_txt, prefix, date_format_buffer.items }) catch return;
writer.print(format, args) catch return;
writer.writeByte('\n') catch return;
file.close();
} else {
const writer = std.io.getStdErr().writer();
writer.print("{s}{s}Time: {s} - ", .{ level_txt, prefix, date_format_buffer.items }) catch return;
writer.print(format, args) catch return;
writer.writeByte('\n') catch return;
}
}
// TODO: If an argument is given when starting the binary, it is the db path
pub fn main() !void {
var state: State = .expect_main_command;
@ -36,48 +79,9 @@ pub fn main() !void {
.leak => std.log.debug("We fucked it up bro...\n", .{}),
};
const path_env_variable = utils.getEnvVariables(allocator, "ZIPPONDB_PATH");
var file_engine: FileEngine = undefined;
var file_engine = try initFileEngine.init(allocator, null);
defer file_engine.deinit();
if (path_env_variable) |path| {
std.debug.print("Found envirionment variable ZIPPONDB_PATH: {s}.\n", .{path});
var to_init = true;
_ = std.fs.cwd().openDir(path, .{}) catch {
std.debug.print("{s} directory not found, creating it\n", .{path});
std.fs.cwd().makeDir(path) catch {
std.debug.print("{s} couldnt be make. Please use 'db new' or 'db use'.\n", .{path});
file_engine = FileEngine.init(allocator, "");
to_init = false;
};
};
if (to_init) {
file_engine = FileEngine.init(allocator, path);
try file_engine.checkAndCreateDirectories();
//file_engine.createLog("main");
file_engine.log("main", .Info, "Found envirionment variable ZIPPONDB_PATH: {s}", .{path});
}
// Check if the db have a schema
if (!file_engine.isSchemaFileInDir()) {
std.debug.print("Database don't have any schema. Checking if ZIPPONDB_SCHEMA env variable exist.\n", .{});
const schema_env_variable = utils.getEnvVariables(allocator, "ZIPPONDB_SCHEMA");
if (schema_env_variable) |schema| {
std.debug.print("Found envirionment variable ZIPPONDB_SCHEMA {s}.\n", .{schema});
file_engine.initDataFolder(schema) catch {
std.debug.print("Couldn't use {s} as schema.\n", .{schema});
};
} else {
std.debug.print("No envirionment variable ZIPPONDB_SCHEMA found.\n", .{});
}
} else {
std.debug.print("Database have a schema.\n", .{});
}
} else {
std.debug.print("No envirionment variable ZIPPONDB_PATH found.\n", .{});
file_engine = FileEngine.init(allocator, "");
}
const line_buf = try allocator.alloc(u8, BUFFER_SIZE);
defer allocator.free(line_buf);
@ -86,7 +90,7 @@ pub fn main() !void {
const line = try std.io.getStdIn().reader().readUntilDelimiterOrEof(line_buf, '\n');
if (line) |line_str| {
file_engine.log("main", .Info, "Query received: {s}", .{line_str});
log.debug("Query received: {s}", .{line_str});
const null_term_line_str = try allocator.dupeZ(u8, line_str[0..line_str.len]);
defer allocator.free(null_term_line_str);
@ -175,7 +179,7 @@ pub fn main() !void {
.expect_path_to_db => switch (token.tag) {
.identifier => {
file_engine.deinit();
file_engine = FileEngine.init(allocator, try allocator.dupe(u8, toker.getTokenSlice(token)));
file_engine = try initFileEngine.init(allocator, try allocator.dupe(u8, toker.getTokenSlice(token)));
send("Successfully started using the database!", .{});
state = .end;
},
@ -273,7 +277,10 @@ pub fn main() !void {
.quit, .end => unreachable,
};
if (state == .quit) break;
if (state == .quit) {
log.info("Bye bye\n", .{});
break;
}
}
}
}
@ -287,7 +294,7 @@ pub fn runQuery(null_term_query_str: [:0]const u8, file_engine: *FileEngine) voi
var parser = ziqlParser.init(allocator, &toker, file_engine);
parser.parse() catch |err| {
file_engine.log("main", .Error, "Error parsing: {any}", .{err});
log.err("Error parsing: {any}", .{err});
};
switch (gpa.deinit()) {
@ -296,4 +303,66 @@ pub fn runQuery(null_term_query_str: [:0]const u8, file_engine: *FileEngine) voi
}
}
// TODO: Put that in the FileEngine
/// Simple struct to manage the init of the FileEngine, mostly managing if env path is here and init the directories, ect
const initFileEngine = struct {
fn init(allocator: std.mem.Allocator, potential_path: ?[]const u8) !FileEngine {
if (potential_path) |p| {
log_path = try std.fmt.bufPrint(&log_buff, "{s}/LOG/log", .{p});
log.info("Start using database path: {s}.", .{p});
return try initWithPath(allocator, p);
}
const path = utils.getEnvVariable(allocator, "ZIPPONDB_PATH");
defer if (path) |p| allocator.free(p);
if (path) |p| {
log_path = try std.fmt.bufPrint(&log_buff, "{s}/LOG/log", .{p});
log.info("Found environment variable ZIPPONDB_PATH: {s}.", .{p});
return try initWithPath(allocator, p);
} else {
log.info("No environment variable ZIPPONDB_PATH found.", .{});
return FileEngine.init(allocator, "");
}
}
fn initWithPath(allocator: std.mem.Allocator, path: []const u8) !FileEngine {
try ensureDirectoryExists(path);
var file_engine = FileEngine.init(allocator, path);
try file_engine.checkAndCreateDirectories();
if (!file_engine.isSchemaFileInDir()) {
try initSchema(allocator, &file_engine);
} else {
std.debug.print("Database has a schema.\n", .{});
}
return file_engine;
}
fn ensureDirectoryExists(path: []const u8) !void {
_ = std.fs.cwd().openDir(path, .{}) catch |err| {
if (err == error.FileNotFound) {
log.info("{s} directory not found, creating it\n", .{path});
try std.fs.cwd().makeDir(path);
return;
} else {
return err;
}
};
}
fn initSchema(allocator: std.mem.Allocator, file_engine: *FileEngine) !void {
log.debug("Database doesn't have any schema. Checking if ZIPPONDB_SCHEMA env variable exists.", .{});
const schema = utils.getEnvVariable(allocator, "ZIPPONDB_SCHEMA");
defer if (schema) |s| allocator.free(s);
if (schema) |s| {
log.debug("Found environment variable ZIPPONDB_SCHEMA: {s}.", .{s});
file_engine.initDataFolder(s) catch {
std.debug.print("Couldn't use {s} as schema.\n", .{s});
};
} else {
log.debug("No environment variable ZIPPONDB_SCHEMA found.", .{});
}
}
};

View File

@ -1,7 +1,7 @@
const std = @import("std");
const ZipponError = @import("errors.zig").ZipponError;
pub fn getEnvVariables(allocator: std.mem.Allocator, variable: []const u8) ?[]const u8 {
pub fn getEnvVariable(allocator: std.mem.Allocator, variable: []const u8) ?[]const u8 {
var env_map = std.process.getEnvMap(allocator) catch return null;
defer env_map.deinit();