From 49e5cc5c5e13af8965869b337b3bd04bc13cfde2 Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Sun, 29 Jan 2023 15:56:47 -0800 Subject: [PATCH] Make debug logging controllable by config. --- src/camera/engine-factory.ts | 8 ++++++- src/camera/frigate/engine-frigate.ts | 34 ++++++++++++++++------------ src/camera/manager.ts | 12 +++++++--- src/card.ts | 14 +++++++++--- src/types.ts | 12 ++++++++++ src/utils/basic.ts | 8 ------- src/utils/debug.ts | 15 ++++++++++++ src/view/view.ts | 2 -- 8 files changed, 74 insertions(+), 31 deletions(-) create mode 100644 src/utils/debug.ts diff --git a/src/camera/engine-factory.ts b/src/camera/engine-factory.ts index d678d97b..07295bb8 100644 --- a/src/camera/engine-factory.ts +++ b/src/camera/engine-factory.ts @@ -1,4 +1,4 @@ -import { CameraConfig } from '../types'; +import { CameraConfig, CardWideConfig } from '../types'; import { ViewMedia } from '../view/media'; import { RecordingSegmentsCache, RequestCache } from './cache'; import { CameraManagerEngine } from './engine'; @@ -9,6 +9,11 @@ type CameraManagerEngineCameraIDMap = Map>; export class CameraManagerEngineFactory { protected _engines: Map = new Map(); + protected _cardWideConfig: CardWideConfig; + + constructor(cardWideConfig: CardWideConfig) { + this._cardWideConfig = cardWideConfig; + } public getEngine(engine: Engine): CameraManagerEngine | null { const cachedEngine = this._engines.get(engine); @@ -19,6 +24,7 @@ export class CameraManagerEngineFactory { switch (engine) { case Engine.Frigate: cameraManagerEngine = new FrigateCameraManagerEngine( + this._cardWideConfig, new RecordingSegmentsCache(), new RequestCache(), ); diff --git a/src/camera/frigate/engine-frigate.ts b/src/camera/frigate/engine-frigate.ts index 5916017a..96f727b6 100644 --- a/src/camera/frigate/engine-frigate.ts +++ b/src/camera/frigate/engine-frigate.ts @@ -3,7 +3,7 @@ import add from 'date-fns/add'; import endOfHour from 'date-fns/endOfHour'; import startOfHour from 'date-fns/startOfHour'; import { CAMERA_BIRDSEYE } from '../../const'; -import { CameraConfig, RecordingSegment } from '../../types'; +import { CameraConfig, CardWideConfig, RecordingSegment } from '../../types'; import { ViewMedia } from '../../view/media'; import { RequestCache, RecordingSegmentsCache } from '../cache'; import { @@ -54,6 +54,7 @@ import { sum } from 'lodash-es'; import { FrigateViewMediaClassifier } from './media-classifier'; import { ViewMediaClassifier } from '../../view/media-classifier'; import { FrigateViewMediaFactory } from './media'; +import { log } from '../../utils/debug'; const EVENT_REQUEST_CACHE_MAX_AGE_SECONDS = 60; const RECORDING_SUMMARY_REQUEST_CACHE_MAX_AGE_SECONDS = 60; @@ -86,6 +87,7 @@ class FrigateQueryResultsClassifier { export class FrigateCameraManagerEngine implements CameraManagerEngine { protected _recordingSegmentsCache: RecordingSegmentsCache; protected _requestCache: RequestCache; + protected _cardWideConfig: CardWideConfig; // Garbage collect segments at most once an hour. protected _throttledSegmentGarbageCollector = throttle( @@ -95,9 +97,11 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine { ); constructor( + cardWideConfig: CardWideConfig, recordingSegmentsCache: RecordingSegmentsCache, requestCache: RequestCache, ) { + this._cardWideConfig = cardWideConfig; this._recordingSegmentsCache = recordingSegmentsCache; this._requestCache = requestCache; } @@ -654,9 +658,7 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine { } }; - const processRecordings = async ( - cameraIDs: Set): Promise => { - + const processRecordings = async (cameraIDs: Set): Promise => { const recordings = await this.getRecordings(hass, cameras, { type: QueryType.Recording, cameraIDs: cameraIDs, @@ -675,13 +677,16 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine { days.add(formatDate(recording.startTime)); } } - } + }; - await allPromises([...instances.entries()], ([instanceID, cameraIDs]) => (async () => { - await Promise.all([ - processEventSummary(instanceID, cameraIDs), - processRecordings(cameraIDs)]); - })()); + await allPromises([...instances.entries()], ([instanceID, cameraIDs]) => + (async () => { + await Promise.all([ + processEventSummary(instanceID, cameraIDs), + processRecordings(cameraIDs), + ]); + })(), + ); if (!what.size && !where.size && !days.size) { return null; @@ -750,7 +755,8 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine { ); } - console.debug( + log( + this._cardWideConfig, 'Frigate Card recording segment garbage collection: ' + `Released ${segmentsStart - countSegments()} segment(s)`, ); @@ -792,12 +798,12 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine { return { canFavoriteEvents: true, canFavoriteRecordings: false, - } + }; } public getMediaCapabilities(media: ViewMedia): CameraManagerMediaCapabilities { return { - canFavorite: ViewMediaClassifier.isEvent(media) - } + canFavorite: ViewMediaClassifier.isEvent(media), + }; } } diff --git a/src/camera/manager.ts b/src/camera/manager.ts index caa7c265..6738c7da 100644 --- a/src/camera/manager.ts +++ b/src/camera/manager.ts @@ -1,5 +1,5 @@ import { HomeAssistant } from 'custom-card-helpers'; -import { CameraConfig } from '../types.js'; +import { CameraConfig, CardWideConfig } from '../types.js'; import { allPromises, arrayify, setify } from '../utils/basic.js'; import { CameraManagerCapabilities, @@ -36,6 +36,7 @@ import uniqBy from 'lodash-es/uniqBy'; import { CameraManagerEngine } from './engine.js'; import sum from 'lodash-es/sum'; import add from 'date-fns/add'; +import { log } from '../utils/debug.js'; export class QueryClassifier { public static isEventQuery(query: DataQuery | PartialDataQuery): query is EventQuery { @@ -79,13 +80,16 @@ export interface ExtendedMediaQueryResult { export class CameraManager { protected _engineFactory: CameraManagerEngineFactory; protected _cameras: Map; + protected _cardWideConfig?: CardWideConfig; constructor( engineFactory: CameraManagerEngineFactory, cameras: Map, + cardWideConfig?: CardWideConfig, ) { this._engineFactory = engineFactory; this._cameras = cameras; + this._cardWideConfig = cardWideConfig; } public generateDefaultEventQueries( @@ -348,7 +352,8 @@ export class CameraManager { const queryStartTime = new Date(); await engine.favoriteMedia(hass, cameraConfig, media, favorite); - console.debug( + log( + this._cardWideConfig, 'Frigate Card CameraManager favorite request (', `Duration: ${(new Date().getTime() - queryStartTime.getTime()) / 1000}s,`, 'Media:', @@ -473,7 +478,8 @@ export class CameraManager { Array.from(results.values()).map((result) => Number(result.cached)), ); - console.debug( + log( + this._cardWideConfig, 'Frigate Card CameraManager request [Input queries:', _queries.length, ', Cached output queries:', diff --git a/src/card.ts b/src/card.ts index 023dd199..08355943 100644 --- a/src/card.ts +++ b/src/card.ts @@ -94,6 +94,7 @@ import { ViewContext } from 'view'; import { CameraManager } from './camera/manager.js'; import { setLowPerformanceProfile, setPerformanceCSSStyles } from './performance.js'; import { CameraManagerEngineFactory } from './camera/engine-factory.js'; +import { log } from './utils/debug.js'; /** A note on media callbacks: * @@ -988,6 +989,7 @@ export class FrigateCard extends LitElement { this._config = config; this._cardWideConfig = { performance: config.performance, + debug: config.debug, }; this._overriddenConfig = undefined; @@ -1015,7 +1017,7 @@ export class FrigateCard extends LitElement { } protected _changeView(args?: { view?: View; resetMessage?: boolean }): void { - console.debug(`Frigate Card view change: `, args?.view ?? '[default]'); + log(this._cardWideConfig, `Frigate Card view change: `, args?.view ?? '[default]'); const changeView = (view: View): void => { if (View.isMediaChange(this._view, view)) { this._currentMediaLoadedInfo = null; @@ -1101,10 +1103,16 @@ export class FrigateCard extends LitElement { * Called before each update. */ protected willUpdate(changedProps: PropertyValues): void { - if (this._cameras && (changedProps.has('_config') || changedProps.has('_cameras'))) { + if ( + this._cameras && this._cardWideConfig && + (changedProps.has('_config') || + changedProps.has('_cameras') || + changedProps.has('_cardWideConfig')) + ) { this._cameraManager = new CameraManager( - new CameraManagerEngineFactory(), + new CameraManagerEngineFactory(this._cardWideConfig), this._cameras, + this._cardWideConfig, ); } diff --git a/src/types.ts b/src/types.ts index 17ab774d..221372ca 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1220,8 +1220,18 @@ const performanceConfigSchema = z .default(performanceConfigDefault); export type PerformanceConfig = z.infer; +const debugConfigDefault = { + logging: false, +}; + +const debugConfigSchema = z.object({ + logging: z.boolean().default(debugConfigDefault.logging), +}).default(debugConfigDefault); +export type DebugConfig = z.infer; + export interface CardWideConfig { performance?: PerformanceConfig; + debug?: DebugConfig; } /** @@ -1240,6 +1250,7 @@ export const frigateCardConfigSchema = z.object({ dimensions: dimensionsConfigSchema, timeline: timelineConfigSchema, performance: performanceConfigSchema, + debug: debugConfigSchema, // Configuration overrides. overrides: overridesSchema, @@ -1265,6 +1276,7 @@ export const frigateCardConfigDefaults = { image: imageConfigDefault, timeline: timelineConfigDefault, performance: performanceConfigDefault, + debug: debugConfigDefault, }; const menuButtonSchema = z.discriminatedUnion('type', [ diff --git a/src/utils/basic.ts b/src/utils/basic.ts index 200b3939..53823d0c 100644 --- a/src/utils/basic.ts +++ b/src/utils/basic.ts @@ -166,14 +166,6 @@ export function getDurationString(start: Date, end: Date): string { return duration; } -/** - * For debug purposes only. - * @param seconds - */ -export const sleep = async (seconds: number) => { - await new Promise((r) => setTimeout(r, seconds * 1000)); -}; - export const allPromises = async ( items: T[], func: (arg: T) => void, diff --git a/src/utils/debug.ts b/src/utils/debug.ts new file mode 100644 index 00000000..863be998 --- /dev/null +++ b/src/utils/debug.ts @@ -0,0 +1,15 @@ +import { CardWideConfig } from '../types'; + +export const log = (cardWideConfig?: CardWideConfig, ...args: unknown[]) => { + if (cardWideConfig?.debug?.logging) { + console.debug(...args); + } +}; + +/** + * For debug purposes only. + * @param seconds + */ +export const sleep = async (seconds: number) => { + await new Promise((r) => setTimeout(r, seconds * 1000)); +}; diff --git a/src/view/view.ts b/src/view/view.ts index f9e99f0f..847f3a17 100644 --- a/src/view/view.ts +++ b/src/view/view.ts @@ -3,13 +3,11 @@ // - TODO: getRecordingTitle should use getCameraTitle but need hass. // - TODO: Take MediaQueries wrappers out of the camera manager. // - TODO: View a media in the gallery from September, then notice timeline missing the item. -// - TODO: Debug statement in card wide config. // Gallery: // - TODO: Filter panel expands from right can occasionally 'stick' open. // Hard: -// - TODO: Implement gallery. // - TODO: Remove FrigateBrowseMediaSource if not necessary (post-gallery). // - TODO: Remove browse-media.ts TODOs. // - TODO: What should the timeline do when an event is clicked on that is not in the queryResults (or if queryResults is empty)?