-
Notifications
You must be signed in to change notification settings - Fork 48
chore: use semver to determine API compatibility #6
Changes from 8 commits
73bd4da
3c9b9e7
2b576fa
29e47ff
04dda0e
d728462
28b2f3e
640c1ea
ca1b381
a6ede59
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 |
---|---|---|
|
@@ -19,66 +19,42 @@ import { | |
DiagLogFunction, | ||
createNoopDiagLogger, | ||
diagLoggerFunctions, | ||
FilteredDiagLogger, | ||
} from '../diag/logger'; | ||
import { DiagLogLevel, createLogLevelDiagLogger } from '../diag/logLevel'; | ||
import { | ||
API_BACKWARDS_COMPATIBILITY_VERSION, | ||
GLOBAL_DIAG_LOGGER_API_KEY, | ||
makeGetter, | ||
_global, | ||
} from './global-utils'; | ||
|
||
/** Internal simple Noop Diag API that returns a noop logger and does not allow any changes */ | ||
function noopDiagApi(): DiagAPI { | ||
dyladan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const noopApi = createNoopDiagLogger() as DiagAPI; | ||
|
||
noopApi.getLogger = () => noopApi; | ||
noopApi.setLogger = noopApi.getLogger; | ||
noopApi.setLogLevel = () => {}; | ||
|
||
return noopApi; | ||
} | ||
getGlobal, | ||
registerGlobal, | ||
unregisterGlobal, | ||
} from '../internal/global-utils'; | ||
|
||
/** | ||
* Singleton object which represents the entry point to the OpenTelemetry internal | ||
* diagnostic API | ||
*/ | ||
export class DiagAPI implements DiagLogger { | ||
private static _instance?: DiagAPI; | ||
|
||
/** Get the singleton instance of the DiagAPI API */ | ||
public static instance(): DiagAPI { | ||
let theInst = null; | ||
if (_global[GLOBAL_DIAG_LOGGER_API_KEY]) { | ||
// Looks like a previous instance was set, so try and fetch it | ||
theInst = _global[GLOBAL_DIAG_LOGGER_API_KEY]?.( | ||
API_BACKWARDS_COMPATIBILITY_VERSION | ||
) as DiagAPI; | ||
} | ||
|
||
if (!theInst) { | ||
theInst = new DiagAPI(); | ||
_global[GLOBAL_DIAG_LOGGER_API_KEY] = makeGetter( | ||
API_BACKWARDS_COMPATIBILITY_VERSION, | ||
theInst, | ||
noopDiagApi() | ||
); | ||
if (!this._instance) { | ||
this._instance = new DiagAPI(); | ||
} | ||
|
||
return theInst; | ||
return this._instance; | ||
} | ||
|
||
/** | ||
* Private internal constructor | ||
* @private | ||
*/ | ||
private constructor() { | ||
let _logLevel: DiagLogLevel = DiagLogLevel.INFO; | ||
let _filteredLogger: DiagLogger | null; | ||
let _logger: DiagLogger = createNoopDiagLogger(); | ||
const _noopLogger = createNoopDiagLogger(); | ||
|
||
function _logProxy(funcName: keyof DiagLogger): DiagLogFunction { | ||
return function () { | ||
const orgArguments = arguments as unknown; | ||
const theLogger = _filteredLogger || _logger; | ||
const theLogger = self.getLogger(); | ||
const theFunc = theLogger[funcName]; | ||
if (typeof theFunc === 'function') { | ||
return theFunc.apply( | ||
|
@@ -94,29 +70,20 @@ export class DiagAPI implements DiagLogger { | |
|
||
// DiagAPI specific functions | ||
|
||
self.getLogger = (): DiagLogger => { | ||
// Return itself if no existing logger is defined (defaults effectively to a Noop) | ||
return _logger; | ||
self.getLogger = (): FilteredDiagLogger => { | ||
return getGlobal('diag') || _noopLogger; | ||
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. Thought: Do we even need this anymore? Can we just have this as the getChildLogger(), as there is no need to call getLogger() to bypass the filtering (as it won't) and the DiagAPI is a logger so you don't need to call 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. Especially, as this getLogger() was previously just here to return the child logger. 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. And this would mean that the usage on L56 would have to change. 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. Do we need the diag API to understand the concept of filtering at all? We could just have the 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 approach I was taking is that users and creators of loggers shouldn't need to worry about log level filtering as this should be controlled by the DiagAPI and any initialization configuration (as it should only be set once). So I prefer what you have done in the setLogger |
||
}; | ||
|
||
self.setLogger = (logger?: DiagLogger): DiagLogger => { | ||
const prevLogger = _logger; | ||
if (!logger || logger !== self) { | ||
// Simple special case to avoid any possible infinite recursion on the logging functions | ||
_logger = logger || createNoopDiagLogger(); | ||
_filteredLogger = createLogLevelDiagLogger(_logLevel, _logger); | ||
} | ||
|
||
return prevLogger; | ||
self.setLogger = ( | ||
logger: DiagLogger = _noopLogger, | ||
logLevel: DiagLogLevel = DiagLogLevel.INFO | ||
) => { | ||
logger = logger === self ? self.getLogger().getChild() : logger; | ||
registerGlobal('diag', createLogLevelDiagLogger(logLevel, logger), true); | ||
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. Might be worth adding a comment that we are allowing the override of the default to both replacing any existing logger AND to avoid any possible endless loop (because of someone refactoring the code as the existing implementation doesn't have an issue) -- just so it make anyone touching the code in the future to think about that scenario before just blindly changing it. |
||
}; | ||
|
||
self.setLogLevel = (maxLogLevel: DiagLogLevel) => { | ||
if (maxLogLevel !== _logLevel) { | ||
_logLevel = maxLogLevel; | ||
if (_logger) { | ||
_filteredLogger = createLogLevelDiagLogger(maxLogLevel, _logger); | ||
} | ||
} | ||
self.disable = () => { | ||
unregisterGlobal('diag'); | ||
}; | ||
|
||
for (let i = 0; i < diagLoggerFunctions.length; i++) { | ||
|
@@ -129,22 +96,26 @@ export class DiagAPI implements DiagLogger { | |
* Return the currently configured logger instance, if no logger has been configured | ||
* it will return itself so any log level filtering will still be applied in this case. | ||
*/ | ||
public getLogger!: () => DiagLogger; | ||
public getLogger!: () => FilteredDiagLogger; | ||
|
||
/** | ||
* Set the DiagLogger instance | ||
* @param logger - [Optional] The DiagLogger instance to set as the default logger, if not provided it will set it back as a noop | ||
* Set the global DiagLogger and DiagLogLevel | ||
* | ||
* @param logger - [Optional] The DiagLogger instance to set as the default logger. If not provided it will set it back as a noop. | ||
* @param logLevel - [Optional] The DiagLogLevel used to filter logs sent to the logger. If not provided it will default to INFO. | ||
* @returns The previously registered DiagLogger | ||
*/ | ||
public setLogger!: (logger?: DiagLogger) => DiagLogger; | ||
|
||
/** Set the default maximum diagnostic logging level */ | ||
public setLogLevel!: (maxLogLevel: DiagLogLevel) => void; | ||
public setLogger!: (logger?: DiagLogger, logLevel?: DiagLogLevel) => void; | ||
|
||
// DiagLogger implementation | ||
public verbose!: DiagLogFunction; | ||
public debug!: DiagLogFunction; | ||
public info!: DiagLogFunction; | ||
public warn!: DiagLogFunction; | ||
public error!: DiagLogFunction; | ||
|
||
/** | ||
* Unregister the global logger and return to Noop | ||
*/ | ||
public disable!: () => void; | ||
} |
This file was deleted.
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 ts comments for asserting a type check will fail. This allows it in tests only