Skip to content

Commit

Permalink
Merge pull request #1789 from riganti/js-custom-logger
Browse files Browse the repository at this point in the history
JS: Add extensibility point to supply a custom logging function
  • Loading branch information
tomasherceg committed Mar 22, 2024
2 parents 3bfa2ea + dcecf98 commit 6a6b6ec
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 6 deletions.
5 changes: 3 additions & 2 deletions src/Framework/Framework/Resources/Scripts/dotvvm-root.ts
Expand Up @@ -22,7 +22,7 @@ import * as api from './api/api'
import * as eventHub from './api/eventHub'
import * as viewModuleManager from './viewModules/viewModuleManager'
import { notifyModuleLoaded } from './postback/resourceLoader'
import { logError, logWarning, logInfo, logInfoVerbose, level, logPostBackScriptError } from "./utils/logging"
import { logError, logWarning, logInfo, logInfoVerbose, level, logPostBackScriptError, setLogger } from "./utils/logging"
import * as metadataHelper from './metadata/metadataHelper'
import { StateManager } from "./state-manager"
import { DotvvmEvent } from "./events"
Expand Down Expand Up @@ -119,7 +119,8 @@ const dotvvmExports = {
logInfo,
logInfoVerbose,
logPostBackScriptError,
level
level,
setLogger
},
options,
translations: translations as any,
Expand Down
31 changes: 31 additions & 0 deletions src/Framework/Framework/Resources/Scripts/tests/validation.test.ts
Expand Up @@ -2,6 +2,7 @@
import { globalValidationObject as validation, ValidationErrorDescriptor } from "../validation/validation"
import { createComplexObservableSubViewmodel, createComplexObservableViewmodel, ObservableHierarchy, ObservableSubHierarchy } from "./observableHierarchies"
import { getErrors } from "../validation/error"
import { setLogger } from "../utils/logging";


describe("DotVVM.Validation - public API", () => {
Expand Down Expand Up @@ -139,6 +140,36 @@ describe("DotVVM.Validation - public API", () => {
}
})

test("addErrors - second level nonexistent property (setLogger capture)", () => {
//Setup
const vm = createComplexObservableViewmodel();
const logMessages: any[][] = []
let captureLog = true
setLogger((next, level, area, ...args) => {
if (captureLog && level == "warn")
logMessages.push([ "area", ...args ])
else
next(level, area, ...args)
})

try {
//Act
validation.addErrors(
[
{ errorMessage: "Does not matter", propertyPath: "/Prop1/NonExistent" },
],
{ root: ko.observable(vm) }
);

//Check
expect(logMessages.length).toBe(1);
expect(logMessages[0][1]).toContain("Validation error could not been applied to property specified by propertyPath /Prop1/NonExistent. Property with name NonExistent does not exist on /Prop1.");
}
finally {
captureLog = false
}
})

test("addErrors - root level nonexistent property", () => {
//Setup
const vm = createComplexObservableViewmodel();
Expand Down
30 changes: 26 additions & 4 deletions src/Framework/Framework/Resources/Scripts/utils/logging.ts
Expand Up @@ -4,6 +4,28 @@ type LogLevel = "normal" | "verbose";

export const level = getLogLevel();

type ConsoleLogLevel = "warn" | "log" | "error" | "trace";

let logger = function defaultLogger(level: ConsoleLogLevel, area: DotvvmLoggingArea, ...args: any) {
console[level](area, ...args)
}

/**
* Instead of calling console.log, console.warn or console.error, DotVVM will call this function instead.
* Please keep in mind that the exact wording of log messages is not DotVVM public API and may change without notice.
* @example
* dotvvm.log.setLogger((next, level, area, ...args) => {
* if (area == "validation" && /^This message should be an error$/.test(args[0])) {
* level = "error"
* }
* previous(level, area, ...args) // call the default logger
* })
*/
export function setLogger(newLogger: (next: typeof logger, level: ConsoleLogLevel, area: DotvvmLoggingArea, ...args: any) => void) {
const nextLogger = logger;
logger = (...args) => newLogger(nextLogger, ...args);
}

export type DotvvmLoggingArea = (
| "debug"
| "configuration"
Expand All @@ -21,20 +43,20 @@ export type DotvvmLoggingArea = (

export function logInfoVerbose(area: DotvvmLoggingArea, ...args: any[]) {
if (compileConstants.debug && level === "verbose") {
console.log(area, ...args);
logger("log", area, ...args);
}
}

export function logInfo(area: DotvvmLoggingArea, ...args: any[]) {
console.log(area, ...args);
logger("log", area, ...args);
}

export function logWarning(area: DotvvmLoggingArea, ...args: any[]) {
console.warn(area, ...args);
logger("warn", area, ...args);
}

export function logError(area: DotvvmLoggingArea, ...args: any[]) {
console.error(area, ...args);
logger("error", area, ...args);
}

export function logPostBackScriptError(err: any) {
Expand Down

0 comments on commit 6a6b6ec

Please sign in to comment.