Repository navigation
[coverage] Conformance findings: LOGGING-002 (#494) #565
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
base: main
Are you sure you want to change the base?
Changes from all commits
fe9d2bf
c5d60e3
5229685
016d6ab
f9ddaaa
324d725
1c1d1ea
c1e837b
f157c89
2700d95
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,45 @@ | ||
| import fs from 'fs'; | ||
| import path from 'path'; | ||
| import winston, { Logger } from 'winston'; | ||
| import IDBSQLLogger, { LoggerOptions, LogLevel } from './contracts/IDBSQLLogger'; | ||
|
|
||
| const DEFAULT_LOG_FILE_NAME = 'databricks-sql-nodejs.log'; | ||
|
|
||
| // An existing directory resolves to a default file inside it. Anything else is | ||
| // returned as the path winston will open (which drops a trailing separator). | ||
| function resolveLogFilePath(filepath: string): string { | ||
|
peco-review-bot[bot] marked this conversation as resolved.
Resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 Low — Treating a trailing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree with the point, but a maintainer has to make the call, so I haven't changed any code. |
||
| try { | ||
| if (fs.statSync(filepath).isDirectory()) { | ||
|
peco-review-bot[bot] marked this conversation as resolved.
Resolved
|
||
| return path.join(filepath, DEFAULT_LOG_FILE_NAME); | ||
| } | ||
| } catch { | ||
| // doesn't exist or isn't accessible: treat it as a file path | ||
| } | ||
| return path.join(path.dirname(filepath), path.basename(filepath)); | ||
| } | ||
|
|
||
| // winston's File transport swallows errors opening its stream (EISDIR, EACCES, | ||
| // ENOTDIR, ...), after which the logger stalls for all transports once its | ||
| // buffer fills. Check up front that the file can be opened for appending. | ||
| // Note: this probe is intentionally not side-effect free. It creates missing | ||
| // parent directories and an empty log file (as winston itself would when the | ||
| // transport opens), so the check exercises the exact same open path. | ||
| // Limitations: this is a one-time, synchronous check (statSync/mkdirSync/ | ||
| // openSync) run each time a DBSQLLogger is constructed with a `filepath`. | ||
| // Failures that start later (file/dir deleted, permissions changed, disk | ||
| // full, a Windows file lock) are not detected here and can still stall the | ||
| // logger. Follow-up (separate change): attach a runtime `error` handler to the | ||
| // File transport that removes it and falls back to console-only logging. | ||
| function checkLogFileWritable(filename: string): Error | undefined { | ||
| try { | ||
| fs.mkdirSync(path.dirname(filename), { recursive: true }); | ||
|
peco-review-bot[bot] marked this conversation as resolved.
Resolved
peco-review-bot[bot] marked this conversation as resolved.
Resolved
peco-review-bot[bot] marked this conversation as resolved.
Resolved
|
||
| fs.closeSync(fs.openSync(filename, 'a')); | ||
| return undefined; | ||
| } catch (error) { | ||
| return error instanceof Error ? error : new Error(String(error)); | ||
| } | ||
| } | ||
|
|
||
| export default class DBSQLLogger implements IDBSQLLogger { | ||
| logger: Logger; | ||
|
|
||
|
|
@@ -21,8 +60,23 @@ export default class DBSQLLogger implements IDBSQLLogger { | |
| transports: [this.transports.console], | ||
| }); | ||
| if (filepath) { | ||
| this.transports.file = new winston.transports.File({ filename: filepath, handleExceptions: true, level }); | ||
| this.logger.add(this.transports.file); | ||
| const filename = resolveLogFilePath(filepath); | ||
| const error = checkLogFileWritable(filename); | ||
| if (error) { | ||
| // Logged at `error` so the console transport's level filter can never | ||
| // drop it (e.g. when the logger is configured with `level: error`). | ||
|
peco-review-bot[bot] marked this conversation as resolved.
Resolved
|
||
| // Trade-off: consumers filtering on the winston `level` field (e.g. | ||
| // error-level alerting) WILL see this as an error; the "[warn] ... | ||
| // non-fatal" wording only helps human readers tell this config | ||
| // fallback apart from a driver failure. | ||
| this.logger.log({ | ||
|
peco-review-bot[bot] marked this conversation as resolved.
Resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 Low — The fallback notice is sent at
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The smallest fix is the reviewer's own fallback option: keep Pushed c1e837b. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keeping
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The corrected comment is already on this branch and I didn't make any new edit. The working tree is clean and |
||
| level: LogLevel.error, | ||
| message: `[warn] Cannot write to log file ${filename}, logging to console only (non-fatal, driver continues normally): ${error.message}`, | ||
| }); | ||
| } else { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 Low — The fallback notice goes out at Two alternatives:
It's a judgement call, but this is a public connector, so a maintainer should decide it explicitly rather than leave it to the code comment.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree with the reviewer that this is a policy decision for a maintainer, so I made no code change. Right now (lib/DBSQLLogger.ts around line 70), when the log file can't be written, the driver logs one notice through winston at |
||
| this.transports.file = new winston.transports.File({ filename, handleExceptions: true, level }); | ||
| this.logger.add(this.transports.file); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.