Skip to content

Commit

Permalink
chore(ui): introduce a logger proxy - WF-85
Browse files Browse the repository at this point in the history
Introduce a simple abstraction to use logger in the application. For the moment, it's just a proxy to `console`, but it can be plugged to any library later. It's also a good way to prevent that logs are not displayed in the tests.
  • Loading branch information
madeindjs committed Dec 18, 2024
1 parent 00b964f commit cab44cd
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 44 deletions.
4 changes: 2 additions & 2 deletions src/ui/src/components/core/content/CoreDataframe.vue
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ import {
UNNAMED_INDEX_COLUMN_PATTERN,
} from "./CoreDataframe/constants";
import WdsButton from "@/wds/WdsButton.vue";
import { useLogger } from "@/composables/useLogger";
const description = "A component to display Pandas DataFrames.";
Expand Down Expand Up @@ -515,8 +516,7 @@ async function loadData() {
[ARQUERO_INTERNAL_ID]: () => aq.op.row_number(),
});
} catch (e) {
// eslint-disable-next-line no-console
console.error("Couldn't load dataframe from Arrow URL.", e);
useLogger().error("Couldn't load dataframe from Arrow URL.", e);
} finally {
isLoadingData.value = false;
}
Expand Down
5 changes: 3 additions & 2 deletions src/ui/src/components/core/content/CoreDataframe/useJobs.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useLogger } from "@/composables/useLogger";
import { shallowRef, ref, readonly } from "vue";

