Replies: 3 comments 2 replies
-
Here is an old issue with a similar ask #47 |
Beta Was this translation helpful? Give feedback.
-
What about a curry function that produces a configured logger function? With overloads, I think we could achieve both these goals, while keeping the invocations simple with just a prefix and a pass through return value. type LogLevel = "Debug" | "Info" | "Warning" | "Error"
type Logger<T> = (prefix: String = "", value: T, level: LogLevel = "Info") -> T
fun logger(level: LogLevel): Logger<T> = (prefix: String = "", value: T) -> // log at specified level this way, invoking it might look like this: logger("Info")(payload.user).name I like the configuration data model, and I think we could provide a curry function that accepts a Developers could have the flexibility to reuse logging configurations through using variables: var myLoggerConfig = dw::util::Logging::loggerConfig([
{
scope: "Runtime",
level: "Warning"
},
{
scope: "Module",
module: "acme::MyModule"
level: "Info"
},
{
scope: "Function",
module: "acme::MyModule"
function: "test"
level: "Debug"
}
])
---
myLoggerConfig("Info")(payload.user).name |
Beta Was this translation helpful? Give feedback.
-
Another useful thing to have would be a way to group logs into tasks (similar to Apples Activity Tracing API). These can be disabled by default (making all calls to these APIs no-ops) but allow detailed information when requested. Some utopic examples 😛. We can add a new native: type TaskDescription = {
name: String
/* This is an open object, allowing extra information to be snuggled here */
}
fun describesWorkFor<T>(description: String | TaskDescription, v: T): T = ??? This is the identity function but:
The expected usage allows for both unstructured tasks: fun doAuthentication(creds: Credentials): AuthToken | AuthError =
"Authenticating ${creds.username}" describesWorkFor do {
/* Imagine some complex code that does authentication
and may perform additional logging happens here
(or is called from here) */
var authResponse = ???
---
if (authResponse.success) authResponse.token
else (authResponse as ErrorResponse).error
} And structured ones: fun doAuthentication(creds: Credentials): AuthToken | AuthError =
{
name: "Authentication",
username: creds.username
} describesWorkFor do {
/* Imagine some complex code that does authentication
and may perform additional logging happens here
(or is called from here) */
var authResponse = ???
---
if (authResponse.success) authResponse.token
else (authResponse as ErrorResponse).error
} Information-wise it should be enough to just log |
Beta Was this translation helpful? Give feedback.
-
Logging
Current
log
function allows the user to print any value in a very simple way. The log function uses the wiretap pattern. It is the identity functionfun log<T>(valueToLog: T): T
that has a side effect that prints thevalueToLog
in the standard output or the logging mechanism in the case of running in mule. With this a user can take any expression or sub expression wrap it into a log function and still work. For exampleIf for some reason we don't understand why name is not being retrieved we can go and modify
and it will not affect any execution or result.
This function has been used to troubleshoot any script, and looks like it was widely adopted. The problem with this function is that it is more a
println
than alog
meaning that it lacks a basic feature of logging such as level o a way to configure when to log and when not based on some configuration. So this means that there shouldn't be anylog
call in any normal flow execution in production. And this is a big problem because there is no way to troubleshoot production scripts without modifying the scripts.Proposal
The proposal is to cover this gaps by adding two features.
Adding the log level to the log function
The proposed log levels are
And the way we can do this is by adding a third parameter to the
log
function with default valueInfo
and we will not break compatibilityThis is the existing signature of the
log
functionfun log <T>(prefix: String = "", value: T): T
The proposed function will be
And I proposed adding new dedicated functions that log at the different levels
Support a way to configure the logging
Now that we can have log levels we should be able to turn logs on and off without needing to change the code. For this we need a configuration file that applies at the runtime level.
The idea is to allow to set the level for different kind of scopes
Scopes:
log
calls executed by a given enginelog
calls in a given Modulelog
calls in a given FunctionThe proposed configuration file is a dataweave file called logs-config.dwl where a user can configure log level for different scopes for example
So for this configuration what it expresses is that any
log
call that is not inside ofacme::MyModule
onlyWarnings
orErrors
are going to be executed. And insideacme::MyModule
is "Info" unless the log is inside a function namedtest
that is "Debug"This way we can have a hierarchical scoping that allows the user to control when to log and when not.
Beta Was this translation helpful? Give feedback.
All reactions