feat(ui): better logging w/ path

This commit is contained in:
psychedelicious 2024-08-12 17:33:56 +10:00
parent df78dd7953
commit b1cb018695
10 changed files with 141 additions and 133 deletions

View File

@ -7,16 +7,19 @@ import type { CanvasBrushLineState } from 'features/controlLayers/store/types';
import Konva from 'konva';
import type { Logger } from 'roarr';
const TYPE = 'brush_line';
export class CanvasBrushLineRenderer {
static TYPE = 'brush_line';
static GROUP_NAME = `${CanvasBrushLineRenderer.TYPE}_group`;
static LINE_NAME = `${CanvasBrushLineRenderer.TYPE}_line`;
static GROUP_NAME = `${TYPE}_group`;
static LINE_NAME = `${TYPE}_line`;
readonly type = TYPE;
id: string;
path: string[];
parent: CanvasObjectRenderer;
manager: CanvasManager;
log: Logger;
getLoggingContext: (extra?: JSONObject) => JSONObject;
state: CanvasBrushLineState;
konva: {
@ -29,8 +32,8 @@ export class CanvasBrushLineRenderer {
this.id = id;
this.parent = parent;
this.manager = parent.manager;
this.path = this.parent.path.concat(this.id);
this.getLoggingContext = this.manager.buildGetLoggingContext(this);
this.log = this.manager.buildLogger(this.getLoggingContext);
this.log.trace({ state }, 'Creating brush line');
@ -90,9 +93,13 @@ export class CanvasBrushLineRenderer {
repr() {
return {
id: this.id,
type: CanvasBrushLineRenderer.TYPE,
type: this.type,
parent: this.parent.id,
state: deepClone(this.state),
};
}
getLoggingContext = (): JSONObject => {
return { ...this.parent.getLoggingContext(), path: this.path.join('.') };
};
}

View File

@ -1,22 +1,26 @@
import type { JSONObject } from 'common/types';
import { rgbaColorToString } from 'common/util/colorCodeTransformers';
import { deepClone } from 'common/util/deepClone';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { CanvasObjectRenderer } from 'features/controlLayers/konva/CanvasObjectRenderer';
import type { CanvasEraserLineState, GetLoggingContext } from 'features/controlLayers/store/types';
import type { CanvasEraserLineState } from 'features/controlLayers/store/types';
import { RGBA_RED } from 'features/controlLayers/store/types';
import Konva from 'konva';
import type { Logger } from 'roarr';
const TYPE = 'eraser_line';
export class CanvasEraserLineRenderer {
static TYPE = 'eraser_line';
static GROUP_NAME = `${CanvasEraserLineRenderer.TYPE}_group`;
static LINE_NAME = `${CanvasEraserLineRenderer.TYPE}_line`;
static GROUP_NAME = `${TYPE}_group`;
static LINE_NAME = `${TYPE}_line`;
readonly type = TYPE;
id: string;
path: string[];
parent: CanvasObjectRenderer;
manager: CanvasManager;
log: Logger;
getLoggingContext: GetLoggingContext;
state: CanvasEraserLineState;
konva: {
@ -29,7 +33,7 @@ export class CanvasEraserLineRenderer {
this.id = id;
this.parent = parent;
this.manager = parent.manager;
this.getLoggingContext = this.manager.buildGetLoggingContext(this);
this.path = this.parent.path.concat(this.id);
this.log = this.manager.buildLogger(this.getLoggingContext);
this.log.trace({ state }, 'Creating eraser line');
@ -88,9 +92,13 @@ export class CanvasEraserLineRenderer {
repr() {
return {
id: this.id,
type: CanvasEraserLineRenderer.TYPE,
type: this.type,
parent: this.parent.id,
state: deepClone(this.state),
};
}
getLoggingContext = (): JSONObject => {
return { ...this.parent.getLoggingContext(), path: this.path.join('.') };
};
}

View File

@ -1,29 +1,33 @@
import { Mutex } from 'async-mutex';
import type { JSONObject } from 'common/types';
import { deepClone } from 'common/util/deepClone';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { CanvasObjectRenderer } from 'features/controlLayers/konva/CanvasObjectRenderer';
import type { CanvasStagingArea } from 'features/controlLayers/konva/CanvasStagingArea';
import { FILTER_MAP } from 'features/controlLayers/konva/filters';
import { loadImage } from 'features/controlLayers/konva/util';
import type { CanvasImageState, GetLoggingContext } from 'features/controlLayers/store/types';
import type { CanvasImageState } from 'features/controlLayers/store/types';
import { t } from 'i18next';
import Konva from 'konva';
import type { Logger } from 'roarr';
import { getImageDTO } from 'services/api/endpoints/images';
const TYPE = 'image';
export class CanvasImageRenderer {
static TYPE = 'image';
static GROUP_NAME = `${CanvasImageRenderer.TYPE}_group`;
static IMAGE_NAME = `${CanvasImageRenderer.TYPE}_image`;
static PLACEHOLDER_GROUP_NAME = `${CanvasImageRenderer.TYPE}_placeholder-group`;
static PLACEHOLDER_RECT_NAME = `${CanvasImageRenderer.TYPE}_placeholder-rect`;
static PLACEHOLDER_TEXT_NAME = `${CanvasImageRenderer.TYPE}_placeholder-text`;
static GROUP_NAME = `${TYPE}_group`;
static IMAGE_NAME = `${TYPE}_image`;
static PLACEHOLDER_GROUP_NAME = `${TYPE}_placeholder-group`;
static PLACEHOLDER_RECT_NAME = `${TYPE}_placeholder-rect`;
static PLACEHOLDER_TEXT_NAME = `${TYPE}_placeholder-text`;
readonly type = TYPE;
id: string;
path: string[];
parent: CanvasObjectRenderer | CanvasStagingArea;
manager: CanvasManager;
log: Logger;
getLoggingContext: GetLoggingContext;
state: CanvasImageState;
konva: {
@ -42,7 +46,7 @@ export class CanvasImageRenderer {
this.id = id;
this.parent = parent;
this.manager = parent.manager;
this.getLoggingContext = this.manager.buildGetLoggingContext(this);
this.path = this.parent.path.concat(this.id);
this.log = this.manager.buildLogger(this.getLoggingContext);
this.log.trace({ state }, 'Creating image');
@ -197,11 +201,15 @@ export class CanvasImageRenderer {
repr = () => {
return {
id: this.id,
type: CanvasImageRenderer.TYPE,
type: this.type,
parent: this.parent.id,
isLoading: this.isLoading,
isError: this.isError,
state: deepClone(this.state),
};
};
getLoggingContext = (): JSONObject => {
return { ...this.parent.getLoggingContext(), path: this.path.join('.') };
};
}

View File

@ -1,23 +1,22 @@
import type { JSONObject } from 'common/types';
import { deepClone } from 'common/util/deepClone';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import { CanvasObjectRenderer } from 'features/controlLayers/konva/CanvasObjectRenderer';
import { CanvasTransformer } from 'features/controlLayers/konva/CanvasTransformer';
import type {
CanvasEntityIdentifier,
CanvasLayerState,
CanvasV2State,
GetLoggingContext,
} from 'features/controlLayers/store/types';
import type { CanvasEntityIdentifier, CanvasLayerState, CanvasV2State } from 'features/controlLayers/store/types';
import Konva from 'konva';
import { get } from 'lodash-es';
import type { Logger } from 'roarr';
const TYPE = 'layer';
export class CanvasLayerAdapter {
readonly type = TYPE;
id: string;
type: CanvasLayerState['type'];
path: string[];
manager: CanvasManager;
log: Logger;
getLoggingContext: GetLoggingContext;
state: CanvasLayerState;
@ -31,9 +30,8 @@ export class CanvasLayerAdapter {
constructor(state: CanvasLayerAdapter['state'], manager: CanvasLayerAdapter['manager']) {
this.id = state.id;
this.type = state.type;
this.manager = manager;
this.getLoggingContext = this.manager.buildGetLoggingContext(this);
this.path = this.manager.path.concat(this.id);
this.log = this.manager.buildLogger(this.getLoggingContext);
this.log.debug({ state }, 'Creating layer');
@ -140,6 +138,10 @@ export class CanvasLayerAdapter {
};
};
getLoggingContext = (): JSONObject => {
return { ...this.manager.getLoggingContext(), path: this.path.join('.') };
};
logDebugInfo(msg = 'Debug info') {
const info = {
repr: this.repr(),

View File

@ -2,12 +2,6 @@ import type { Store } from '@reduxjs/toolkit';
import { logger } from 'app/logging/logger';
import type { RootState } from 'app/store/store';
import type { JSONObject } from 'common/types';
import type { CanvasBrushLineRenderer } from 'features/controlLayers/konva/CanvasBrushLine';
import type { CanvasEraserLineRenderer } from 'features/controlLayers/konva/CanvasEraserLine';
import type { CanvasImageRenderer } from 'features/controlLayers/konva/CanvasImage';
import { CanvasObjectRenderer } from 'features/controlLayers/konva/CanvasObjectRenderer';
import type { CanvasRectRenderer } from 'features/controlLayers/konva/CanvasRect';
import type { CanvasTransformer } from 'features/controlLayers/konva/CanvasTransformer';
import { MAX_CANVAS_SCALE, MIN_CANVAS_SCALE } from 'features/controlLayers/konva/constants';
import {
getImageDataTransparency,
@ -17,14 +11,7 @@ import {
nanoid,
} from 'features/controlLayers/konva/util';
import type { Extents, ExtentsResult, GetBboxTask, WorkerLogMessage } from 'features/controlLayers/konva/worker';
import type {
CanvasV2State,
Coordinate,
Dimensions,
GenerationMode,
GetLoggingContext,
Rect,
} from 'features/controlLayers/store/types';
import type { CanvasV2State, Coordinate, Dimensions, GenerationMode, Rect } from 'features/controlLayers/store/types';
import { isValidLayer } from 'features/nodes/util/graph/generation/addLayers';
import type Konva from 'konva';
import { clamp } from 'lodash-es';
@ -39,13 +26,17 @@ import { CanvasControlAdapter } from './CanvasControlAdapter';
import { CanvasLayerAdapter } from './CanvasLayerAdapter';
import { CanvasMaskAdapter } from './CanvasMaskAdapter';
import { CanvasPreview } from './CanvasPreview';
import { CanvasStagingArea } from './CanvasStagingArea';
import { CanvasStateApi } from './CanvasStateApi';
import { setStageEventHandlers } from './events';
export const $canvasManager = atom<CanvasManager | null>(null);
const TYPE = 'manager';
export class CanvasManager {
readonly type = TYPE;
id: string;
path: string[];
stage: Konva.Stage;
container: HTMLDivElement;
controlAdapters: Map<string, CanvasControlAdapter>;
@ -68,6 +59,8 @@ export class CanvasManager {
_tasks: Map<string, { task: GetBboxTask; onComplete: (extents: Extents | null) => void }> = new Map();
constructor(stage: Konva.Stage, container: HTMLDivElement, store: Store<RootState>) {
this.id = getPrefixedId(this.type);
this.path = [this.id];
this.stage = stage;
this.container = container;
this._store = store;
@ -79,8 +72,8 @@ export class CanvasManager {
return {
...message,
context: {
...message.context,
...this.getLoggingContext(),
...message.context,
},
};
});
@ -637,13 +630,13 @@ export class CanvasManager {
}
}
getLoggingContext() {
getLoggingContext = (): JSONObject => {
return {
// timestamp: new Date().toISOString(),
path: this.path.join('.'),
};
}
};
buildLogger(getContext: () => JSONObject): Logger {
buildLogger = (getContext: () => JSONObject): Logger => {
return this.log.child((message) => {
return {
...message,
@ -653,49 +646,6 @@ export class CanvasManager {
},
};
});
}
buildGetLoggingContext = (
instance:
| CanvasBrushLineRenderer
| CanvasEraserLineRenderer
| CanvasRectRenderer
| CanvasImageRenderer
| CanvasTransformer
| CanvasObjectRenderer
| CanvasLayerAdapter
| CanvasMaskAdapter
| CanvasStagingArea
): GetLoggingContext => {
if (
instance instanceof CanvasLayerAdapter ||
instance instanceof CanvasStagingArea ||
instance instanceof CanvasMaskAdapter
) {
return (extra?: JSONObject): JSONObject => {
return {
...instance.manager.getLoggingContext(),
entityId: instance.id,
...extra,
};
};
} else if (instance instanceof CanvasObjectRenderer) {
return (extra?: JSONObject): JSONObject => {
return {
...instance.parent.getLoggingContext(),
rendererId: instance.id,
...extra,
};
};
} else {
return (extra?: JSONObject): JSONObject => {
return {
...instance.parent.getLoggingContext(),
objectId: instance.id,
...extra,
};
};
}
};
logDebugInfo() {

View File

@ -1,3 +1,4 @@
import type { JSONObject } from 'common/types';
import { deepClone } from 'common/util/deepClone';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import { CanvasObjectRenderer } from 'features/controlLayers/konva/CanvasObjectRenderer';
@ -7,7 +8,6 @@ import type {
CanvasInpaintMaskState,
CanvasRegionalGuidanceState,
CanvasV2State,
GetLoggingContext,
} from 'features/controlLayers/store/types';
import Konva from 'konva';
import { get } from 'lodash-es';
@ -15,10 +15,10 @@ import type { Logger } from 'roarr';
export class CanvasMaskAdapter {
id: string;
path: string[];
type: CanvasInpaintMaskState['type'] | CanvasRegionalGuidanceState['type'];
manager: CanvasManager;
log: Logger;
getLoggingContext: GetLoggingContext;
state: CanvasInpaintMaskState | CanvasRegionalGuidanceState;
maskOpacity: number;
@ -36,7 +36,7 @@ export class CanvasMaskAdapter {
this.id = state.id;
this.type = state.type;
this.manager = manager;
this.getLoggingContext = this.manager.buildGetLoggingContext(this);
this.path = this.manager.path.concat(this.id);
this.log = this.manager.buildLogger(this.getLoggingContext);
this.log.debug({ state }, 'Creating mask');
@ -146,4 +146,8 @@ export class CanvasMaskAdapter {
state: deepClone(this.state),
};
};
getLoggingContext = (): JSONObject => {
return { ...this.manager.getLoggingContext(), path: this.path.join('.') };
};
}

View File

@ -9,15 +9,15 @@ import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { CanvasMaskAdapter } from 'features/controlLayers/konva/CanvasMaskAdapter';
import { CanvasRectRenderer } from 'features/controlLayers/konva/CanvasRect';
import { getPrefixedId, konvaNodeToBlob, konvaNodeToImageData, previewBlob } from 'features/controlLayers/konva/util';
import {
type CanvasBrushLineState,
type CanvasEraserLineState,
type CanvasImageState,
type CanvasRectState,
imageDTOToImageObject,
type Rect,
type RgbColor,
import type {
CanvasBrushLineState,
CanvasEraserLineState,
CanvasImageState,
CanvasRectState,
Rect,
RgbColor,
} from 'features/controlLayers/store/types';
import { imageDTOToImageObject } from 'features/controlLayers/store/types';
import Konva from 'konva';
import type { Logger } from 'roarr';
import { uploadImage } from 'services/api/endpoints/images';
@ -33,19 +33,22 @@ type AnyObjectRenderer = CanvasBrushLineRenderer | CanvasEraserLineRenderer | Ca
*/
type AnyObjectState = CanvasBrushLineState | CanvasEraserLineState | CanvasImageState | CanvasRectState;
const TYPE = 'object_renderer';
/**
* Handles rendering of objects for a canvas entity.
*/
export class CanvasObjectRenderer {
static TYPE = 'object_renderer';
static KONVA_OBJECT_GROUP_NAME = `${CanvasObjectRenderer.TYPE}:object_group`;
static KONVA_COMPOSITING_RECT_NAME = `${CanvasObjectRenderer.TYPE}:compositing_rect`;
static KONVA_OBJECT_GROUP_NAME = `${TYPE}:object_group`;
static KONVA_COMPOSITING_RECT_NAME = `${TYPE}:compositing_rect`;
readonly type = TYPE;
id: string;
path: string[];
parent: CanvasLayerAdapter | CanvasMaskAdapter;
manager: CanvasManager;
log: Logger;
getLoggingContext: (extra?: JSONObject) => JSONObject;
/**
* A set of subscriptions that should be cleaned up when the transformer is destroyed.
@ -90,10 +93,10 @@ export class CanvasObjectRenderer {
};
constructor(parent: CanvasLayerAdapter | CanvasMaskAdapter) {
this.id = getPrefixedId(CanvasObjectRenderer.TYPE);
this.id = getPrefixedId(TYPE);
this.parent = parent;
this.path = this.parent.path.concat(this.id);
this.manager = parent.manager;
this.getLoggingContext = this.manager.buildGetLoggingContext(this);
this.log = this.manager.buildLogger(this.getLoggingContext);
this.log.trace('Creating object renderer');
@ -414,10 +417,14 @@ export class CanvasObjectRenderer {
repr = () => {
return {
id: this.id,
type: CanvasObjectRenderer.TYPE,
type: this.type,
parent: this.parent.id,
renderers: Array.from(this.renderers.values()).map((renderer) => renderer.repr()),
buffer: deepClone(this.buffer),
};
};
getLoggingContext = (): JSONObject => {
return { ...this.parent.getLoggingContext(), path: this.path.join('.') };
};
}

View File

@ -1,21 +1,25 @@
import type { JSONObject } from 'common/types';
import { rgbaColorToString } from 'common/util/colorCodeTransformers';
import { deepClone } from 'common/util/deepClone';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { CanvasObjectRenderer } from 'features/controlLayers/konva/CanvasObjectRenderer';
import type { CanvasRectState, GetLoggingContext } from 'features/controlLayers/store/types';
import type { CanvasRectState } from 'features/controlLayers/store/types';
import Konva from 'konva';
import type { Logger } from 'roarr';
const TYPE = 'rect';
export class CanvasRectRenderer {
static TYPE = 'rect';
static GROUP_NAME = `${CanvasRectRenderer.TYPE}_group`;
static RECT_NAME = `${CanvasRectRenderer.TYPE}_rect`;
static GROUP_NAME = `${TYPE}_group`;
static RECT_NAME = `${TYPE}_rect`;
readonly type = TYPE;
id: string;
path: string[];
parent: CanvasObjectRenderer;
manager: CanvasManager;
log: Logger;
getLoggingContext: GetLoggingContext;
state: CanvasRectState;
konva: {
@ -29,7 +33,7 @@ export class CanvasRectRenderer {
this.id = id;
this.parent = parent;
this.manager = parent.manager;
this.getLoggingContext = this.manager.buildGetLoggingContext(this);
this.path = this.parent.path.concat(this.id);
this.log = this.manager.buildLogger(this.getLoggingContext);
this.log.trace({ state }, 'Creating rect');
@ -76,10 +80,14 @@ export class CanvasRectRenderer {
repr() {
return {
id: this.id,
type: CanvasRectRenderer.TYPE,
type: this.type,
parent: this.parent.id,
isFirstRender: this.isFirstRender,
state: deepClone(this.state),
};
}
getLoggingContext = (): JSONObject => {
return { ...this.parent.getLoggingContext(), path: this.path.join('.') };
};
}

View File

@ -1,20 +1,24 @@
import type { JSONObject } from 'common/types';
import { CanvasImageRenderer } from 'features/controlLayers/konva/CanvasImage';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { CanvasPreview } from 'features/controlLayers/konva/CanvasPreview';
import { getPrefixedId } from 'features/controlLayers/konva/util';
import type { GetLoggingContext, StagingAreaImage } from 'features/controlLayers/store/types';
import type { StagingAreaImage } from 'features/controlLayers/store/types';
import Konva from 'konva';
import type { Logger } from 'roarr';
const TYPE = 'staging_area';
export class CanvasStagingArea {
static TYPE = 'staging_area';
static GROUP_NAME = `${CanvasStagingArea.TYPE}_group`;
static GROUP_NAME = `${TYPE}_group`;
readonly type = TYPE;
id: string;
path: string[];
parent: CanvasPreview;
manager: CanvasManager;
log: Logger;
getLoggingContext: GetLoggingContext;
konva: { group: Konva.Group };
@ -27,10 +31,10 @@ export class CanvasStagingArea {
subscriptions: Set<() => void> = new Set();
constructor(parent: CanvasPreview) {
this.id = getPrefixedId(CanvasStagingArea.TYPE);
this.id = getPrefixedId(TYPE);
this.parent = parent;
this.manager = this.parent.manager;
this.getLoggingContext = this.manager.buildGetLoggingContext(this);
this.path = this.manager.path.concat(this.id);
this.log = this.manager.buildLogger(this.getLoggingContext);
this.log.debug('Creating staging area');
@ -103,8 +107,12 @@ export class CanvasStagingArea {
repr = () => {
return {
id: this.id,
type: CanvasStagingArea.TYPE,
type: this.type,
selectedImage: this.selectedImage,
};
};
getLoggingContext = (): JSONObject => {
return { ...this.manager.getLoggingContext(), path: this.path.join('.') };
};
}

View File

@ -1,8 +1,9 @@
import type { JSONObject } from 'common/types';
import type { CanvasLayerAdapter } from 'features/controlLayers/konva/CanvasLayerAdapter';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { CanvasMaskAdapter } from 'features/controlLayers/konva/CanvasMaskAdapter';
import { getEmptyRect, getPrefixedId } from 'features/controlLayers/konva/util';
import type { Coordinate, GetLoggingContext, Rect } from 'features/controlLayers/store/types';
import type { Coordinate, Rect } from 'features/controlLayers/store/types';
import Konva from 'konva';
import { debounce, get } from 'lodash-es';
import type { Logger } from 'roarr';
@ -37,11 +38,13 @@ export class CanvasTransformer {
static ROTATE_ANCHOR_STROKE_COLOR = 'hsl(200 76% 40% / 1)'; // invokeBlue.700
static ROTATE_ANCHOR_SIZE = 12;
readonly type = CanvasTransformer.TYPE;
id: string;
path: string[];
parent: CanvasLayerAdapter | CanvasMaskAdapter;
manager: CanvasManager;
log: Logger;
getLoggingContext: GetLoggingContext;
/**
* The rect of the parent, _including_ transparent regions.
@ -100,8 +103,7 @@ export class CanvasTransformer {
this.id = getPrefixedId(CanvasTransformer.TYPE);
this.parent = parent;
this.manager = parent.manager;
this.getLoggingContext = this.manager.buildGetLoggingContext(this);
this.path = this.parent.path.concat(this.id);
this.log = this.manager.buildLogger(this.getLoggingContext);
this.konva = {
@ -729,7 +731,7 @@ export class CanvasTransformer {
repr = () => {
return {
id: this.id,
type: CanvasTransformer.TYPE,
type: this.type,
mode: this.interactionMode,
isTransformEnabled: this.isTransformEnabled,
isDragEnabled: this.isDragEnabled,
@ -749,4 +751,8 @@ export class CanvasTransformer {
this.konva.transformer.destroy();
this.konva.proxyRect.destroy();
};
getLoggingContext = (): JSONObject => {
return { ...this.parent.getLoggingContext(), path: this.path.join('.') };
};
}