diff --git a/packages/api/src/controllers/files.js b/packages/api/src/controllers/files.js index 1cf350ac2..120ccba78 100644 --- a/packages/api/src/controllers/files.js +++ b/packages/api/src/controllers/files.js @@ -1,7 +1,7 @@ const fs = require('fs-extra'); const path = require('path'); const crypto = require('crypto'); -const { filesdir, archivedir, resolveArchiveFolder, uploadsdir, appdir } = require('../utility/directories'); +const { filesdir, archivedir, resolveArchiveFolder, uploadsdir, appdir, jsldir } = require('../utility/directories'); const getChartExport = require('../utility/getChartExport'); const { hasPermission } = require('../utility/hasPermission'); const socket = require('../utility/socket'); @@ -13,7 +13,7 @@ const dbgateApi = require('../shell'); const { getLogger } = require('dbgate-tools'); const platformInfo = require('../utility/platformInfo'); const { checkSecureFilePathsWithoutDirectory, checkSecureDirectories } = require('../utility/security'); -const { AppLogDatastore, getRecentAppLogRecords } = require('../utility/AppLogDatastore'); +const { copyAppLogsIntoFile, getRecentAppLogRecords } = require('../utility/appLogStore'); const logger = getLogger('files'); function serialize(format, data) { @@ -29,9 +29,6 @@ function deserialize(format, text) { } module.exports = { - currentLogReader: null, - currentLogParamsKey: null, - list_meta: true, async list({ folder }, req) { if (!hasPermission(`files/${folder}/read`, req)) return []; @@ -316,19 +313,14 @@ module.exports = { return true; }, - getAppLog_meta: true, - async getAppLog({ offset = 0, limit = 100, dateFrom = 0, dateTo = new Date().getTime(), filters = {} }) { - const paramsKey = `${dateFrom}-${dateTo}`; - if (paramsKey != this.currentLogParamsKey) { - if (this.currentLogReader) { - this.currentLogReader._closeReader(); - this.currentLogReader = null; - } - this.currentLogReader = new AppLogDatastore({ timeFrom: dateFrom, timeTo: dateTo }); - this.currentLogParamsKey = paramsKey; - } - - return this.currentLogReader.getRows(offset, limit, filters); + fillAppLogs_meta: true, + async fillAppLogs({ dateFrom = 0, dateTo = new Date().getTime() }) { + const jslid = crypto.randomUUID(); + const outputFile = path.join(jsldir(), `${jslid}.jsonl`); + await copyAppLogsIntoFile(dateFrom, dateTo, outputFile); + return { + jslid, + }; }, getRecentAppLog_meta: true, diff --git a/packages/api/src/index.js b/packages/api/src/index.js index 8883767ed..17f55ed7a 100644 --- a/packages/api/src/index.js +++ b/packages/api/src/index.js @@ -33,7 +33,7 @@ if (processArgs.processDisplayName) { // } function configureLogger() { - const { initializeRecentLogProvider, pushToRecentLogs } = require('./utility/AppLogDatastore'); + const { initializeRecentLogProvider, pushToRecentLogs } = require('./utility/appLogStore'); initializeRecentLogProvider(); const logsFilePath = path.join(logsdir(), `${moment().format('YYYY-MM-DD-HH-mm')}-${process.pid}.ndjson`); diff --git a/packages/api/src/proc/databaseConnectionProcess.js b/packages/api/src/proc/databaseConnectionProcess.js index 4684fee5f..cf3b42639 100644 --- a/packages/api/src/proc/databaseConnectionProcess.js +++ b/packages/api/src/proc/databaseConnectionProcess.js @@ -6,7 +6,6 @@ const { extractIntSettingsValue, getLogger, isCompositeDbName, - dbNameLogCategory, extractErrorMessage, extractErrorLogData, ScriptWriterEval, @@ -45,6 +44,14 @@ function getStatusCounter() { return statusCounter; } +function getLogInfo() { + return { + database: dbhan ? dbhan.database : undefined, + conid: dbhan ? dbhan.conid : undefined, + engine: storedConnection ? storedConnection.engine : undefined, + }; +} + async function checkedAsyncCall(promise) { try { const res = await promise; @@ -131,10 +138,10 @@ async function readVersion() { const driver = requireEngineDriver(storedConnection); try { const version = await driver.getVersion(dbhan); - logger.debug(`DBGM-00037 Got server version: ${version.version}`); + logger.debug(getLogInfo(), `DBGM-00037 Got server version: ${version.version}`); serverVersion = version; } catch (err) { - logger.error(extractErrorLogData(err), 'DBGM-00149 Error getting DB server version'); + logger.error(extractErrorLogData(err, getLogInfo()), 'DBGM-00149 Error getting DB server version'); serverVersion = { version: 'Unknown' }; } process.send({ msgtype: 'version', version: serverVersion }); @@ -148,9 +155,8 @@ async function handleConnect({ connection, structure, globalSettings }) { const driver = requireEngineDriver(storedConnection); dbhan = await checkedAsyncCall(connectUtility(driver, storedConnection, 'app')); logger.debug( - `DBGM-00038 Connected to database, driver: ${storedConnection.engine}, separate schemas: ${ - storedConnection.useSeparateSchemas ? 'YES' : 'NO' - }, 'DB: ${dbNameLogCategory(dbhan.database)}` + getLogInfo(), + `DBGM-00038 Connected to database, separate schemas: ${storedConnection.useSeparateSchemas ? 'YES' : 'NO'}` ); dbhan.feedback = feedback => setStatus({ feedback }); await checkedAsyncCall(readVersion()); @@ -257,13 +263,16 @@ async function handleDriverDataCore(msgid, callMethod, { logName }) { const result = await callMethod(driver); process.send({ msgtype: 'response', msgid, result: serializeJsTypesForJsonStringify(result) }); } catch (err) { - logger.error(extractErrorLogData(err, { logName }), `DBGM-00150 Error when handling message ${logName}`); + logger.error( + extractErrorLogData(err, { logName, ...getLogInfo() }), + `DBGM-00150 Error when handling message ${logName}` + ); process.send({ msgtype: 'response', msgid, errorMessage: extractErrorMessage(err, 'Error executing DB data') }); } } async function handleSchemaList({ msgid }) { - logger.debug('DBGM-00039 Loading schema list'); + logger.debug(getLogInfo(), 'DBGM-00039 Loading schema list'); return handleDriverDataCore(msgid, driver => driver.listSchemas(dbhan), { logName: 'listSchemas' }); } @@ -351,7 +360,7 @@ async function handleSqlPreview({ msgid, objects, options }) { process.send({ msgtype: 'response', msgid, sql: dmp.s, isTruncated: generator.isTruncated }); if (generator.isUnhandledException) { setTimeout(async () => { - logger.error('DBGM-00151 Exiting because of unhandled exception'); + logger.error(getLogInfo(), 'DBGM-00151 Exiting because of unhandled exception'); await driver.close(dbhan); process.exit(0); }, 500); @@ -485,7 +494,7 @@ function start() { setInterval(async () => { const time = new Date().getTime(); if (time - lastPing > 40 * 1000) { - logger.info('DBGM-00040 Database connection not alive, exiting'); + logger.info(getLogInfo(), 'DBGM-00040 Database connection not alive, exiting'); const driver = requireEngineDriver(storedConnection); await driver.close(dbhan); process.exit(0); @@ -497,7 +506,7 @@ function start() { try { await handleMessage(message); } catch (err) { - logger.error(extractErrorLogData(err), 'DBGM-00041 Error in DB connection'); + logger.error(extractErrorLogData(err, getLogInfo()), 'DBGM-00041 Error in DB connection'); process.send({ msgtype: 'error', error: extractErrorMessage(err, 'DBGM-00042 Error processing message'), diff --git a/packages/api/src/utility/JsonLinesDatastore.js b/packages/api/src/utility/JsonLinesDatastore.js index d92a6b088..107002796 100644 --- a/packages/api/src/utility/JsonLinesDatastore.js +++ b/packages/api/src/utility/JsonLinesDatastore.js @@ -12,10 +12,9 @@ const { jsldir } = require('./directories'); const LineReader = require('./LineReader'); class JsonLinesDatastore { - constructor(file, formatterFunction, resolveNextFile = null) { + constructor(file, formatterFunction) { this.file = file; this.formatterFunction = formatterFunction; - this.resolveNextFile = resolveNextFile; this.reader = null; this.readedDataRowCount = 0; this.readedSchemaRow = false; @@ -23,12 +22,10 @@ class JsonLinesDatastore { this.notifyChangedCallback = null; this.currentFilter = null; this.currentSort = null; - this.currentFileName = null; if (formatterFunction) { const requirePluginFunction = require('./requirePluginFunction'); this.rowFormatter = requirePluginFunction(formatterFunction); } - this.sortedFiles = {}; } @@ -72,7 +69,6 @@ class JsonLinesDatastore { // this.firstRowToBeReturned = null; this.currentFilter = null; this.currentSort = null; - this.currentFileName = null; await reader.close(); } @@ -106,18 +102,8 @@ class JsonLinesDatastore { // return res; // } for (;;) { - let line = await this.reader.readLine(); - while (!line) { - if (!this.currentSort && this.resolveNextFile) { - const nextFile = await this.resolveNextFile(this.currentFileName); - if (nextFile) { - await this.reader.close(); - this.reader = await this._openReader(nextFile); - this.currentFileName = nextFile; - line = await this.reader.readLine(); - continue; - } - } + const line = await this.reader.readLine(); + if (!line) { // EOF return null; } @@ -189,7 +175,6 @@ class JsonLinesDatastore { } if (!this.reader) { const reader = await this._openReader(sort ? this.sortedFiles[stableStringify(sort)] : this.file); - this.currentFileName = this.file; this.reader = reader; this.currentFilter = filter; this.currentSort = sort; diff --git a/packages/api/src/utility/AppLogDatastore.js b/packages/api/src/utility/appLogStore.js similarity index 54% rename from packages/api/src/utility/AppLogDatastore.js rename to packages/api/src/utility/appLogStore.js index ec9a7588e..6d4cfa4cd 100644 --- a/packages/api/src/utility/AppLogDatastore.js +++ b/packages/api/src/utility/appLogStore.js @@ -17,75 +17,6 @@ async function getLogFiles(timeFrom, timeTo) { return logFiles.sort().map(x => path.join(dir, x)); } -class AppLogDatastore { - constructor({ timeFrom, timeTo }) { - this.timeFrom = timeFrom; - this.timeTo = timeTo; - } - - async resolveNextFile(file) { - const files = await getLogFiles(this.timeFrom, this.timeTo); - const index = files.indexOf(file); - if (index < 0 || index >= files.length - 1) return null; - return files[index + 1]; - } - - async getRows(offset = 0, limit = 100, filters = {}) { - if (!this.linesReader) { - const files = await getLogFiles(this.timeFrom, this.timeTo); - this.linesReader = new JsonLinesDatastore(files[0], null, file => this.resolveNextFile(file)); - } - - const conditions = [ - { - conditionType: 'binary', - operator: '>=', - left: { exprType: 'column', columnName: 'time' }, - right: { exprType: 'value', value: this.timeFrom }, - }, - { - conditionType: 'binary', - operator: '<=', - left: { exprType: 'column', columnName: 'time' }, - right: { exprType: 'value', value: this.timeTo }, - }, - ]; - for (const [key, values] of Object.entries(filters)) { - if (values.length == 1 && values[0] == null) { - // @ts-ignore - conditions.push({ - conditionType: 'isNull', - expr: { exprType: 'column', columnName: key }, - }); - continue; - } - // @ts-ignore - conditions.push({ - conditionType: 'in', - expr: { exprType: 'column', columnName: key }, - values, - }); - } - - return this.linesReader.getRows( - offset, - limit, - { - conditionType: 'and', - conditions, - }, - null - ); - } - - _closeReader() { - if (this.linesReader) { - this.linesReader._closeReader(); - this.linesReader = null; - } - } -} - const RECENT_LOG_LIMIT = 1000; let recentLogs = null; @@ -97,6 +28,27 @@ function adjustRecentLogs() { } } +async function copyAppLogsIntoFile(timeFrom, timeTo, fileName) { + const writeStream = fs.createWriteStream(fileName); + + for (const file of await getLogFiles(timeFrom, timeTo)) { + const readStream = fs.createReadStream(file); + const reader = new LineReader(readStream); + do { + const line = await reader.readLine(); + if (line == null) break; + try { + const logEntry = JSON.parse(line); + if (logEntry.time >= timeFrom && logEntry.time <= timeTo) { + writeStream.write(JSON.stringify(logEntry) + '\n'); + } + } catch (e) { + continue; + } + } while (true); + } +} + async function initializeRecentLogProvider() { const logs = []; for (const file of await getLogFiles(startOfDay(new Date()), new Date())) { @@ -141,8 +93,8 @@ function getRecentAppLogRecords() { } module.exports = { - AppLogDatastore, initializeRecentLogProvider, getRecentAppLogRecords, pushToRecentLogs, + copyAppLogsIntoFile, }; diff --git a/packages/api/src/utility/connectUtility.js b/packages/api/src/utility/connectUtility.js index 121c5e126..fe0b23e77 100644 --- a/packages/api/src/utility/connectUtility.js +++ b/packages/api/src/utility/connectUtility.js @@ -132,7 +132,7 @@ async function connectUtility(driver, storedConnection, connectionMode, addition connection.ssl = await extractConnectionSslParams(connection); - const conn = await driver.connect({ ...connection, ...additionalOptions }); + const conn = await driver.connect({ conid: connectionLoaded?._id, ...connection, ...additionalOptions }); return conn; } diff --git a/packages/sqltree/src/utility.ts b/packages/sqltree/src/utility.ts index e9b3e9829..d91354c32 100644 --- a/packages/sqltree/src/utility.ts +++ b/packages/sqltree/src/utility.ts @@ -83,3 +83,44 @@ export function selectKeysFromTable(options: { }; return res; } + +export function createLogCompoudCondition( + fieldFilters: { [field: string]: string[] }, + timeColumn: string, + timeFrom: number, + timeTo: number +): Condition { + const conditions: Condition[] = [ + { + conditionType: 'binary', + operator: '>=', + left: { exprType: 'column', columnName: timeColumn }, + right: { exprType: 'value', value: timeFrom }, + }, + { + conditionType: 'binary', + operator: '<=', + left: { exprType: 'column', columnName: timeColumn }, + right: { exprType: 'value', value: timeTo }, + }, + ]; + for (const [key, values] of Object.entries(fieldFilters)) { + if (values.length == 1 && values[0] == null) { + conditions.push({ + conditionType: 'isNull', + expr: { exprType: 'column', columnName: key }, + }); + continue; + } + conditions.push({ + conditionType: 'in', + expr: { exprType: 'column', columnName: key }, + values, + }); + } + + return { + conditionType: 'and', + conditions, + }; +} diff --git a/packages/tools/src/DatabaseAnalyser.ts b/packages/tools/src/DatabaseAnalyser.ts index 19ace2f52..3d938fe11 100644 --- a/packages/tools/src/DatabaseAnalyser.ts +++ b/packages/tools/src/DatabaseAnalyser.ts @@ -5,7 +5,7 @@ import _pick from 'lodash/pick'; import _compact from 'lodash/compact'; import { getLogger } from './getLogger'; import { type Logger } from 'pinomin'; -import { dbNameLogCategory, isCompositeDbName, splitCompositeDbName } from './schemaInfoTools'; +import { isCompositeDbName, splitCompositeDbName } from './schemaInfoTools'; import { extractErrorLogData } from './stringTools'; const logger = getLogger('dbAnalyser'); @@ -77,10 +77,12 @@ export class DatabaseAnalyser { return db; } + getLogDbInfo() { + return this.driver.getLogDbInfo(this.dbhan); + } + async fullAnalysis() { - logger.debug( - `DBGM-00126 Performing full analysis, DB=${dbNameLogCategory(this.dbhan.database)}, engine=${this.driver.engine}` - ); + logger.debug(this.getLogDbInfo(), 'DBGM-00126 Performing full analysis'); const res = this.addEngineField(await this._runAnalysis()); // console.log('FULL ANALYSIS', res); return res; @@ -101,9 +103,7 @@ export class DatabaseAnalyser { } async incrementalAnalysis(structure) { - logger.info( - `DBGM-00127 Performing incremental analysis, DB=${dbNameLogCategory(this.dbhan.database)}, engine=${this.driver.engine}` - ); + logger.info(this.getLogDbInfo(), 'DBGM-00127 Performing incremental analysis'); this.structure = structure; const modifications = await this.getModifications(); @@ -129,7 +129,7 @@ export class DatabaseAnalyser { this.modifications = structureModifications; if (structureWithRowCounts) this.structure = structureWithRowCounts; - logger.info({ modifications: this.modifications }, 'DBGM-00128 DB modifications detected:'); + logger.info({ ...this.getLogDbInfo(), modifications: this.modifications }, 'DBGM-00128 DB modifications detected'); return this.addEngineField(this.mergeAnalyseResult(await this._runAnalysis())); } @@ -274,7 +274,7 @@ export class DatabaseAnalyser { this.dbhan.feedback(obj); } if (obj && obj.analysingMessage) { - logger.debug(obj.analysingMessage); + logger.debug(this.getLogDbInfo(), obj.analysingMessage); } } @@ -347,10 +347,16 @@ export class DatabaseAnalyser { } try { const res = await this.driver.query(this.dbhan, sql); - this.logger.debug({ rows: res.rows.length, template }, `DBGM-00129 Loaded analyser query`); + this.logger.debug( + { ...this.getLogDbInfo(), rows: res.rows.length, template }, + `DBGM-00129 Loaded analyser query` + ); return res; } catch (err) { - logger.error(extractErrorLogData(err, { template }), 'DBGM-00130 Error running analyser query'); + logger.error( + extractErrorLogData(err, { template, ...this.getLogDbInfo() }), + 'DBGM-00130 Error running analyser query' + ); return { rows: [], isError: true, diff --git a/packages/tools/src/driverBase.ts b/packages/tools/src/driverBase.ts index 991c11ecc..9d5158d15 100644 --- a/packages/tools/src/driverBase.ts +++ b/packages/tools/src/driverBase.ts @@ -254,4 +254,12 @@ export const driverBase = { async writeQueryFromStream(dbhan, sql) { return null; }, + + getLogDbInfo(dbhan) { + return { + database: dbhan ? dbhan.database : undefined, + engine: this.engine, + conid: dbhan ? dbhan.conid : undefined, + }; + }, }; diff --git a/packages/tools/src/schemaInfoTools.ts b/packages/tools/src/schemaInfoTools.ts index 2737ee778..9c103f1ce 100644 --- a/packages/tools/src/schemaInfoTools.ts +++ b/packages/tools/src/schemaInfoTools.ts @@ -37,15 +37,15 @@ export function extractSchemaNameFromComposite(name: string) { return splitCompositeDbName(name)?.schema; } -export function dbNameLogCategory(database: string): string { - if (isCompositeDbName(database)) { - return '~composite'; - } - if (database) { - return '~simple'; - } - return '~nodb'; -} +// export function getDbNameLogFace(database: string): string { +// if (isCompositeDbName(database)) { +// return '~composite'; +// } +// if (database) { +// return '~simple'; +// } +// return '~nodb'; +// } export function compositeDbNameIfNeeded( connnection: { useSeparateSchemas: boolean }, diff --git a/packages/types/engines.d.ts b/packages/types/engines.d.ts index 12fba070f..4d8fd53b5 100644 --- a/packages/types/engines.d.ts +++ b/packages/types/engines.d.ts @@ -164,6 +164,7 @@ export interface FilterBehaviourProvider { export interface DatabaseHandle { client: TClient; database?: string; + conid?: string; feedback?: (message: any) => void; getDatabase?: () => any; connectionType?: string; @@ -336,6 +337,11 @@ export interface EngineDriver extends FilterBehaviourProvider { analyserClass?: any; dumperClass?: any; singleConnectionOnly?: boolean; + getLogDbInfo(dbhan: DatabaseHandle): { + database?: string; + engine: string; + conid?: string; + }; } export interface DatabaseModification { diff --git a/packages/web/src/tabs/AppLogTab.svelte b/packages/web/src/tabs/AppLogTab.svelte index 2ebf9c2bd..f32633fce 100644 --- a/packages/web/src/tabs/AppLogTab.svelte +++ b/packages/web/src/tabs/AppLogTab.svelte @@ -15,6 +15,10 @@ import Link from '../elements/Link.svelte'; import SelectField from '../forms/SelectField.svelte'; import { onDestroy, onMount, tick } from 'svelte'; + import DropDownButton from '../buttons/DropDownButton.svelte'; + import { showModal } from '../modals/modalTools'; + import ValueLookupModal from '../modals/ValueLookupModal.svelte'; + import { createLogCompoudCondition } from 'dbgate-sqltree'; let loadedRows = []; let loadedAll = false; @@ -26,8 +30,13 @@ let mode = 'recent'; let autoScroll = true; let domTable; + let jslid; - function formatValue(value) { + function formatPossibleUuid(value) { + const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; + if (_.isString(value) && value.match(uuidRegex)) { + return value.slice(0, 8); + } if (value == null) { return 'N/A'; } @@ -36,12 +45,16 @@ async function loadNextRows() { const pageSize = getIntSettingsValue('dataGrid.pageSize', 100, 5, 1000); - const rows = await apiCall('files/get-app-log', { + const rows = await apiCall('jsldata/get-rows', { + jslid, offset: loadedRows.length, limit: pageSize, - dateFrom: startOfDay(dateFilter[0]).getTime(), - dateTo: endOfDay(dateFilter[1]).getTime(), - filters, + filters: createLogCompoudCondition( + filters, + 'time', + startOfDay(dateFilter[0]).getTime(), + endOfDay(dateFilter[1]).getTime() + ), }); loadedRows = [...loadedRows, ...rows]; if (rows.length < 10) { @@ -68,7 +81,7 @@ startObserver(domLoadNext); } - async function reloadData() { + async function reloadData(createNewJslId = true) { switch (mode) { case 'recent': loadedRows = await apiCall('files/get-recent-app-log', { limit: 100 }); @@ -76,6 +89,13 @@ scrollToRecent(); break; case 'date': + if (createNewJslId) { + const resp = await apiCall('files/fill-app-logs', { + dateFrom: startOfDay(dateFilter[0]).getTime(), + dateTo: endOfDay(dateFilter[1]).getTime(), + }); + jslid = resp.jslid; + } loadedRows = []; loadedAll = false; break; @@ -87,7 +107,7 @@ ...filters, [field]: values, }; - reloadData(); + reloadData(false); } const ColumnNamesMap = { @@ -110,6 +130,17 @@ } } + function filterBy(field) { + showModal(ValueLookupModal, { + jslid, + field, + multiselect: true, + onConfirm: values => { + doSetFilter(field, values); + }, + }); + } + onMount(() => { apiOn('applog-event', handleLogMessage); reloadData(); @@ -155,6 +186,21 @@ reloadData(); }} /> +
+ filterBy('conid') }, + { text: 'Database', onClick: () => filterBy('database') }, + { text: 'Engine', onClick: () => filterBy('engine') }, + { text: 'Message code', onClick: () => filterBy('msgcode') }, + { text: 'Caller', onClick: () => filterBy('caller') }, + { text: 'Name', onClick: () => filterBy('name') }, + ]} + /> +
+ {#each Object.keys(filters) as filterKey}
{ColumnNamesMap[filterKey] || filterKey}: @@ -165,10 +211,10 @@ if (!filters[filterKey].length) { filters = _.omit(filters, filterKey); } - reloadData(); + reloadData(false); }} > - {formatValue(value)} + {formatPossibleUuid(value)} {/each}
@@ -183,6 +229,9 @@ Time Code Message + Connection + Database + Engine Caller Name @@ -203,13 +252,16 @@ {format(new Date(parseInt(row.time)), 'HH:mm:ss')} {row.msgcode || ''} {row.msg} + {formatPossibleUuid(row.conid) || ''} + {row.database || ''} + {row.engine?.includes('@') ? row.engine.split('@')[0] : row.engine || ''} {row.caller || ''} {row.name || ''} {#if index === selectedLogIndex} - + + {#if row.conid} +
+
Connection ID:
+ {#if mode == 'date'} + doSetFilter('conid', [row.conid])} + >{formatPossibleUuid(row.conid)} + {:else} + {formatPossibleUuid(row.conid)} + {/if} +
+ {/if} + {#if row.database} +
+
Database:
+ {#if mode == 'date'} + doSetFilter('database', [row.database])}>{row.database} + {:else} + {row.database} + {/if} +
+ {/if} + {#if row.engine} +
+
Engine:
+ {#if mode == 'date'} + doSetFilter('engine', [row.engine])}>{row.engine} + {:else} + {row.engine} + {/if} +
+ {/if} diff --git a/plugins/dbgate-plugin-mssql/src/backend/driver.js b/plugins/dbgate-plugin-mssql/src/backend/driver.js index cc0e85ed2..8d16e35b8 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/driver.js +++ b/plugins/dbgate-plugin-mssql/src/backend/driver.js @@ -96,6 +96,7 @@ const driver = { client, connectionType, database: conn.database, + conid: conn.conid, }; }, async close(dbhan) { diff --git a/plugins/dbgate-plugin-mysql/src/backend/drivers.js b/plugins/dbgate-plugin-mysql/src/backend/drivers.js index f8a362b2b..bd6bb5a02 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/drivers.js +++ b/plugins/dbgate-plugin-mysql/src/backend/drivers.js @@ -34,7 +34,8 @@ const drivers = driverBases.map(driverBase => ({ analyserClass: Analyser, async connect(props) { - const { server, port, user, password, database, ssl, isReadOnly, forceRowsAsObjects, socketPath, authType } = props; + const { conid, server, port, user, password, database, ssl, isReadOnly, forceRowsAsObjects, socketPath, authType } = + props; let awsIamToken = null; if (authType == 'awsIam') { awsIamToken = await authProxy.getAwsIamToken(props); @@ -60,6 +61,7 @@ const drivers = driverBases.map(driverBase => ({ const dbhan = { client, database, + conid, }; if (isReadOnly) { await this.query(dbhan, 'SET SESSION TRANSACTION READ ONLY'); @@ -138,7 +140,7 @@ const drivers = driverBases.map(driverBase => ({ }; const handleError = error => { - logger.error(extractErrorLogData(error), 'DBGM-00200 Stream error'); + logger.error(extractErrorLogData(error, this.getLogDbInfo(dbhan)), 'DBGM-00200 Stream error'); const { message } = error; options.info({ message, diff --git a/plugins/dbgate-plugin-postgres/src/backend/drivers.js b/plugins/dbgate-plugin-postgres/src/backend/drivers.js index 24b1941e4..595b56b97 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/drivers.js +++ b/plugins/dbgate-plugin-postgres/src/backend/drivers.js @@ -78,6 +78,7 @@ const drivers = driverBases.map(driverBase => ({ async connect(props) { const { + conid, engine, server, port, @@ -137,6 +138,7 @@ const drivers = driverBases.map(driverBase => ({ const dbhan = { client, database, + conid, }; const datatypes = await this.query(dbhan, `SELECT oid, typname FROM pg_type WHERE typname in ('geography')`); @@ -228,7 +230,7 @@ const drivers = driverBases.map(driverBase => ({ }); query.on('error', error => { - logger.error(extractErrorLogData(error), 'DBGM-00201 Stream error'); + logger.error(extractErrorLogData(error, this.getLogDbInfo(dbhan)), 'DBGM-00201 Stream error'); const { message, position, procName } = error; let line = null; if (position) { @@ -382,7 +384,7 @@ const drivers = driverBases.map(driverBase => ({ const defaultSchemaRows = await this.query(dbhan, 'SELECT current_schema'); const defaultSchema = defaultSchemaRows.rows[0]?.current_schema?.trim(); - logger.debug(`DBGM-00142 Loaded ${schemaRows.rows.length} postgres schemas`); + logger.debug(this.getLogDbInfo(dbhan), `DBGM-00142 Loaded ${schemaRows.rows.length} postgres schemas`); const schemas = schemaRows.rows.map(x => ({ schemaName: x.schema_name,