-
-
Notifications
You must be signed in to change notification settings - Fork 321
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/sql auditing #1370
Feature/sql auditing #1370
Conversation
architecture of current implementation of sql auditing can't be combined with the project's architecture which (projects) have logs system like |
dev/sql_auditing.h
Outdated
std::string destination_file = "sql_auditor.txt"; | ||
friend class sql_auditor; | ||
sql_auditor_settings() {} | ||
inline static sql_auditor_settings& settings() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if the app has >1 storages and author wants to write logs to different files for different storages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the destination file could be part of the storage_base object but then we could not log the initial instructions (i.e. make_storage) -- what if we want to see the SQL emitted by make_storage()? What do you think? is storage_base the place to put the sql_auditor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the call to sql_auditor::log() occurs in util.h, how do we know which storage it belongs to? I am talking about e.g. void perform_exec()??? we only know the sqlite3* but that does not map to storage so its no use
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could intercept on_open to register every connection used by a storage_base?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and create a map of sqlite3* pointers and storage_base* pointers!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think? is storage_base the place to put the sql_auditor?
I don't think we need sql_auditor
at all but it is up to you
dev/sql_auditing.h
Outdated
static void log(const std::string& message); | ||
}; | ||
|
||
class sql_auditor_settings { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
different classes better be put in different files like so: one file for one class/enum/struct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok - one question about namespace: what to use here? namespace sqlite_orm or global namespace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't use global namespace in the lib cause it may lead to collisions in the user code
dev/sql_auditing.h
Outdated
@@ -0,0 +1,86 @@ | |||
#pragma once | |||
#include <fstream> | |||
#include "error_code.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
put ""
include after <>
include like it is done everywhere within this repo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
dev/sql_auditing.h
Outdated
#include "error_code.h" | ||
#include <chrono> | ||
#include <ctime> // For std::localtime and std::tm | ||
#include <iomanip> // For std::put_time |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please skip For
, just write expressions for which this include is required how it is done everywhere within this repo
dev/sql_auditing.h
Outdated
open(); | ||
} | ||
|
||
inline void sql_auditor_settings::set_destination_file(const std::string& filename) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one can refactor argument to accepts std::string
by value not by reference and to move it. It can skip one extra copying of std::string
dev/sql_auditing.h
Outdated
if(!log_file.is_open()) { | ||
log_file.open(sql_auditor_settings::settings().destination_file, ios::trunc | ios::out); | ||
if(!log_file.good()) { | ||
throw std::system_error{sqlite_orm::orm_error_code::failure_to_init_logfile}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens if this exception is fired, caught, the app is executing further and calls sql_auditor::log
?
dev/sql_auditing.h
Outdated
std::tm local_time = *std::localtime(&now_time); | ||
|
||
// Print the local time in a human-readable format | ||
auditor().log_file << "@: " << std::put_time(&local_time, sql_auditor_settings::settings().format_str.c_str()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if the user of sqlite_orm
wants to use sql auditor but doesn't want @
symbol to be put in the logs?
@@ -14,6 +14,14 @@ TEST_CASE("Prepared select") { | |||
|
|||
auto filename = "prepared.sqlite"; | |||
remove(filename); | |||
|
|||
#define JD_AUDITING_SETTINGS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the purpose of lines 18 and 19? you define a value and next you check whether it is defined (and it is definitely defined)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its the way I mark tentative code...
experimental code...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is useless cause it never goes in branch, it goes the same way in all the conditions so if you drop it nothing will change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
architecture of current implementation of sql auditing can't be combined with the project's architecture which (projects) have logs system like boost::log or custom written ones. How this approach is going to wok in projects which use boost::log for example?
@@ -14,6 +14,14 @@ TEST_CASE("Prepared select") { | |||
|
|||
auto filename = "prepared.sqlite"; | |||
remove(filename); | |||
|
|||
#define JD_AUDITING_SETTINGS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is useless cause it never goes in branch, it goes the same way in all the conditions so if you drop it nothing will change
class storage_base; | ||
} | ||
} | ||
using sqlite_orm::internal::storage_base; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this using
is here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using is used here because log_settings and log_admin are declared in the glocal namespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't use global namespace in the lib code
status = stats; | ||
global_settings = glob_settings; | ||
} | ||
log_settings() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need default constructor here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need a default constructor for log_settings because we provide a default constructor for log_admin!!
std::shared_ptr<std::ofstream> log_file; | ||
std::string log_file_name; | ||
std::string time_format; | ||
enum status_code { FAIL, GOOD } status = status_code::FAIL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avoid using non-class enums cause old enums add their constants into global scope
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
}; | ||
|
||
inline std::shared_ptr<std::ofstream> get_file(std::string log_file_name) { | ||
static std::map<std::string, std::shared_ptr<std::ofstream>> files; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need to keep file streams in a static map? better avoid static vars at all cause it is not thread safe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__the other alternative would be a global object;....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't use global/static objects cause it it not thread safe and break the architecture. Global object is anti-pattern
static std::map<std::string, std::shared_ptr<std::ofstream>> files; | ||
auto it = files.find(log_file_name); | ||
if(it == files.end()) { | ||
std::shared_ptr<std::ofstream> pointer_to_shared{new std::ofstream()}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use std::make_shared
instead of new
. Avoid using new
and delete
if you can
@@ -766,6 +766,9 @@ namespace sqlite_orm { | |||
if(this->on_open) { | |||
this->on_open(db); | |||
} | |||
// JD added |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this comment is useless cause git blame has info about authors of every line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
@@ -766,6 +766,9 @@ namespace sqlite_orm { | |||
if(this->on_open) { | |||
this->on_open(db); | |||
} | |||
// JD added | |||
log_admin::admin().register_db(this, db); | |||
// JD end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here: this comment is useless cause git blame has info about authors of every line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
Why do they break the architecture?Sent from my iPhoneOn 5 Jan 2025, at 4:07 AM, Yevgeniy Zakharov ***@***.***> wrote:
@fnc12 commented on this pull request.
In dev/sql_auditing.h:
+
+ std::time_t now_time = std::chrono::system_clock::to_time_t(now);
+
+ // Convert to local time (std::tm structure)
+ // WARNING: localtime is not thread safe!
+ std::tm local_time = *std::localtime(&now_time);
+
+ // Print the local time in a human-readable format
+ *log_file << "@: " << std::put_time(&local_time, time_format.c_str()) << " = ";
+ *log_file << message << std::endl;
+ }
+ }
+};
+
+inline std::shared_ptr<std::ofstream> get_file(std::string log_file_name) {
+ static std::map<std::string, std::shared_ptr<std::ofstream>> files;
don't use global/static objects cause it it not thread safe and break the architecture. Global object is anti-pattern
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you authored the thread.Message ID: ***@***.***>
|
Cause global object (singleton) is anti-pattern. If we can avoid it we have to avoid it |
Which is the global/static object you refer to?Sent from my iPhoneOn 5 Jan 2025, at 10:28 AM, Juan Dent ***@***.***> wrote:Why do they break the architecture?Sent from my iPhoneOn 5 Jan 2025, at 4:07 AM, Yevgeniy Zakharov ***@***.***> wrote:
@fnc12 commented on this pull request.
In dev/sql_auditing.h:
+
+ std::time_t now_time = std::chrono::system_clock::to_time_t(now);
+
+ // Convert to local time (std::tm structure)
+ // WARNING: localtime is not thread safe!
+ std::tm local_time = *std::localtime(&now_time);
+
+ // Print the local time in a human-readable format
+ *log_file << "@: " << std::put_time(&local_time, time_format.c_str()) << " = ";
+ *log_file << message << std::endl;
+ }
+ }
+};
+
+inline std::shared_ptr<std::ofstream> get_file(std::string log_file_name) {
+ static std::map<std::string, std::shared_ptr<std::ofstream>> files;
don't use global/static objects cause it it not thread safe and break the architecture. Global object is anti-pattern
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you authored the thread.Message ID: ***@***.***>
|
But I am using singleton patternSent from my iPhoneOn 5 Jan 2025, at 10:30 AM, Yevgeniy Zakharov ***@***.***> wrote:
Why do they break the architecture?
Cause global object (singleton) is anti-pattern. If we can avoid it we have to avoid it
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you authored the thread.Message ID: ***@***.***>
|
The one defined as static in a function and returns as a ref
This comment doesn't make any sense |
@juandent you are still ignoring this comment
It is the main issue with this PR. No reason to spend time on talking about singleton and other stuff until this one is solved |
“But I am using singleton pattern”
I am following Dimitri Nesteruk’ “Design patterns in Modern C++” and Fedor Pikus’ “Hands-on design patterns with C++” both of which implement a safe way for
Singletons.
So why so negative about the correct use of singletons?
Regards,
Juan
From: Yevgeniy Zakharov ***@***.***>
Sent: Sunday, January 5, 2025 10:49 AM
To: fnc12/sqlite_orm ***@***.***>
Cc: designPattern_OptimisticOfflineLock_sqlite_orm ***@***.***>; Author ***@***.***>
Subject: Re: [fnc12/sqlite_orm] Feature/sql auditing (PR #1370)
Which is the global/static object you refer to?
The one defined as static in a function and returns as a ref
But I am using singleton pattern
This comment doesn't make any sense
—
Reply to this email directly, view it on GitHub <#1370 (comment)> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/ABI6OFJQDXRWCTVVNJJ56YD2JFO7ZAVCNFSM6AAAAABT7X2B5SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNZRGY4DMMRQGA> .
You are receiving this because you authored the thread. <https://github.com/notifications/beacon/ABI6OFPARYGTX6KSTDSVMT32JFO7ZA5CNFSM6AAAAABT7X2B5SWGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTUZJDITQ.gif> Message ID: ***@***.*** ***@***.***> >
|
Good for you. Still it is not acceptable for |
This is no way to react!
“Good for you” you say! Can you be more sarcastic?
From: Yevgeniy Zakharov ***@***.***>
Sent: Sunday, January 5, 2025 11:25 AM
To: fnc12/sqlite_orm ***@***.***>
Cc: designPattern_OptimisticOfflineLock_sqlite_orm ***@***.***>; Mention ***@***.***>
Subject: Re: [fnc12/sqlite_orm] Feature/sql auditing (PR #1370)
I am following Dimitri Nesteruk’ “Design patterns in Modern C++” and Fedor Pikus’ “Hands-on design patterns with C++” both of which implement a safe way for singletons.
Good for you. Still it is not acceptable for sqlite_orm cause singleton is anti-pattern
—
Reply to this email directly, view it on GitHub <#1370 (comment)> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/ABI6OFLB7TE35GRTYLF27VD2JFTIHAVCNFSM6AAAAABT7X2B5SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNZRGY4TKNZYHA> .
You are receiving this because you were mentioned. <https://github.com/notifications/beacon/ABI6OFOGQVFBM776UHJM6V32JFTIHA5CNFSM6AAAAABT7X2B5SWGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTUZJD3KY.gif> Message ID: ***@***.*** ***@***.***> >
|
I am not sarcastic at all. Please don't ignore my other comments |
Discussed in DM. Closing |
First implementation of sql_auditing -- testing use of it