From e7b6882ef2b3f049c4f1e4a3df4e25469337862b Mon Sep 17 00:00:00 2001 From: Lorenzo Blasa Date: Tue, 22 Aug 2023 06:03:26 -0700 Subject: [PATCH] ScribeLogger moved to common Summary: There's nothing specific nor private about the ScribeLogger, so it is moved to flipper-common. Reviewed By: LukeDefeo Differential Revision: D48556074 fbshipit-source-id: aa9446036fd07fe6e6debc5a978a42308fc93fe0 --- desktop/flipper-common/src/index.tsx | 1 + .../flipper-common/src/utils/ScribeLogger.tsx | 94 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 desktop/flipper-common/src/utils/ScribeLogger.tsx diff --git a/desktop/flipper-common/src/index.tsx b/desktop/flipper-common/src/index.tsx index ef20b09a5..7925006b6 100644 --- a/desktop/flipper-common/src/index.tsx +++ b/desktop/flipper-common/src/index.tsx @@ -21,6 +21,7 @@ export { NoopLogger, } from './utils/Logger'; export * from './utils/LoggerTailer'; +export * from './utils/ScribeLogger'; export * from './server-types'; export * from './companion-types'; export * from './ServerAddOn'; diff --git a/desktop/flipper-common/src/utils/ScribeLogger.tsx b/desktop/flipper-common/src/utils/ScribeLogger.tsx new file mode 100644 index 000000000..57252b847 --- /dev/null +++ b/desktop/flipper-common/src/utils/ScribeLogger.tsx @@ -0,0 +1,94 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const FLUSH_TIMEOUT = 500; +const MAX_MESSAGES = 1000; + +export type ScribeMessage = { + category: string; + message: string; +}; + +/** + * Send messages to arbitrary Scribe categories. This is useful to log data to + * LogView, Scuba, Hive, etc. + */ +export class ScribeLogger { + constructor( + sender: (messages: Array) => Promise, + disabled = false, + flushTimeout = FLUSH_TIMEOUT, + ) { + this.isFlushPending = false; + this.queue = []; + this.sendMessages = sender; + this.flushTimeout = flushTimeout; + this.disabled = disabled; + } + + isFlushPending: boolean; + queue: Array; + sendMessages: (messages: Array) => Promise; + flushTimeout: number; + disabled: boolean; + + /** + * Send all the queued messages and reset. + */ + flushQueue = async () => { + const messages = this.queue.splice(0); // copy & clear + try { + // send all the message currently in the queue + await this.sendMessages(messages); + } catch (e) { + console.debug(`[ScribeLogger] Failed to send messages: ${e}`); + // restore messages if emit failed + this.queue = messages.concat(this.queue); + this.enforceQueueLimit(); + } finally { + // reset the queue + this.isFlushPending = false; + } + }; + + /** + * Add a message to be queued. Start a queue flush timer if one isn't already pending. + */ + queueSend(message: ScribeMessage) { + this.queue.push(message); + this.enforceQueueLimit(); + + // start a flush timer if none exists + if (this.isFlushPending === false) { + this.isFlushPending = true; + if (this.flushTimeout >= 0) { + setTimeout(this.flushQueue, FLUSH_TIMEOUT); + } else { + this.flushQueue(); + } + } + } + + enforceQueueLimit() { + if (this.queue.length > MAX_MESSAGES) { + console.debug('[ScribeLogger] Queue full, dropping oldest messages'); + this.queue = this.queue.slice(Math.floor(MAX_MESSAGES / 10)); + } + } + + /** + * Messages are not guaranteed to be sent right away. + */ + send(message: ScribeMessage) { + if (this.disabled) { + return; + } + this.queueSend(message); + } +}