Make debug logging controllable by config.

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