refs #5563 rowExcludeField, excludeRegex, excludeFields
gitea/mylogger/pipeline/head This commit looks good Details

This commit is contained in:
Juan Ferrer 2023-06-07 15:32:43 +02:00
parent 0eb7c9e98e
commit 512bd56a2c
6 changed files with 82 additions and 48 deletions

View File

@ -1,10 +1,14 @@
upperCaseTable: true upperCaseTable: true
userField: userField: editorFk
- editorFk rowExcludeField: logExclude
excludeRegex: '__$'
showFields: showFields:
- name - name
- description - description
- nickname - nickname
excludeFields:
- created
- updated
castTypes: castTypes:
tinyint: boolean tinyint: boolean
logs: logs:

View File

@ -65,23 +65,13 @@ module.exports = class ModelLoader {
? toUpperCamelCase(table.name) ? toUpperCamelCase(table.name)
: table.name; : table.name;
} }
const {
showField,
relation,
idName
} = tableConf;
Object.assign(tableInfo, { Object.assign(tableInfo, {
conf: tableConf, conf: tableConf,
exclude: new Set(tableConf.exclude),
modelName, modelName,
showField, relation: tableConf.relation
relation,
idName,
userField: tableConf.userField || conf.userField
}); });
return tableInfo; return tableInfo;
} }
} }
@ -89,10 +79,31 @@ module.exports = class ModelLoader {
async loadSchema() { async loadSchema() {
const {db, schemaMap} = this.logger; const {db, schemaMap} = this.logger;
const {conf} = this; const {conf} = this;
const excludeFields = new Set(conf.excludeFields);
const excludeRegex = conf.excludeRegex
? new RegExp(conf.excludeRegex) : null;
const localProps = [
'idName'
];
const globalProps = [
'showField',
'userField',
'rowExcludeField'
];
for (const [schema, table, tableInfo] of schemaMap) { for (const [schema, table, tableInfo] of schemaMap) {
const tableConf = tableInfo.conf; const tableConf = tableInfo.conf;
for (const prop of localProps)
tableInfo[prop] = tableConf[prop];
for (const prop of globalProps)
tableInfo[prop] = tableConf[prop] !== undefined
? tableConf[prop]
: conf[prop];
// Fetch columns & types // Fetch columns & types
Object.assign (tableInfo, { Object.assign (tableInfo, {
@ -113,9 +124,17 @@ module.exports = class ModelLoader {
WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?`, WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?`,
[table, schema] [table, schema]
); );
const exclude = new Set(tableConf.exclude);
exclude.add(tableInfo.userField);
for (const {col, type, def} of dbCols) { for (const {col, type, def} of dbCols) {
if (!tableInfo.exclude.has(col) && col != tableInfo.userField) const isExcluded =
excludeFields.has(col)
|| (excludeRegex && excludeRegex.test(col))
|| exclude.has(col);
if (!isExcluded)
tableInfo.columns.set(col, {type, def}); tableInfo.columns.set(col, {type, def});
const castType = conf.castTypes[type]; const castType = conf.castTypes[type];
@ -125,7 +144,7 @@ module.exports = class ModelLoader {
// Fetch primary key // Fetch primary key
if (!tableConf.idName) { if (!tableInfo.idName) {
const [dbPks] = await db.query( const [dbPks] = await db.query(
`SELECT COLUMN_NAME idName `SELECT COLUMN_NAME idName
FROM information_schema.KEY_COLUMN_USAGE FROM information_schema.KEY_COLUMN_USAGE
@ -146,9 +165,9 @@ module.exports = class ModelLoader {
// Get show field // Get show field
if (!tableInfo.isMain) { const {showField} = tableInfo;
const {showField} = tableInfo; if (showField !== null && !tableInfo.isMain) {
if (!showField) { if (showField === undefined) {
for (const field of conf.showFields) { for (const field of conf.showFields) {
if (tableInfo.columns.has(field)) { if (tableInfo.columns.has(field)) {
tableInfo.showField = field; tableInfo.showField = field;
@ -159,8 +178,7 @@ module.exports = class ModelLoader {
const match = showField.match(/(^.*)\$$/); const match = showField.match(/(^.*)\$$/);
if (match) tableInfo.showRelation = match[1]; if (match) tableInfo.showRelation = match[1];
} }
} else }
tableInfo.showField = null;
} }
// Fetch relation to main table // Fetch relation to main table

View File

@ -9,19 +9,20 @@ module.exports = class ShowDb {
logger, logger,
conf: logger.conf.showCache, conf: logger.conf.showCache,
tables: new MultiMap(), tables: new MultiMap(),
valueDb: new MultiMap() cache: new MultiMap()
}); });
} }
checkDb() { checkDb() {
const {conf, valueDb} = this; const {conf, cache} = this;
const now = Date.now();
const dbOutdated = this.loops % conf.maxLoops == 0 const dbOutdated = this.loops % conf.maxLoops == 0
|| this.lastFlush > Date.now() + conf.life * 1000 || this.lastFlush > now + conf.life * 1000
if (dbOutdated) { if (dbOutdated) {
valueDb.clear(); cache.clear();
this.loops = 0; this.loops = 0;
this.lastFlush = Date.now(); this.lastFlush = now;
} }
this.loops++; this.loops++;
} }
@ -134,8 +135,8 @@ module.exports = class ShowDb {
} }
async getValues(db, ops) { async getValues(db, ops) {
const {tables, valueDb} = this; const {tables, cache} = this;
const showIds = new MultiMap(); const fetchMap = new MultiMap();
this.checkDb(); this.checkDb();
@ -164,11 +165,11 @@ module.exports = class ShowDb {
const {schema, table} = relation; const {schema, table} = relation;
const id = row[col]; const id = row[col];
let ids = valueDb.get(schema, table); let ids = cache.get(schema, table);
if (ids && ids.has(id)) continue; if (ids && ids.has(id)) continue;
ids = showIds.get(schema, table); ids = fetchMap.get(schema, table);
if (!ids) showIds.set(schema, table, ids = new Set()); if (!ids) fetchMap.set(schema, table, ids = new Set());
ids.add(id); ids.add(id);
} }
} }
@ -176,18 +177,18 @@ module.exports = class ShowDb {
// Query show values to database // Query show values to database
for (const [schema, table, ids] of showIds) { for (const [schema, table, fetchIds] of fetchMap) {
const tableInfo = tables.get(schema, table); const tableInfo = tables.get(schema, table);
const [res] = await db.query( const [res] = await db.query(
tableInfo.selectStmt, tableInfo.selectStmt,
[Array.from(ids.keys())] [Array.from(fetchIds.keys())]
); );
let cacheIds = valueDb.get(schema, table); let ids = cache.get(schema, table);
if (!cacheIds) valueDb.set(schema, table, cacheIds = new Map()); if (!ids) cache.set(schema, table, ids = new Map());
for (const row of res) for (const row of res)
cacheIds.set(row.id, row.val); ids.set(row.id, row.val);
} }
// Fill rows with show values // Fill rows with show values
@ -225,7 +226,7 @@ module.exports = class ShowDb {
function getValue(relation, row, col) { function getValue(relation, row, col) {
const {schema, table} = relation; const {schema, table} = relation;
const ids = valueDb.get(schema, table); const ids = cache.get(schema, table);
return ids && ids.get(row[col]) return ids && ids.get(row[col])
} }
} }

View File

@ -227,8 +227,8 @@ module.exports = class MyLogger {
await new Promise(resolve => { await new Promise(resolve => {
zongji.ctrlConnection.query('KILL ?', [zongji.connection.threadId], zongji.ctrlConnection.query('KILL ?', [zongji.connection.threadId],
err => { err => {
if (err && err.code !== 'ER_NO_SUCH_THREAD') // if (err && err.code !== 'ER_NO_SUCH_THREAD');
logError(err); // console.error(err);
resolve(); resolve();
}); });
}); });
@ -313,8 +313,15 @@ module.exports = class MyLogger {
if (!tableInfo) return; if (!tableInfo) return;
const action = actions[eventName]; const action = actions[eventName];
const columns = tableInfo.columns; const {
let changes = []; columns,
rowExcludeField
} = tableInfo;
const changes = [];
function isExcluded(row) {
return rowExcludeField && row[rowExcludeField];
}
function castValue(col, value) { function castValue(col, value) {
switch(tableInfo.castTypes.get(col)) { switch(tableInfo.castTypes.get(col)) {
@ -348,11 +355,13 @@ module.exports = class MyLogger {
if (action == 'update') { if (action == 'update') {
for (const row of evt.rows) { for (const row of evt.rows) {
let nColsChanged = 0;
const before = row.before;
const after = row.after; const after = row.after;
if (isExcluded(after)) continue;
const before = row.before;
const oldI = {}; const oldI = {};
const newI = {}; const newI = {};
let nColsChanged = 0;
for (const col in before) { for (const col in before) {
if (columns.has(col) if (columns.has(col)
@ -370,6 +379,8 @@ module.exports = class MyLogger {
const cols = columns.keys(); const cols = columns.keys();
for (const row of evt.rows) { for (const row of evt.rows) {
if (isExcluded(row)) continue;
const instance = {}; const instance = {};
for (const col of cols) { for (const col of cols) {
if (row[col] !== null) if (row[col] !== null)

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "mylogger", "name": "mylogger",
"version": "0.1.24", "version": "1.0.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "mylogger", "name": "mylogger",
"version": "0.1.24", "version": "1.0.0",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"colors": "^1.4.0", "colors": "^1.4.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "mylogger", "name": "mylogger",
"version": "0.1.24", "version": "1.0.0",
"author": "Verdnatura Levante SL", "author": "Verdnatura Levante SL",
"description": "MySQL and MariaDB logger using binary log", "description": "MySQL and MariaDB logger using binary log",
"license": "GPL-3.0", "license": "GPL-3.0",