/**
Expand All @@ -6,6 +7,7 @@ import { shallowRef, ref, readonly } from "vue";
export function useJobs<T>(handler: (value: T) => Promise<void>) {
const jobs = shallowRef<T[]>([]);
const isRunning = ref(false);
const logger = useLogger();

async function run() {
if (isRunning.value) return;
Expand All @@ -18,8 +20,7 @@ export function useJobs<T>(handler: (value: T) => Promise<void>) {
try {
await handler(job);
} catch (error) {
// eslint-disable-next-line no-console
console.error("Error during handling job", job, error);
logger.error("Error during handling job", job, error);
} finally {
jobs.value = rest;
}
Expand Down
4 changes: 2 additions & 2 deletions src/ui/src/components/core/content/CoreDataframeLegacy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ import { onUnmounted } from "vue";
import WdsTextInput from "@/wds/WdsTextInput.vue";
import WdsControl from "@/wds/WdsControl.vue";
import BaseMarkdown from "../base/BaseMarkdown.vue";
import { useLogger } from "@/composables/useLogger";
const description = "A component to display Pandas DataFrames.";
const defaultDataframe = `data:application/vnd.apache.arrow.file;base64,QVJST1cxAAD/////iAMAABAAAAAAAAoADgAGAAUACAAKAAAAAAEEABAAAAAAAAoADAAAAAQACAAKAAAAlAIAAAQAAAABAAAADAAAAAgADAAEAAgACAAAAGwCAAAEAAAAXwIAAHsiaW5kZXhfY29sdW1ucyI6IFsiX19pbmRleF9sZXZlbF8wX18iXSwgImNvbHVtbl9pbmRleGVzIjogW3sibmFtZSI6IG51bGwsICJmaWVsZF9uYW1lIjogbnVsbCwgInBhbmRhc190eXBlIjogInVuaWNvZGUiLCAibnVtcHlfdHlwZSI6ICJvYmplY3QiLCAibWV0YWRhdGEiOiB7ImVuY29kaW5nIjogIlVURi04In19XSwgImNvbHVtbnMiOiBbeyJuYW1lIjogImNvbF9hIiwgImZpZWxkX25hbWUiOiAiY29sX2EiLCAicGFuZGFzX3R5cGUiOiAiaW50NjQiLCAibnVtcHlfdHlwZSI6ICJpbnQ2NCIsICJtZXRhZGF0YSI6IG51bGx9LCB7Im5hbWUiOiAiY29sX2IiLCAiZmllbGRfbmFtZSI6ICJjb2xfYiIsICJwYW5kYXNfdHlwZSI6ICJpbnQ2NCIsICJudW1weV90eXBlIjogImludDY0IiwgIm1ldGFkYXRhIjogbnVsbH0sIHsibmFtZSI6IG51bGwsICJmaWVsZF9uYW1lIjogIl9faW5kZXhfbGV2ZWxfMF9fIiwgInBhbmRhc190eXBlIjogImludDY0IiwgIm51bXB5X3R5cGUiOiAiaW50NjQiLCAibWV0YWRhdGEiOiBudWxsfV0sICJjcmVhdG9yIjogeyJsaWJyYXJ5IjogInB5YXJyb3ciLCAidmVyc2lvbiI6ICIxMi4wLjAifSwgInBhbmRhc192ZXJzaW9uIjogIjEuNS4zIn0ABgAAAHBhbmRhcwAAAwAAAIgAAABEAAAABAAAAJT///8AAAECEAAAACQAAAAEAAAAAAAAABEAAABfX2luZGV4X2xldmVsXzBfXwAAAJD///8AAAABQAAAAND///8AAAECEAAAABgAAAAEAAAAAAAAAAUAAABjb2xfYgAAAMD///8AAAABQAAAABAAFAAIAAYABwAMAAAAEAAQAAAAAAABAhAAAAAgAAAABAAAAAAAAAAFAAAAY29sX2EAAAAIAAwACAAHAAgAAAAAAAABQAAAAAAAAAD/////6AAAABQAAAAAAAAADAAWAAYABQAIAAwADAAAAAADBAAYAAAAMAAAAAAAAAAAAAoAGAAMAAQACAAKAAAAfAAAABAAAAACAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAAAAAAAAAAAAAMAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAwAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAD/////AAAAABAAAAAMABQABgAIAAwAEAAMAAAAAAAEADwAAAAoAAAABAAAAAEAAACYAwAAAAAAAPAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAACgAMAAAABAAIAAoAAACUAgAABAAAAAEAAAAMAAAACAAMAAQACAAIAAAAbAIAAAQAAABfAgAAeyJpbmRleF9jb2x1bW5zIjogWyJfX2luZGV4X2xldmVsXzBfXyJdLCAiY29sdW1uX2luZGV4ZXMiOiBbeyJuYW1lIjogbnVsbCwgImZpZWxkX25hbWUiOiBudWxsLCAicGFuZGFzX3R5cGUiOiAidW5pY29kZSIsICJudW1weV90eXBlIjogIm9iamVjdCIsICJtZXRhZGF0YSI6IHsiZW5jb2RpbmciOiAiVVRGLTgifX1dLCAiY29sdW1ucyI6IFt7Im5hbWUiOiAiY29sX2EiLCAiZmllbGRfbmFtZSI6ICJjb2xfYSIsICJwYW5kYXNfdHlwZSI6ICJpbnQ2NCIsICJudW1weV90eXBlIjogImludDY0IiwgIm1ldGFkYXRhIjogbnVsbH0sIHsibmFtZSI6ICJjb2xfYiIsICJmaWVsZF9uYW1lIjogImNvbF9iIiwgInBhbmRhc190eXBlIjogImludDY0IiwgIm51bXB5X3R5cGUiOiAiaW50NjQiLCAibWV0YWRhdGEiOiBudWxsfSwgeyJuYW1lIjogbnVsbCwgImZpZWxkX25hbWUiOiAiX19pbmRleF9sZXZlbF8wX18iLCAicGFuZGFzX3R5cGUiOiAiaW50NjQiLCAibnVtcHlfdHlwZSI6ICJpbnQ2NCIsICJtZXRhZGF0YSI6IG51bGx9XSwgImNyZWF0b3IiOiB7ImxpYnJhcnkiOiAicHlhcnJvdyIsICJ2ZXJzaW9uIjogIjEyLjAuMCJ9LCAicGFuZGFzX3ZlcnNpb24iOiAiMS41LjMifQAGAAAAcGFuZGFzAAADAAAAiAAAAEQAAAAEAAAAlP///wAAAQIQAAAAJAAAAAQAAAAAAAAAEQAAAF9faW5kZXhfbGV2ZWxfMF9fAAAAkP///wAAAAFAAAAA0P///wAAAQIQAAAAGAAAAAQAAAAAAAAABQAAAGNvbF9iAAAAwP///wAAAAFAAAAAEAAUAAgABgAHAAwAAAAQABAAAAAAAAECEAAAACAAAAAEAAAAAAAAAAUAAABjb2xfYQAAAAgADAAIAAcACAAAAAAAAAFAAAAAsAMAAEFSUk9XMQ==`;
Expand Down Expand Up @@ -418,8 +419,7 @@ async function loadData() {
baseTable = aqTable;
table.value = baseTable;
} catch (e) {
// eslint-disable-next-line no-console
console.error("Couldn't load dataframe from Arrow URL.", e);
useLogger().error("Couldn't load dataframe from Arrow URL.", e);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/ui/src/components/core/embed/CoreMapbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<script lang="ts">
import { FieldType } from "@/writerTypes";
import { cssClasses } from "@/renderer/sharedStyleFields";
import { useLogger } from "@/composables/useLogger";
const markersDefaultData = [
{ lat: 37.79322359164316, lng: -122.39999318828129, name: "Marker" },
Expand Down Expand Up @@ -137,8 +138,7 @@ const initMap = async () => {
map.value.on("load", renderMarkers);
}
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
useLogger().error(error);
}
};
Expand Down
9 changes: 5 additions & 4 deletions src/ui/src/components/core/other/CoreWebcamCapture.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
} from "@/renderer/sharedStyleFields";
import WdsButton from "@/wds/WdsButton.vue";
import WdsDropdownInput from "@/wds/WdsDropdownInput.vue";
import { useLogger } from "@/composables/useLogger";
const description =
"A user input component that allows users to capture images using their webcam.";
Expand Down Expand Up @@ -106,6 +107,8 @@ const fields = inject(injectionKeys.evaluatedFields);
const videoDevices: Ref<MediaDeviceInfo[]> = ref(null);
const preferredDeviceId: Ref<MediaDeviceInfo["deviceId"]> = ref(null);
const logger = useLogger();
onMounted(async () => {
videoDevices.value = await getVideoDevices();
preferredDeviceId.value = videoDevices.value?.[0]?.deviceId;
Expand Down Expand Up @@ -174,8 +177,7 @@ const startCapture = async (): Promise<void> => {
videoEl.value.style.display = "";
return new Promise((resolve, reject) => {
if (!navigator.mediaDevices.getUserMedia) {
// eslint-disable-next-line no-console
console.error("This browser doesn't support webcam connection.");
logger.error("This browser doesn't support webcam connection.");
reject();
}
Expand All @@ -201,8 +203,7 @@ const startCapture = async (): Promise<void> => {
resolve();
})
.catch((error) => {
// eslint-disable-next-line no-console
console.error(
logger.error(
"An error occurred when trying to use the webcam.",
error,
);
Expand Down
5 changes: 3 additions & 2 deletions src/ui/src/components/shared/SharedControlBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
</template>

<script setup lang="ts">
import { useLogger } from "@/composables/useLogger";
const props = defineProps<{
copyRawContent?: string;
copyStructuredContent?: string;
Expand All @@ -27,8 +29,7 @@ function copyToClipboard({ text = "" }: { text?: string }) {
try {
navigator.clipboard.writeText(text);
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
useLogger().error(error);
}
}
</script>
Expand Down
16 changes: 16 additions & 0 deletions src/ui/src/composables/useLogger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* eslint-disable no-console */

