fix(log): inconsistent webview log target (#2021)

* Fix very inconsistent webview log target

* Add change file

* It's log-plugin not log

* Lower rust version requirement

* Use the third line instead of second
pull/2041/head
Tony 7 months ago committed by GitHub
parent 52c093ac9d
commit 371a2f7361
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,6 @@
---
'log-plugin': 'patch'
'log-js': 'patch'
---
Make webview log target more consistent that it always starts with `webview`

@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_LOG__=function(e){"use strict";function n(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}async function r(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}var a,t;async function o(e,a,t){const o={kind:"Any"};return r("plugin:event|listen",{event:e,target:o,handler:n(a)}).then((n=>async()=>async function(e,n){await r("plugin:event|unlisten",{event:e,eventId:n})}(e,n)))}async function i(e,n,a){const t=(new Error).stack?.split("\n").map((e=>e.split("@"))),o=t?.filter((([e,n])=>e.length>0&&"[native code]"!==n)),{file:i,line:c,keyValues:u}=a??{};let l=o?.[0]?.filter((e=>e.length>0)).join("@");"Error"===l&&(l="webview::unknown"),await r("plugin:log|log",{level:e,message:n,location:l,file:i,line:c,keyValues:u})}async function c(e){return await o("log://log",(n=>{const{level:r}=n.payload;let{message:a}=n.payload;a=a.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,""),e({message:a,level:r})}))}return"function"==typeof SuppressedError&&SuppressedError,function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(a||(a={})),function(e){e[e.Trace=1]="Trace",e[e.Debug=2]="Debug",e[e.Info=3]="Info",e[e.Warn=4]="Warn",e[e.Error=5]="Error"}(t||(t={})),e.attachConsole=async function(){return await c((({level:e,message:n})=>{switch(e){case t.Trace:console.log(n);break;case t.Debug:console.debug(n);break;case t.Info:console.info(n);break;case t.Warn:console.warn(n);break;case t.Error:console.error(n);break;default:throw new Error(`unknown log level ${e}`)}}))},e.attachLogger=c,e.debug=async function(e,n){await i(t.Debug,e,n)},e.error=async function(e,n){await i(t.Error,e,n)},e.info=async function(e,n){await i(t.Info,e,n)},e.trace=async function(e,n){await i(t.Trace,e,n)},e.warn=async function(e,n){await i(t.Warn,e,n)},e}({});Object.defineProperty(window.__TAURI__,"log",{value:__TAURI_PLUGIN_LOG__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_LOG__=function(e){"use strict";function n(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}async function r(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}var a,t;async function o(e,a,t){const o={kind:"Any"};return r("plugin:event|listen",{event:e,target:o,handler:n(a)}).then((n=>async()=>async function(e,n){await r("plugin:event|unlisten",{event:e,eventId:n})}(e,n)))}async function i(e,n,a){const t=function(e){if(e){if(!e.startsWith("Error"))return e.split("\n").map((e=>e.split("@"))).filter((([e,n])=>e.length>0&&"[native code]"!==n))[2].filter((e=>e.length>0)).join("@");{const n=e.split("\n")[3].trim(),r=/at\s+(?<functionName>.*?)\s+\((?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)\)/,a=n.match(r);if(a){const{functionName:e,fileName:n,lineNumber:r,columnNumber:t}=a.groups;return`${e}@${n}:${r}:${t}`}{const e=/at\s+(?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)/,r=n.match(e);if(r){const{fileName:e,lineNumber:n,columnNumber:a}=r.groups;return`<anonymous>@${e}:${n}:${a}`}}}}}((new Error).stack),{file:o,line:i,keyValues:u}=a??{};await r("plugin:log|log",{level:e,message:n,location:t,file:o,line:i,keyValues:u})}async function u(e){return await o("log://log",(n=>{const{level:r}=n.payload;let{message:a}=n.payload;a=a.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,""),e({message:a,level:r})}))}return"function"==typeof SuppressedError&&SuppressedError,function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(a||(a={})),function(e){e[e.Trace=1]="Trace",e[e.Debug=2]="Debug",e[e.Info=3]="Info",e[e.Warn=4]="Warn",e[e.Error=5]="Error"}(t||(t={})),e.attachConsole=async function(){return await u((({level:e,message:n})=>{switch(e){case t.Trace:console.log(n);break;case t.Debug:console.debug(n);break;case t.Info:console.info(n);break;case t.Warn:console.warn(n);break;case t.Error:console.error(n);break;default:throw new Error(`unknown log level ${e}`)}}))},e.attachLogger=u,e.debug=async function(e,n){await i(t.Debug,e,n)},e.error=async function(e,n){await i(t.Error,e,n)},e.info=async function(e,n){await i(t.Info,e,n)},e.trace=async function(e,n){await i(t.Trace,e,n)},e.warn=async function(e,n){await i(t.Warn,e,n)},e}({});Object.defineProperty(window.__TAURI__,"log",{value:__TAURI_PLUGIN_LOG__})}

