| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import * as Common from '../../core/common/common.js'; |
| import type * as Platform from '../../core/platform/platform.js'; |
| import * as SDK from '../../core/sdk/sdk.js'; |
| import * as Protocol from '../../generated/protocol.js'; |
| |
| import {NetworkLog} from './NetworkLog.js'; |
| |
| const modelToEventListeners = new WeakMap<SDK.LogModel.LogModel, Common.EventTarget.EventDescriptor[]>(); |
| |
| let instance: LogManager|null = null; |
| |
| export class LogManager implements SDK.TargetManager.SDKModelObserver<SDK.LogModel.LogModel> { |
| private constructor() { |
| SDK.TargetManager.TargetManager.instance().observeModels(SDK.LogModel.LogModel, this); |
| } |
| |
| static instance({forceNew}: {forceNew: boolean} = {forceNew: false}): LogManager { |
| if (!instance || forceNew) { |
| instance = new LogManager(); |
| } |
| |
| return instance; |
| } |
| |
| modelAdded(logModel: SDK.LogModel.LogModel): void { |
| const eventListeners = []; |
| eventListeners.push(logModel.addEventListener(SDK.LogModel.Events.ENTRY_ADDED, this.logEntryAdded, this)); |
| modelToEventListeners.set(logModel, eventListeners); |
| } |
| |
| modelRemoved(logModel: SDK.LogModel.LogModel): void { |
| const eventListeners = modelToEventListeners.get(logModel); |
| if (eventListeners) { |
| Common.EventTarget.removeEventListeners(eventListeners); |
| } |
| } |
| |
| private logEntryAdded(event: Common.EventTarget.EventTargetEvent<SDK.LogModel.EntryAddedEvent>): void { |
| const {logModel, entry} = event.data; |
| const target = logModel.target(); |
| const details = { |
| url: entry.url as Platform.DevToolsPath.UrlString, |
| line: entry.lineNumber, |
| parameters: [entry.text, ...(entry.args ?? [])], |
| stackTrace: entry.stackTrace, |
| timestamp: entry.timestamp, |
| workerId: entry.workerId, |
| category: entry.category, |
| affectedResources: entry.networkRequestId ? {requestId: entry.networkRequestId} : undefined, |
| }; |
| const consoleMessage = new SDK.ConsoleModel.ConsoleMessage( |
| target.model(SDK.RuntimeModel.RuntimeModel), entry.source, entry.level, entry.text, details); |
| |
| if (entry.networkRequestId) { |
| NetworkLog.instance().associateConsoleMessageWithRequest(consoleMessage, entry.networkRequestId); |
| } |
| |
| const consoleModel = target.model(SDK.ConsoleModel.ConsoleModel); |
| if (consoleMessage.source === Protocol.Log.LogEntrySource.Worker) { |
| const workerId = consoleMessage.workerId || ''; |
| // We have a copy of worker messages reported through the page, so that |
| // user can see messages from the worker which has been already destroyed. |
| // When opening DevTools, give us some time to connect to the worker and |
| // not report the message twice if the worker is still alive. |
| if (SDK.TargetManager.TargetManager.instance().targetById(workerId)) { |
| return; |
| } |
| window.setTimeout(() => { |
| if (!SDK.TargetManager.TargetManager.instance().targetById(workerId)) { |
| consoleModel?.addMessage(consoleMessage); |
| } |
| }, 1000); |
| } else { |
| consoleModel?.addMessage(consoleMessage); |
| } |
| } |
| } |