/**
* A simple abstraction to use logger in the application. For the moment, it's just a proxy to `console`, but it can be plugged to any library later.
*/
export function useLogger(): Pick<
typeof console,
"log" | "warn" | "info" | "error"
> {
return {
log: console.log,
warn: console.warn,
info: console.info,
error: console.error,
};
}
21 changes: 14 additions & 7 deletions src/ui/src/core/auditAndFix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
WriterComponentDefinition,
} from "@/writerTypes";
import { getComponentDefinition } from "./templateMap";
import { useLogger } from "@/composables/useLogger";

/**
* Audits integrity of ComponentMap. Applies automatic fixes if necessary.
Expand All @@ -23,9 +24,11 @@ export function auditAndFixComponents(components: ComponentMap): boolean {
}

export function auditAndFixComponent(component: Component): boolean {
const logger = useLogger();

const def = getComponentDefinition(component.type);
if (!def || def.category == "Fallback") {
console.error(
logger.error(
`Component ${component.id} (${component.type}). Invalid component type.`,
);
return false;
Expand Down Expand Up @@ -53,14 +56,15 @@ function traverseComponentTree(
}

function auditOrphanComponents(components: ComponentMap) {
const logger = useLogger();
const visited = Object.fromEntries(
Object.entries(components).map(([componentId]) => [componentId, false]),
);
traverseComponentTree("root", components, visited);
traverseComponentTree("workflows_root", components, visited);
Object.entries(visited).forEach(([componentId, isVisited]) => {
if (!isVisited) {
console.warn(
logger.warn(
`Component ${componentId} (${components[componentId].type}). Orphan component.`,
);
}
Expand All @@ -71,11 +75,12 @@ function auditComponentFieldKeys(
component: Component,
def: WriterComponentDefinition,
) {
const logger = useLogger();
const fieldKeys = Object.keys(def.fields ?? {});
if (!component.content) return;
Object.keys(component.content).forEach((contentFieldKey) => {
if (fieldKeys.includes(contentFieldKey)) return;
console.warn(
logger.warn(
`Component ${component.id} (${component.type}). Field key "${contentFieldKey}" is defined in the component but not in the template.`,
);
});
Expand All @@ -93,7 +98,8 @@ function auditComponentBinding(
def.events[boundEventType].bindable
)
return;
console.warn(
const logger = useLogger();
logger.warn(
`Component ${component.id} (${component.type}). The component is bound to event "${component.binding.eventType}" but the template doesn't define that event or it's not bindable.`,
);
}
Expand All @@ -110,14 +116,15 @@ function auditAndFixPositions(
component: Component,
components: ComponentMap,
): boolean {
const logger = useLogger();
let isFixApplied = false;
if (component.id == "root") {
if (component.position !== 0) {
console.error("Root must be at position 0.");
logger.error("Root must be at position 0.");
}
}
if (component.position == -1) {
console.error(
logger.error(
`Component ${component.id} (${component.type}). Invalid position.`,
);
}
Expand All @@ -136,7 +143,7 @@ function auditAndFixPositions(
const arithmeticProgression =
((positionfulChildren.length - 1) * positionfulChildren.length) / 2;
if (arithmeticProgression !== positionSum) {
console.error(
logger.error(
`Component ${component.id} (${component.type}). Invalid children positions. Automated fix will be applied.`,
);
fixPositions(positionfulChildren);
Expand Down
26 changes: 12 additions & 14 deletions src/ui/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { auditAndFixComponents } from "./auditAndFix";
import { parseAccessor } from "./parsing";
import { loadExtensions } from "./loadExtensions";
import { bigIntReplacer } from "./serializer";
import { useLogger } from "@/composables/useLogger";

const RECONNECT_DELAY_MS = 1000;
const KEEP_ALIVE_DELAY_MS = 60000;
Expand Down Expand Up @@ -191,6 +192,8 @@ export function generateCore() {
async function startSync(): Promise<void> {
if (webSocket) return; // Open WebSocket exists

const logger = useLogger();

const url = new URL("./api/stream", window.location.href);
url.protocol = url.protocol.replace("https", "wss");
url.protocol = url.protocol.replace("http", "ws");
Expand All @@ -199,7 +202,7 @@ export function generateCore() {
webSocket.onopen = () => {
clearFrontendMap();
syncHealth.value = "connected";
console.log("WebSocket connected. Initialising stream...");
logger.log("WebSocket connected. Initialising stream...");
sendFrontendMessage("streamInit", { sessionId });
};

Expand Down Expand Up @@ -236,7 +239,7 @@ export function generateCore() {
// Connection established correctly but closed due to invalid session.
// Do not attempt to reconnect, the session will remain invalid. Initialise a new session.

console.error("Invalid session. Reinitialising...");
logger.error("Invalid session. Reinitialising...");

// Take care of pending event resolutions and fail them.
await initSession();
Expand All @@ -245,12 +248,12 @@ export function generateCore() {

// Connection lost due to some other reason. Try to reconnect.

console.error("WebSocket closed. Attempting to reconnect...");
logger.error("WebSocket closed. Attempting to reconnect...");
setTimeout(async () => {
try {
await startSync();
} catch {
console.error("Couldn't reconnect.");
logger.error("Couldn't reconnect.");
}
}, RECONNECT_DELAY_MS);
};
Expand Down Expand Up @@ -336,11 +339,11 @@ export function generateCore() {
/**
* Sends a message to be hashed in the backend using the relevant keys.
* Due to security reasons, it works only in edit mode.
*
*
* @param message Messaged to be hashed
* @returns The hashed message
*/
async function hashMessage(message: string):Promise<string> {
async function hashMessage(message: string): Promise<string> {
return new Promise((resolve, reject) => {
const messageCallback = (r: {
ok: boolean;
Expand All @@ -353,13 +356,8 @@ export function generateCore() {
resolve(r.payload?.message);
};

sendFrontendMessage(
"hashRequest",
{ message },
messageCallback,
);
sendFrontendMessage("hashRequest", { message }, messageCallback);
});

}

async function sendCodeSaveRequest(newCode: string): Promise<void> {
Expand Down Expand Up @@ -440,6 +438,7 @@ export function generateCore() {
callback?.({ ok: false });
return;
}
const logger = useLogger();
const trackingId = frontendMessageCounter++;
try {
if (callback || track) {
Expand Down Expand Up @@ -468,8 +467,7 @@ export function generateCore() {
}
webSocket.send(JSON.stringify(wsData, bigIntReplacer));
} catch (error) {
// eslint-disable-next-line no-console
console.error("sendFrontendMessage error", error);
logger.error("sendFrontendMessage error", error);
callback?.({ ok: false });
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/ui/src/core/loadExtensions.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useLogger } from "@/composables/useLogger";
import { registerComponentTemplate } from "./templateMap";

const CUSTOM_COMPONENTS_GLOBAL_VAR = "WriterCustomComponentTemplates";
Expand All @@ -16,15 +17,16 @@ export async function loadExtensions(extensionPaths: string[]) {
}

async function importCustomComponentTemplate(path: string) {
console.log(`Importing custom component templates at "${path}"...`);
const logger = useLogger();
logger.log(`Importing custom component templates at "${path}"...`);
await import(/* @vite-ignore */ getRelativeExtensionsPath() + path);
Object.entries(window[CUSTOM_COMPONENTS_GLOBAL_VAR])?.forEach(
([key, template]) => {
if (checkComponentKey(key)) {
registerComponentTemplate(`custom_${key}`, template);
console.log(`Registering template for "${key}".`);
logger.log(`Registering template for "${key}".`);
} else {
console.warn(
logger.warn(
`custom component '${key}' is ignored. A custom component should be declared using only alphanumeric lowercase and _.`,
);
}
Expand Down Expand Up @@ -62,5 +64,3 @@ function getRelativeExtensionsPath() {

return `${pathname}extensions/`;
}


Loading

0 comments on commit cab44cd

Please sign in to comment.