@ -44,24 +44,78 @@ enum LogLevel {
Error
}
function getCallerLocation(stack?: string) {
if (!stack) {
return
}
if (stack.startsWith('Error')) {
// Assume it's Chromium V8
//
// Error
// at baz (filename.js:10:15)
// at bar (filename.js:6:3)
// at foo (filename.js:2:3)
// at filename.js:13:1
const lines = stack.split('\n')
// Find the third line (caller's caller of the current location)
const callerLine = lines[3].trim()
const regex =
/at\s+(?<functionName>.*?)\s+\((?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)\)/
const match = callerLine.match(regex)
if (match) {
const { functionName, fileName, lineNumber, columnNumber } =
match.groups as {
functionName: string
fileName: string
lineNumber: string
columnNumber: string
}
return `${functionName}@${fileName}:${lineNumber}:${columnNumber}`
} else {
// Handle cases where the regex does not match (e.g., last line without function name)
const regexNoFunction =
/at\s+(?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)/
const matchNoFunction = callerLine.match(regexNoFunction)
if (matchNoFunction) {
const { fileName, lineNumber, columnNumber } =
matchNoFunction.groups as {
fileName: string
lineNumber: string
columnNumber: string
}
return `<anonymous>@${fileName}:${lineNumber}:${columnNumber}`
}
}
} else {
// Assume it's Webkit JavaScriptCore, example:
//
// baz@filename.js:10:24
// bar@filename.js:6:6
// foo@filename.js:2:6
// global code@filename.js:13:4
const traces = stack.split('\n').map((line) => line.split('@'))
const filtered = traces.filter(([name, location]) => {
return name.length > 0 && location !== '[native code]'
})
// Find the third line (caller's caller of the current location)
return filtered[2].filter((v) => v.length > 0).join('@')
}
}
async function log(
level: LogLevel,
message: string,
options?: LogOptions
): Promise<void> {
const traces = new Error().stack?.split('\n').map((line) => line.split('@'))
const filtered = traces?.filter(([name, location]) => {
return name.length > 0 && location !== '[native code]'
})
const location = getCallerLocation(new Error().stack)
const { file, line, keyValues } = options ?? {}
let location = filtered?.[0]?.filter((v) => v.length > 0).join('@')
if (location === 'Error') {
location = 'webview::unknown'
}
await invoke('plugin:log|log', {
level,
message,

@ -33,7 +33,7 @@ use tauri::{AppHandle, Emitter};
pub use fern;
use time::OffsetDateTime;
pub const WEBVIEW_TARGET: &str = "Webview";
pub const WEBVIEW_TARGET: &str = "webview";
#[cfg(target_os = "ios")]
mod ios {
@ -230,22 +230,16 @@ fn log(
line: Option<u32>,
key_values: Option<HashMap<String, String>>,
) {
let location = location.unwrap_or("webview");
let level = log::Level::from(level);
let metadata = log::MetadataBuilder::new()
.level(level)
.target(WEBVIEW_TARGET)
.build();
let target = if let Some(location) = location {
format!("{WEBVIEW_TARGET}:{location}")
} else {
WEBVIEW_TARGET.to_string()
};
let mut builder = RecordBuilder::new();
builder
.level(level)
.metadata(metadata)
.target(location)
.file(file)
.line(line);
builder.level(level).target(&target).file(file).line(line);
let key_values = key_values.unwrap_or_default();
let mut kv = HashMap::new();
@ -380,8 +374,8 @@ impl Builder {
/// .clear_targets()
/// .targets([
/// Target::new(TargetKind::Webview),
/// Target::new(TargetKind::LogDir { file_name: Some("webview".into()) }).filter(|metadata| metadata.target() == WEBVIEW_TARGET),
/// Target::new(TargetKind::LogDir { file_name: Some("rust".into()) }).filter(|metadata| metadata.target() != WEBVIEW_TARGET),
/// Target::new(TargetKind::LogDir { file_name: Some("webview".into()) }).filter(|metadata| metadata.target().starts_with(WEBVIEW_TARGET)),
/// Target::new(TargetKind::LogDir { file_name: Some("rust".into()) }).filter(|metadata| !metadata.target().starts_with(WEBVIEW_TARGET)),
/// ]);
/// ```
pub fn targets(mut self, targets: impl IntoIterator<Item = Target>) -> Self {

Loading…
Cancel
Save