import "typeLib" as typeLib; import "ansiLib" as ansiLib; import "JSONLib" as JSONLib; def logLevels: [ "trace", "debug", "info", "warn", "error", "fatal" ]; def isJSONTooComplex: (.. | length) > 128; def isValidLogLevel($logLevel): logLevels | any(index($logLevel)); def ensureLogLevel: . as $logLevel | if typeLib::typecheckingEnabled then if isValidLogLevel($logLevel) | not then typeLib::typeErrorText("logLevel") end end; def maxLogLevel: ($ENV["JQ_LOGLEVEL"] // "info") as $maxLogLevel | if isValidLogLevel($maxLogLevel) | not then "info" else $maxLogLevel end; def shouldLog($logLevel): maxLogLevel as $maxLogLevel | logLevels as $logLevels | reduce range($logLevels | length) as $logLevelIndex ({}; .[$logLevels[$logLevelIndex]] = $logLevelIndex ) as $logLevelIndexes | $logLevelIndexes[$maxLogLevel] <= $logLevelIndexes[$logLevel]; def ansiColourByName: . as $name | { "red": "31", "yellow": "33", "blue": "36", "gray": "37" }[$name]; def levelColour: . as $logLevel | { "trace": "yellow", "debug": "gray", "info": "blue", "warn": "yellow", "error": "red", "fatal": "red" }[$logLevel] | ansiColourByName; def log($logLevel; $msg; $data): . as $input | ($logLevel | ensureLogLevel) | ($msg | typeLib::ensureNullOr(typeLib::ensureString)) | if shouldLog($logLevel) then ($logLevel | levelColour) as $logLevelColour | ($logLevel | ascii_upcase | ansiLib::colourText($logLevelColour)) as $logLevelText | ($msg | ansiLib::colourText("gray" | ansiColourByName)) as $msgText | if $data != null then if $data | isJSONTooComplex | not then $data | JSONLib::encodeJSON(true; 2) else $data | tojson end else "" end | . as $dataText | "\($logLevelText) \($msgText) \($dataText)\n" | if $logLevel == "fatal" then halt_error(1) else stderr end end | $input; def trace($msg; $data): log("trace"; $msg; $data); def debug($msg; $data): log("debug"; $msg; $data); def info($msg; $data): log("info"; $msg; $data); def warn($msg; $data): log("warn"; $msg; $data); def error($msg; $data): log("error"; $msg; $data); def fatal($msg; $data): log("fatal"; $msg; $data); def trace($msg): trace($msg; null); def debug($msg): debug($msg; null); def info($msg): info($msg; null); def warn($msg): warn($msg; null); def error($msg): error($msg; null); def fatal($msg): fatal($msg; null); def logTest: ([ "trace", "debug", "info", "warn", "error" ][] | log(.; "example text \(.)"; {})) | empty;