From: Aki Tuomi Date: Thu, 30 Aug 2018 11:23:10 +0000 (+0300) Subject: lib-sql: Add events X-Git-Tag: 2.3.4~92 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5c98b165a59df94becafd1fb6181440bbe697a4b;p=thirdparty%2Fdovecot%2Fcore.git lib-sql: Add events --- diff --git a/src/lib-sql/sql-api-private.h b/src/lib-sql/sql-api-private.h index bbc763ce0a..5355f31635 100644 --- a/src/lib-sql/sql-api-private.h +++ b/src/lib-sql/sql-api-private.h @@ -35,6 +35,15 @@ enum sql_db_state { ((db)->state == SQL_DB_STATE_IDLE) #define SQL_ERRSTR_NOT_CONNECTED "Not connected to database" +/* What is considered slow query */ +#define SQL_SLOW_QUERY_MSEC 1000 + +#define SQL_QUERY_FINISHED "sql_query_finished" +#define SQL_CONNECTION_FINISHED "sql_connection_finished" +#define SQL_TRANSACTION_FINISHED "sql_transaction_finished" + +#define SQL_QUERY_FINISHED_FMT "Finished query '%s' in %u msecs" + struct sql_db_module_register { unsigned int id; }; @@ -45,6 +54,8 @@ union sql_db_module_context { extern struct sql_db_module_register sql_db_module_register; +extern struct event_category event_category_sql; + struct sql_transaction_query { struct sql_transaction_query *next; struct sql_transaction_context *trans; @@ -121,6 +132,8 @@ struct sql_db { void *context); void *state_change_context; + struct event *event; + enum sql_db_state state; /* last time we started connecting to this server (which may or may not have succeeded) */ @@ -129,6 +142,11 @@ struct sql_db { unsigned int connect_failure_count; struct timeout *to_reconnect; + uint64_t succeeded_queries; + uint64_t failed_queries; + /* includes both succeeded and failed */ + uint64_t slow_queries; + bool no_reconnect:1; }; @@ -183,6 +201,7 @@ struct sql_result { unsigned int map_size; struct sql_field_map *map; void *fetch_dest; + struct event *event; size_t fetch_dest_size; enum sql_result_error_type error_type; @@ -193,6 +212,7 @@ struct sql_result { struct sql_transaction_context { struct sql_db *db; + struct event *event; /* commit() must use this query list if head is non-NULL. */ struct sql_transaction_query *head, *tail; @@ -214,4 +234,9 @@ void sql_transaction_add_query(struct sql_transaction_context *ctx, pool_t pool, const char *query, unsigned int *affected_rows); const char *sql_statement_get_query(struct sql_statement *stmt); +void sql_connection_log_finished(struct sql_db *db); +struct event_passthrough * +sql_query_finished_event(struct sql_db *db, struct event *event, const char *query, + bool success, int *duration_r); +struct event_passthrough *sql_transaction_finished_event(struct sql_transaction_context *ctx); #endif diff --git a/src/lib-sql/sql-api.c b/src/lib-sql/sql-api.c index 95ce32b991..7be2230757 100644 --- a/src/lib-sql/sql-api.c +++ b/src/lib-sql/sql-api.c @@ -4,6 +4,7 @@ #include "array.h" #include "ioloop.h" #include "str.h" +#include "time-util.h" #include "sql-api-private.h" #include @@ -13,6 +14,10 @@ struct default_sql_prepared_statement { char *query_template; }; +struct event_category event_category_sql = { + .name = "sql", +}; + struct sql_db_module_register sql_db_module_register = { 0 }; ARRAY_TYPE(sql_drivers) sql_drivers; @@ -92,9 +97,11 @@ int sql_init_full(const struct sql_settings *set, struct sql_db **db_r, } if ((driver->flags & SQL_DB_FLAG_POOLED) == 0) { - if (driver->v.init_full == NULL) + if (driver->v.init_full == NULL) { db = driver->v.init(set->connect_string); - else + db->event = event_create(set->event_parent); + event_add_category(db->event, &event_category_sql); + } else ret = driver->v.init_full(set, &db, error_r); } else ret = driver_sqlpool_init_full(set, driver, &db, error_r); @@ -719,6 +726,51 @@ void sql_transaction_add_query(struct sql_transaction_context *ctx, pool_t pool, ctx->tail = tquery; } +void sql_connection_log_finished(struct sql_db *db) +{ + struct event_passthrough *e = event_create_passthrough(db->event)-> + set_name(SQL_CONNECTION_FINISHED); + e_debug(e->event(), + "Connection finished (queries=%"PRIu64", slow queries=%"PRIu64")", + db->succeeded_queries + db->failed_queries, + db->slow_queries); +} + +struct event_passthrough * +sql_query_finished_event(struct sql_db *db, struct event *event, const char *query, + bool success, int *duration_r) +{ + int diff; + struct timeval tv; + event_get_create_time(event, &tv); + struct event_passthrough *e = event_create_passthrough(event)-> + set_name(SQL_QUERY_FINISHED)-> + add_str("query_first_word", t_strcut(query, ' ')); + diff = timeval_diff_msecs(&ioloop_timeval, &tv); + + if (!success) { + db->failed_queries++; + } else { + db->succeeded_queries++; + } + + if (diff >= SQL_SLOW_QUERY_MSEC) { + e->add_str("slow_query", "y"); + db->slow_queries++; + } + + if (duration_r != NULL) + *duration_r = diff; + + return e; +} + +struct event_passthrough *sql_transaction_finished_event(struct sql_transaction_context *ctx) +{ + return event_create_passthrough(ctx->event)-> + set_name(SQL_TRANSACTION_FINISHED); +} + struct sql_result sql_not_connected_result = { .v = { sql_result_not_connected_free, diff --git a/src/lib-sql/sql-api.h b/src/lib-sql/sql-api.h index 7e4fd33800..f2aca6927d 100644 --- a/src/lib-sql/sql-api.h +++ b/src/lib-sql/sql-api.h @@ -73,6 +73,7 @@ struct sql_commit_result { struct sql_settings { const char *driver; const char *connect_string; + struct event *event_parent; }; typedef void sql_query_callback_t(struct sql_result *result, void *context);