diff --git a/desktop/src/main/log.ts b/desktop/src/main/log.ts index c66c09e44..0e504115c 100644 --- a/desktop/src/main/log.ts +++ b/desktop/src/main/log.ts @@ -60,11 +60,11 @@ const logInfo = (...params: any[]) => { .map((p) => (typeof p == "string" ? p : util.inspect(p))) .join(" "); log.info(`[main] ${message}`); - if (isDev) console.log(message); + if (isDev) console.log(`[info] ${message}`); }; const logDebug = (param: () => any) => { - if (isDev) console.log(`[main] [debug] ${util.inspect(param())}`); + if (isDev) console.log(`[debug] ${util.inspect(param())}`); }; /** diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts index 0d2c8f7bf..aa528b7ad 100644 --- a/desktop/src/preload.ts +++ b/desktop/src/preload.ts @@ -307,7 +307,7 @@ const getDirFiles = (dirPath: string): Promise => // // The copy itself is relatively fast, but the problem with transfering large // amounts of data is potentially running out of memory during the copy. -contextBridge.exposeInMainWorld("ElectronAPIs", { +contextBridge.exposeInMainWorld("electron", { // - General appVersion, openDirectory, diff --git a/web/apps/accounts/src/pages/account-handoff.tsx b/web/apps/accounts/src/pages/account-handoff.tsx index fcb363960..45d8fa968 100644 --- a/web/apps/accounts/src/pages/account-handoff.tsx +++ b/web/apps/accounts/src/pages/account-handoff.tsx @@ -1,8 +1,8 @@ +import log from "@/next/log"; import { VerticallyCentered } from "@ente/shared/components/Container"; import EnteSpinner from "@ente/shared/components/EnteSpinner"; import { ACCOUNTS_PAGES } from "@ente/shared/constants/pages"; import HTTPService from "@ente/shared/network/HTTPService"; -import { logError } from "@ente/shared/sentry"; import { LS_KEYS, getData, setData } from "@ente/shared/storage/localStorage"; import { useRouter } from "next/router"; import { useEffect } from "react"; @@ -16,7 +16,7 @@ const AccountHandoff = () => { router.push(ACCOUNTS_PAGES.PASSKEYS); } catch (e) { - logError(e, "Failed to deserialize and set passed user data"); + log.error("Failed to deserialize and set passed user data", e); router.push(ACCOUNTS_PAGES.LOGIN); } }; diff --git a/web/apps/accounts/src/pages/passkeys/flow/index.tsx b/web/apps/accounts/src/pages/passkeys/flow/index.tsx index 6c74bd65a..baf44c7e3 100644 --- a/web/apps/accounts/src/pages/passkeys/flow/index.tsx +++ b/web/apps/accounts/src/pages/passkeys/flow/index.tsx @@ -1,3 +1,4 @@ +import log from "@/next/log"; import { APPS, CLIENT_PACKAGE_NAMES } from "@ente/shared/apps/constants"; import { CenteredFlex, @@ -7,7 +8,6 @@ import EnteButton from "@ente/shared/components/EnteButton"; import EnteSpinner from "@ente/shared/components/EnteSpinner"; import FormPaper from "@ente/shared/components/Form/FormPaper"; import HTTPService from "@ente/shared/network/HTTPService"; -import { logError } from "@ente/shared/sentry"; import { LS_KEYS, setData } from "@ente/shared/storage/localStorage"; import InfoIcon from "@mui/icons-material/Info"; import { Box, Typography } from "@mui/material"; @@ -73,7 +73,7 @@ const PasskeysFlow = () => { try { beginData = await beginAuthentication(passkeySessionID); } catch (e) { - logError(e, "Couldn't begin passkey authentication"); + log.error("Couldn't begin passkey authentication", e); setErrored(true); return; } finally { @@ -89,7 +89,7 @@ const PasskeysFlow = () => { try { credential = await getCredential(beginData.options.publicKey); } catch (e) { - logError(e, "Couldn't get credential"); + log.error("Couldn't get credential", e); continue; } finally { tries++; @@ -117,7 +117,7 @@ const PasskeysFlow = () => { beginData.ceremonySessionID, ); } catch (e) { - logError(e, "Couldn't finish passkey authentication"); + log.error("Couldn't finish passkey authentication", e); setErrored(true); setLoading(false); return; diff --git a/web/apps/accounts/src/pages/passkeys/index.tsx b/web/apps/accounts/src/pages/passkeys/index.tsx index f41d8e3f2..977595af6 100644 --- a/web/apps/accounts/src/pages/passkeys/index.tsx +++ b/web/apps/accounts/src/pages/passkeys/index.tsx @@ -1,8 +1,8 @@ +import log from "@/next/log"; import { CenteredFlex } from "@ente/shared/components/Container"; import FormPaper from "@ente/shared/components/Form/FormPaper"; import SingleInputForm from "@ente/shared/components/SingleInputForm"; import { ACCOUNTS_PAGES } from "@ente/shared/constants/pages"; -import { logError } from "@ente/shared/sentry"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { Box, Typography } from "@mui/material"; import { t } from "i18next"; @@ -104,7 +104,7 @@ const Passkeys = () => { try { newCredential = await navigator.credentials.create(options); } catch (e) { - logError(e, "Error creating credential"); + log.error("Error creating credential", e); setFieldError("Failed to create credential"); return; } diff --git a/web/apps/accounts/src/services/passkeysService.ts b/web/apps/accounts/src/services/passkeysService.ts index ecc6ad406..27f9773e5 100644 --- a/web/apps/accounts/src/services/passkeysService.ts +++ b/web/apps/accounts/src/services/passkeysService.ts @@ -1,8 +1,9 @@ +import log from "@/next/log"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import _sodium from "libsodium-wrappers"; + const ENDPOINT = getEndpoint(); export const getPasskeys = async () => { @@ -16,7 +17,7 @@ export const getPasskeys = async () => { ); return await response.data; } catch (e) { - logError(e, "get passkeys failed"); + log.error("get passkeys failed", e); throw e; } }; @@ -33,7 +34,7 @@ export const renamePasskey = async (id: string, name: string) => { ); return await response.data; } catch (e) { - logError(e, "rename passkey failed"); + log.error("rename passkey failed", e); throw e; } }; @@ -50,7 +51,7 @@ export const deletePasskey = async (id: string) => { ); return await response.data; } catch (e) { - logError(e, "delete passkey failed"); + log.error("delete passkey failed", e); throw e; } }; @@ -68,7 +69,7 @@ export const getPasskeyRegistrationOptions = async () => { ); return await response.data; } catch (e) { - logError(e, "get passkey registration options failed"); + log.error("get passkey registration options failed", e); throw e; } }; @@ -116,7 +117,7 @@ export const finishPasskeyRegistration = async ( ); return await response.data; } catch (e) { - logError(e, "finish passkey registration failed"); + log.error("finish passkey registration failed", e); throw e; } }; @@ -142,7 +143,7 @@ export const beginPasskeyAuthentication = async ( return data.data; } catch (e) { - logError(e, "begin passkey authentication failed"); + log.error("begin passkey authentication failed", e); throw e; } }; @@ -194,7 +195,7 @@ export const finishPasskeyAuthentication = async ( return data.data; } catch (e) { - logError(e, "finish passkey authentication failed"); + log.error("finish passkey authentication failed", e); throw e; } }; diff --git a/web/apps/auth/src/services/index.ts b/web/apps/auth/src/services/index.ts index 893ddfb66..5fd032215 100644 --- a/web/apps/auth/src/services/index.ts +++ b/web/apps/auth/src/services/index.ts @@ -1,8 +1,8 @@ +import log from "@/next/log"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import { ApiError, CustomError } from "@ente/shared/error"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { getActualKey } from "@ente/shared/user"; import { HttpStatusCode } from "axios"; @@ -35,10 +35,7 @@ export const getAuthCodes = async (): Promise => { ); return Code.fromRawData(entity.id, decryptedCode); } catch (e) { - logError( - Error("failed to parse code"), - "codeId = " + entity.id, - ); + log.error(`failed to parse codeId = ${entity.id}`); return null; } }), @@ -62,7 +59,7 @@ export const getAuthCodes = async (): Promise => { return filteredAuthCodes; } catch (e) { if (e.message !== CustomError.AUTH_KEY_NOT_FOUND) { - logError(e, "get authenticator entities failed"); + log.error("get authenticator entities failed", e); } throw e; } @@ -85,7 +82,7 @@ export const getAuthKey = async (): Promise => { ) { throw Error(CustomError.AUTH_KEY_NOT_FOUND); } else { - logError(e, "Get key failed"); + log.error("Get key failed", e); throw e; } } @@ -109,7 +106,7 @@ export const getDiff = async ( ); return resp.data.diff; } catch (e) { - logError(e, "Get diff failed"); + log.error("Get diff failed", e); throw e; } }; diff --git a/web/apps/cast/src/pages/slideshow.tsx b/web/apps/cast/src/pages/slideshow.tsx index 3251b26ab..692e61154 100644 --- a/web/apps/cast/src/pages/slideshow.tsx +++ b/web/apps/cast/src/pages/slideshow.tsx @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import PairedSuccessfullyOverlay from "components/PairedSuccessfullyOverlay"; import Theatre from "components/Theatre"; import { FILE_TYPE } from "constants/file"; @@ -54,7 +54,7 @@ export default function Slideshow() { ); } } catch (e) { - logError(e, "error during sync"); + log.error("error during sync", e); router.push("/"); } }; @@ -107,7 +107,7 @@ export default function Slideshow() { return () => clearTimeout(timeoutId); } catch (e) { - logError(e, "error during sync"); + log.error("error during sync", e); router.push("/"); } }, []); diff --git a/web/apps/cast/src/services/cast/castService.ts b/web/apps/cast/src/services/cast/castService.ts index 0f8b368a5..84636d3a1 100644 --- a/web/apps/cast/src/services/cast/castService.ts +++ b/web/apps/cast/src/services/cast/castService.ts @@ -1,10 +1,9 @@ +import log from "@/next/log"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import { CustomError, parseSharingErrorCodes } from "@ente/shared/error"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import localForage from "@ente/shared/storage/localForage"; - import { Collection, CollectionPublicMagicMetadata } from "types/collection"; import { EncryptedEnteFile, EnteFile } from "types/file"; import { decryptFile, mergeMetadata, sortFiles } from "utils/file"; @@ -150,14 +149,14 @@ export const syncPublicFiles = async ( setPublicFiles([...sortFiles(mergeMetadata(files), sortAsc)]); } catch (e) { const parsedError = parseSharingErrorCodes(e); - logError(e, "failed to sync shared collection files"); + log.error("failed to sync shared collection files", e); if (parsedError.message === CustomError.TOKEN_EXPIRED) { throw e; } } return [...sortFiles(mergeMetadata(files), sortAsc)]; } catch (e) { - logError(e, "failed to get local or sync shared collection files"); + log.error("failed to get local or sync shared collection files", e); throw e; } }; @@ -217,7 +216,7 @@ const fetchFiles = async ( } while (resp.data.hasMore); return decryptedFiles; } catch (e) { - logError(e, "Get cast files failed"); + log.error("Get cast files failed", e); throw e; } }; @@ -264,7 +263,7 @@ export const getCastCollection = async ( await saveCollection(collection); return collection; } catch (e) { - logError(e, "failed to get cast collection"); + log.error("failed to get cast collection", e); throw e; } }; diff --git a/web/apps/cast/src/services/readerService.ts b/web/apps/cast/src/services/readerService.ts index 1514be630..19f9bb931 100644 --- a/web/apps/cast/src/services/readerService.ts +++ b/web/apps/cast/src/services/readerService.ts @@ -1,13 +1,14 @@ import { convertBytesToHumanReadable } from "@/next/file"; -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; export async function getUint8ArrayView(file: Blob): Promise { try { return new Uint8Array(await file.arrayBuffer()); } catch (e) { - logError(e, "reading file blob failed", { - fileSize: convertBytesToHumanReadable(file.size), - }); + log.error( + `Failed to read file blob of size ${convertBytesToHumanReadable(file.size)}`, + e, + ); throw e; } } diff --git a/web/apps/cast/src/services/typeDetectionService.ts b/web/apps/cast/src/services/typeDetectionService.ts index d6fe5b305..c52e2d80c 100644 --- a/web/apps/cast/src/services/typeDetectionService.ts +++ b/web/apps/cast/src/services/typeDetectionService.ts @@ -1,6 +1,5 @@ -import { convertBytesToHumanReadable } from "@/next/file"; +import log from "@/next/log"; import { CustomError } from "@ente/shared/error"; -import { logError } from "@ente/shared/sentry"; import { FILE_TYPE } from "constants/file"; import { KNOWN_NON_MEDIA_FORMATS, @@ -42,7 +41,6 @@ export async function getFileType(receivedFile: File): Promise { }; } catch (e) { const fileFormat = getFileExtension(receivedFile.name); - const fileSize = convertBytesToHumanReadable(receivedFile.size); const whiteListedFormat = WHITELISTED_FILE_FORMATS.find( (a) => a.exactType === fileFormat, ); @@ -53,16 +51,10 @@ export async function getFileType(receivedFile: File): Promise { throw Error(CustomError.UNSUPPORTED_FILE_FORMAT); } if (e.message === CustomError.NON_MEDIA_FILE) { - logError(e, "unsupported file format", { - fileFormat, - fileSize, - }); + log.error(`unsupported file format ${fileFormat}`, e); throw Error(CustomError.UNSUPPORTED_FILE_FORMAT); } - logError(e, "type detection failed", { - fileFormat, - fileSize, - }); + log.error(`type detection failed for format ${fileFormat}`, e); throw Error(CustomError.TYPE_DETECTION_FAILED(fileFormat)); } } diff --git a/web/apps/cast/src/utils/file/index.ts b/web/apps/cast/src/utils/file/index.ts index 8e3aec1a3..caa15d743 100644 --- a/web/apps/cast/src/utils/file/index.ts +++ b/web/apps/cast/src/utils/file/index.ts @@ -1,5 +1,5 @@ +import log from "@/next/log"; import ComlinkCryptoWorker from "@ente/shared/crypto"; -import { logError } from "@ente/shared/sentry"; import { FILE_TYPE, RAW_FORMATS } from "constants/file"; import CastDownloadManager from "services/castDownloadManager"; import { decodeLivePhoto } from "services/livePhotoService"; @@ -80,7 +80,7 @@ export async function decryptFile( pubMagicMetadata: filePubMagicMetadata, }; } catch (e) { - logError(e, "file decryption failed"); + log.error("file decryption failed", e); throw e; } } @@ -160,6 +160,6 @@ export const getPreviewableImage = async ( fileBlob = new Blob([fileBlob], { type: fileType.mimeType }); return fileBlob; } catch (e) { - logError(e, "failed to download file"); + log.error("failed to download file", e); } }; diff --git a/web/apps/photos/src/components/AuthenticateUserModal.tsx b/web/apps/photos/src/components/AuthenticateUserModal.tsx index 7459982bc..97f47e7fb 100644 --- a/web/apps/photos/src/components/AuthenticateUserModal.tsx +++ b/web/apps/photos/src/components/AuthenticateUserModal.tsx @@ -1,14 +1,14 @@ -import { useContext, useEffect, useState } from "react"; - +import log from "@/next/log"; import DialogBoxV2 from "@ente/shared/components/DialogBoxV2"; import VerifyMasterPasswordForm, { VerifyMasterPasswordFormProps, } from "@ente/shared/components/VerifyMasterPasswordForm"; -import { logError } from "@ente/shared/sentry"; -import { getData, LS_KEYS } from "@ente/shared/storage/localStorage"; +import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; import { KeyAttributes, User } from "@ente/shared/user/types"; import { t } from "i18next"; import { AppContext } from "pages/_app"; +import { useContext, useEffect, useState } from "react"; + interface Iprops { open: boolean; onClose: () => void; @@ -51,7 +51,7 @@ export default function AuthenticateUserModal({ setKeyAttributes(keyAttributes); } } catch (e) { - logError(e, "AuthenticateUserModal initialization failed"); + log.error("AuthenticateUserModal initialization failed", e); onClose(); somethingWentWrong(); } diff --git a/web/apps/photos/src/components/Collections/CollectionOptions/index.tsx b/web/apps/photos/src/components/Collections/CollectionOptions/index.tsx index f39f73b9c..ffdc6ad1f 100644 --- a/web/apps/photos/src/components/Collections/CollectionOptions/index.tsx +++ b/web/apps/photos/src/components/Collections/CollectionOptions/index.tsx @@ -1,6 +1,6 @@ +import log from "@/next/log"; import { HorizontalFlex } from "@ente/shared/components/Container"; import OverflowMenu from "@ente/shared/components/OverflowMenu/menu"; -import { logError } from "@ente/shared/sentry"; import MoreHoriz from "@mui/icons-material/MoreHoriz"; import { Box } from "@mui/material"; import { @@ -161,22 +161,15 @@ const CollectionOptions = (props: CollectionOptionsProps) => { case CollectionActions.SHOW_ALBUM_CAST_DIALOG: callback = showCastAlbumDialog; break; - default: - logError( - Error("invalid collection action "), - "handleCollectionAction failed", - ); - { - action; - } + log.error(`invalid collection action ${action}`); } return async (...args: any) => { try { loader && startLoading(); await callback(...args); } catch (e) { - logError(e, "collection action failed", { action }); + log.error(`collection action ${action} failed`, e); setDialogMessage({ title: t("ERROR"), content: t("UNKNOWN_ERROR"), diff --git a/web/apps/photos/src/components/Collections/CollectionShare/emailShare/ManageParticipant.tsx b/web/apps/photos/src/components/Collections/CollectionShare/emailShare/ManageParticipant.tsx index 55562e996..74bf9828c 100644 --- a/web/apps/photos/src/components/Collections/CollectionShare/emailShare/ManageParticipant.tsx +++ b/web/apps/photos/src/components/Collections/CollectionShare/emailShare/ManageParticipant.tsx @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import BlockIcon from "@mui/icons-material/Block"; import DoneIcon from "@mui/icons-material/Done"; import ModeEditIcon from "@mui/icons-material/ModeEdit"; @@ -63,8 +63,7 @@ export default function ManageParticipant({ selectedParticipant.role = newRole; await galleryContext.syncWithRemote(false, true); } catch (e) { - const errorMessage = handleSharingErrors(e); - logError(e, errorMessage); + log.error(handleSharingErrors(e), e); } }; diff --git a/web/apps/photos/src/components/DeleteAccountModal.tsx b/web/apps/photos/src/components/DeleteAccountModal.tsx index 87cfe64bd..744fbf312 100644 --- a/web/apps/photos/src/components/DeleteAccountModal.tsx +++ b/web/apps/photos/src/components/DeleteAccountModal.tsx @@ -1,8 +1,8 @@ +import log from "@/next/log"; import { logoutUser } from "@ente/accounts/services/user"; import DialogBoxV2 from "@ente/shared/components/DialogBoxV2"; import EnteButton from "@ente/shared/components/EnteButton"; import { DELETE_ACCOUNT_EMAIL } from "@ente/shared/constants/urls"; -import { logError } from "@ente/shared/sentry"; import { Button, Link, Stack } from "@mui/material"; import { Formik, FormikHelpers } from "formik"; import { t } from "i18next"; @@ -92,7 +92,7 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { askToMailForDeletion(); } } catch (e) { - logError(e, "Error while initiating account deletion"); + log.error("Error while initiating account deletion", e); somethingWentWrong(); } finally { setLoading(false); @@ -147,7 +147,7 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { await deleteAccount(decryptedChallenge, reason, feedback); logoutUser(); } catch (e) { - logError(e, "solveChallengeAndDeleteAccount failed"); + log.error("solveChallengeAndDeleteAccount failed", e); somethingWentWrong(); } finally { setLoading(false); diff --git a/web/apps/photos/src/components/Directory/index.tsx b/web/apps/photos/src/components/Directory/index.tsx index 154db456e..a99581134 100644 --- a/web/apps/photos/src/components/Directory/index.tsx +++ b/web/apps/photos/src/components/Directory/index.tsx @@ -1,6 +1,6 @@ -import ElectronAPIs from "@/next/electron"; +import { ensureElectron } from "@/next/electron"; +import log from "@/next/log"; import LinkButton from "@ente/shared/components/LinkButton"; -import { logError } from "@ente/shared/sentry"; import { Tooltip } from "@mui/material"; import { styled } from "@mui/material/styles"; @@ -19,9 +19,9 @@ const DirectoryPathContainer = styled(LinkButton)( export const DirectoryPath = ({ width, path }) => { const handleClick = async () => { try { - await ElectronAPIs.openDirectory(path); + await ensureElectron().openDirectory(path); } catch (e) { - logError(e, "openDirectory failed"); + log.error("openDirectory failed", e); } }; return ( diff --git a/web/apps/photos/src/components/FilesDownloadProgress.tsx b/web/apps/photos/src/components/FilesDownloadProgress.tsx index 1185cc61c..81c01369f 100644 --- a/web/apps/photos/src/components/FilesDownloadProgress.tsx +++ b/web/apps/photos/src/components/FilesDownloadProgress.tsx @@ -1,7 +1,5 @@ -import ElectronAPIs from "@/next/electron"; import Notification from "components/Notification"; import { t } from "i18next"; -import isElectron from "is-electron"; import { AppContext } from "pages/_app"; import { GalleryContext } from "pages/gallery"; import { useContext } from "react"; @@ -101,8 +99,9 @@ export const FilesDownloadProgress: React.FC = ({ const handleOnClick = (id: number) => () => { const attributes = attributesList.find((attr) => attr.id === id); - if (isElectron()) { - ElectronAPIs.openDirectory(attributes.downloadDirPath); + const electron = globalThis.electron; + if (electron) { + electron.openDirectory(attributes.downloadDirPath); } else { if (attributes.isHidden) { galleryContext.openHiddenSection(() => { diff --git a/web/apps/photos/src/components/MachineLearning/MLSearchSettings/index.tsx b/web/apps/photos/src/components/MachineLearning/MLSearchSettings/index.tsx index b1da26a65..9b33a984a 100644 --- a/web/apps/photos/src/components/MachineLearning/MLSearchSettings/index.tsx +++ b/web/apps/photos/src/components/MachineLearning/MLSearchSettings/index.tsx @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { Box, DialogProps, Typography } from "@mui/material"; import { EnteDrawer } from "components/EnteDrawer"; import { t } from "i18next"; @@ -41,7 +41,7 @@ const MLSearchSettings = ({ open, onClose, onRootClose }) => { updateMlSearchEnabled(true); } } catch (e) { - logError(e, "Enable ML search failed"); + log.error("Enable ML search failed", e); somethingWentWrong(); } }; @@ -54,7 +54,7 @@ const MLSearchSettings = ({ open, onClose, onRootClose }) => { closeEnableFaceSearch(); finishLoading(); } catch (e) { - logError(e, "Enable face search failed"); + log.error("Enable face search failed", e); somethingWentWrong(); } }; @@ -64,7 +64,7 @@ const MLSearchSettings = ({ open, onClose, onRootClose }) => { await updateMlSearchEnabled(false); onClose(); } catch (e) { - logError(e, "Disable ML search failed"); + log.error("Disable ML search failed", e); somethingWentWrong(); } }; @@ -76,7 +76,7 @@ const MLSearchSettings = ({ open, onClose, onRootClose }) => { await disableMlSearch(); finishLoading(); } catch (e) { - logError(e, "Disable face search failed"); + log.error("Disable face search failed", e); somethingWentWrong(); } }; diff --git a/web/apps/photos/src/components/MachineLearning/PeopleList.tsx b/web/apps/photos/src/components/MachineLearning/PeopleList.tsx index fe7d323bb..0e358ce33 100644 --- a/web/apps/photos/src/components/MachineLearning/PeopleList.tsx +++ b/web/apps/photos/src/components/MachineLearning/PeopleList.tsx @@ -1,5 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { CACHES } from "@ente/shared/storage/cacheStorage/constants"; import { styled } from "@mui/material"; import { Legend } from "components/PhotoViewer/styledComponents/Legend"; @@ -87,11 +86,11 @@ export function PhotoPeopleList(props: PhotoPeopleListProps) { let didCancel = false; async function updateFaceImages() { - addLogLine("calling getPeopleList"); + log.info("calling getPeopleList"); const startTime = Date.now(); const people = await getPeopleList(props.file); - addLogLine("getPeopleList", Date.now() - startTime, "ms"); - addLogLine("getPeopleList done, didCancel: ", didCancel); + log.info(`getPeopleList ${Date.now() - startTime} ms`); + log.info(`getPeopleList done, didCancel: ${didCancel}`); !didCancel && setPeople(people); } @@ -130,7 +129,7 @@ export function AllPeopleList(props: AllPeopleListProps) { } !didCancel && setPeople(people); } catch (e) { - logError(e, "updateFaceImages failed"); + log.error("updateFaceImages failed", e); } } updateFaceImages(); diff --git a/web/apps/photos/src/components/PhotoFrame.tsx b/web/apps/photos/src/components/PhotoFrame.tsx index 405f09ac4..90e1cf32c 100644 --- a/web/apps/photos/src/components/PhotoFrame.tsx +++ b/web/apps/photos/src/components/PhotoFrame.tsx @@ -1,8 +1,7 @@ +import log from "@/next/log"; import { PHOTOS_PAGES } from "@ente/shared/constants/pages"; import { CustomError } from "@ente/shared/error"; import useMemoSingleThreaded from "@ente/shared/hooks/useMemoSingleThreaded"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; import { styled } from "@mui/material"; import PhotoViewer from "components/PhotoViewer"; import { TRASH_SECTION } from "constants/collection"; @@ -184,7 +183,7 @@ const PhotoFrame = ({ const file = displayFiles[index]; // this is to prevent outdated updateURL call from updating the wrong file if (file.id !== id) { - addLogLine( + log.info( `[${id}]PhotoSwipe: updateURL: file id mismatch: ${file.id} !== ${id}`, ); throw Error(CustomError.UPDATE_URL_FILE_ID_MISMATCH); @@ -204,7 +203,7 @@ const PhotoFrame = ({ const file = displayFiles[index]; // this is to prevent outdate updateSrcURL call from updating the wrong file if (file.id !== id) { - addLogLine( + log.info( `[${id}]PhotoSwipe: updateSrcURL: file id mismatch: ${file.id}`, ); throw Error(CustomError.UPDATE_URL_FILE_ID_MISMATCH); @@ -212,7 +211,7 @@ const PhotoFrame = ({ if (file.isSourceLoaded && !forceUpdate) { throw Error(CustomError.URL_ALREADY_SET); } else if (file.conversionFailed) { - addLogLine(`[${id}]PhotoSwipe: updateSrcURL: conversion failed`); + log.info(`[${id}]PhotoSwipe: updateSrcURL: conversion failed`); throw Error(CustomError.FILE_CONVERSION_FAILED); } @@ -308,7 +307,7 @@ const PhotoFrame = ({ index: number, item: EnteFile, ) => { - addLogLine( + log.info( `[${ item.id }] getSlideData called for thumbnail:${!!item.msrc} sourceLoaded:${ @@ -319,17 +318,15 @@ const PhotoFrame = ({ if (!item.msrc) { try { if (thumbFetching[item.id]) { - addLogLine( - `[${item.id}] thumb download already in progress`, - ); + log.info(`[${item.id}] thumb download already in progress`); return; } - addLogLine(`[${item.id}] doesn't have thumbnail`); + log.info(`[${item.id}] doesn't have thumbnail`); thumbFetching[item.id] = true; const url = await DownloadManager.getThumbnailForPreview(item); try { updateURL(index)(item.id, url); - addLogLine( + log.info( `[${ item.id }] calling invalidateCurrItems for thumbnail msrc :${!!item.msrc}`, @@ -340,35 +337,35 @@ const PhotoFrame = ({ } } catch (e) { if (e.message !== CustomError.URL_ALREADY_SET) { - logError( - e, + log.error( "updating photoswipe after msrc url update failed", + e, ); } // ignore } } catch (e) { - logError(e, "getSlideData failed get msrc url failed"); + log.error("getSlideData failed get msrc url failed", e); thumbFetching[item.id] = false; } } if (item.isSourceLoaded || item.conversionFailed) { if (item.isSourceLoaded) { - addLogLine(`[${item.id}] source already loaded`); + log.info(`[${item.id}] source already loaded`); } if (item.conversionFailed) { - addLogLine(`[${item.id}] conversion failed`); + log.info(`[${item.id}] conversion failed`); } return; } if (fetching[item.id]) { - addLogLine(`[${item.id}] file download already in progress`); + log.info(`[${item.id}] file download already in progress`); return; } try { - addLogLine(`[${item.id}] new file src request`); + log.info(`[${item.id}] new file src request`); fetching[item.id] = true; const srcURLs = await DownloadManager.getFileForPreview(item); if (item.metadata.fileType === FILE_TYPE.LIVE_PHOTO) { @@ -383,7 +380,7 @@ const PhotoFrame = ({ }; try { await updateSrcURL(index, item.id, dummyImgSrcUrl); - addLogLine( + log.info( `[${item.id}] calling invalidateCurrItems for live photo imgSrc, source loaded :${item.isSourceLoaded}`, ); instance.invalidateCurrItems(); @@ -392,9 +389,9 @@ const PhotoFrame = ({ } } catch (e) { if (e.message !== CustomError.URL_ALREADY_SET) { - logError( - e, + log.error( "updating photoswipe after for live photo imgSrc update failed", + e, ); } } @@ -417,7 +414,7 @@ const PhotoFrame = ({ loadedLivePhotoSrcURL, true, ); - addLogLine( + log.info( `[${item.id}] calling invalidateCurrItems for live photo complete, source loaded :${item.isSourceLoaded}`, ); instance.invalidateCurrItems(); @@ -426,16 +423,16 @@ const PhotoFrame = ({ } } catch (e) { if (e.message !== CustomError.URL_ALREADY_SET) { - logError( - e, + log.error( "updating photoswipe for live photo complete update failed", + e, ); } } } else { try { await updateSrcURL(index, item.id, srcURLs); - addLogLine( + log.info( `[${item.id}] calling invalidateCurrItems for src, source loaded :${item.isSourceLoaded}`, ); instance.invalidateCurrItems(); @@ -444,15 +441,15 @@ const PhotoFrame = ({ } } catch (e) { if (e.message !== CustomError.URL_ALREADY_SET) { - logError( - e, + log.error( "updating photoswipe after src url update failed", + e, ); } } } } catch (e) { - logError(e, "getSlideData failed get src url failed"); + log.error("getSlideData failed get src url failed", e); fetching[item.id] = false; // no-op } @@ -467,22 +464,18 @@ const PhotoFrame = ({ item.metadata.fileType !== FILE_TYPE.VIDEO && item.metadata.fileType !== FILE_TYPE.LIVE_PHOTO ) { - logError( - new Error(), - "getConvertedVideo called for non video file", - ); + log.error("getConvertedVideo called for non video file"); return; } if (item.conversionFailed) { - logError( - new Error(), + log.error( "getConvertedVideo called for file that conversion failed", ); return; } try { updateURL(index)(item.id, item.msrc, true); - addLogLine( + log.info( `[${ item.id }] calling invalidateCurrItems for thumbnail msrc :${!!item.msrc}`, @@ -493,12 +486,15 @@ const PhotoFrame = ({ } } catch (e) { if (e.message !== CustomError.URL_ALREADY_SET) { - logError(e, "updating photoswipe after msrc url update failed"); + log.error( + "updating photoswipe after msrc url update failed", + e, + ); } // ignore } try { - addLogLine( + log.info( `[${item.id}] new file getConvertedVideo request- ${item.metadata.title}}`, ); fetching[item.id] = true; @@ -507,7 +503,7 @@ const PhotoFrame = ({ try { await updateSrcURL(index, item.id, srcURL, true); - addLogLine( + log.info( `[${item.id}] calling invalidateCurrItems for src, source loaded :${item.isSourceLoaded}`, ); instance.invalidateCurrItems(); @@ -516,15 +512,15 @@ const PhotoFrame = ({ } } catch (e) { if (e.message !== CustomError.URL_ALREADY_SET) { - logError( - e, + log.error( "updating photoswipe after src url update failed", + e, ); } throw e; } } catch (e) { - logError(e, "getConvertedVideo failed get src url failed"); + log.error("getConvertedVideo failed get src url failed", e); fetching[item.id] = false; // no-op } diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderCaption.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderCaption.tsx index 76f4d5ca9..871da2b05 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderCaption.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderCaption.tsx @@ -1,5 +1,5 @@ +import log from "@/next/log"; import { FlexWrapper } from "@ente/shared/components/Container"; -import { logError } from "@ente/shared/sentry"; import Close from "@mui/icons-material/Close"; import Done from "@mui/icons-material/Done"; import { Box, IconButton, TextField } from "@mui/material"; @@ -48,7 +48,7 @@ export function RenderCaption({ scheduleUpdate(); } } catch (e) { - logError(e, "failed to update caption"); + log.error("failed to update caption", e); } }; diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderCreationTime.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderCreationTime.tsx index 123eb8800..9d5cad467 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderCreationTime.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderCreationTime.tsx @@ -1,5 +1,5 @@ +import log from "@/next/log"; import { FlexWrapper } from "@ente/shared/components/Container"; -import { logError } from "@ente/shared/sentry"; import { formatDate, formatTime } from "@ente/shared/time/format"; import CalendarTodayIcon from "@mui/icons-material/CalendarToday"; import EnteDateTimePicker from "components/EnteDateTimePicker"; @@ -44,7 +44,7 @@ export function RenderCreationTime({ scheduleUpdate(); } } catch (e) { - logError(e, "failed to update creationTime"); + log.error("failed to update creationTime", e); } finally { closeEditMode(); setLoading(false); diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx index e5761d5c3..74ae87380 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx @@ -1,5 +1,5 @@ +import log from "@/next/log"; import { FlexWrapper } from "@ente/shared/components/Container"; -import { logError } from "@ente/shared/sentry"; import PhotoOutlined from "@mui/icons-material/PhotoOutlined"; import VideocamOutlined from "@mui/icons-material/VideocamOutlined"; import Box from "@mui/material/Box"; @@ -86,7 +86,7 @@ export function RenderFileName({ scheduleUpdate(); } } catch (e) { - logError(e, "failed to update file name"); + log.error("failed to update file name", e); throw e; } }; diff --git a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/TransformMenu.tsx b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/TransformMenu.tsx index aa096d8a4..3dd8f1a42 100644 --- a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/TransformMenu.tsx +++ b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/TransformMenu.tsx @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import Crop169Icon from "@mui/icons-material/Crop169"; import Crop32Icon from "@mui/icons-material/Crop32"; import CropSquareIcon from "@mui/icons-material/CropSquare"; @@ -172,10 +172,13 @@ const TransformMenu = () => { setCanvasLoading(false); setTransformationPerformed(true); } catch (e) { - logError(e, "crop handler failed", { - widthRatio, - heightRatio, - }); + log.error( + `crop handler failed - ${JSON.stringify({ + widthRatio, + heightRatio, + })}`, + e, + ); } }; const createRotationHandler = (rotation: "left" | "right") => () => { @@ -189,9 +192,7 @@ const TransformMenu = () => { setCanvasLoading(false); setTransformationPerformed(true); } catch (e) { - logError(e, "rotation handler failed", { - rotation, - }); + log.error(`rotation handler (${rotation}) failed`, e); } }; @@ -204,9 +205,7 @@ const TransformMenu = () => { setCanvasLoading(false); setTransformationPerformed(true); } catch (e) { - logError(e, "flip handler failed", { - direction, - }); + log.error(`flip handler ${direction} failed`, e); } }; diff --git a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx index bf4a186b7..997ad3d27 100644 --- a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx @@ -1,3 +1,4 @@ +import log from "@/next/log"; import { Backdrop, Box, @@ -23,7 +24,6 @@ import { HorizontalFlex, } from "@ente/shared/components/Container"; import EnteButton from "@ente/shared/components/EnteButton"; -import { logError } from "@ente/shared/sentry"; import { downloadUsingAnchor } from "@ente/shared/utils"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; import CloseIcon from "@mui/icons-material/Close"; @@ -275,7 +275,7 @@ const ImageEditorOverlay = (props: IProps) => { invert !== FILTER_DEFAULT_VALUES.invert, ); } catch (e) { - logError(e, "Error applying filters"); + log.error("Error applying filters", e); } }, [brightness, contrast, blur, saturation, invert, canvasRef, fileURL]); @@ -329,7 +329,7 @@ const ImageEditorOverlay = (props: IProps) => { }); } } catch (e) { - logError(e, "Error applying filters"); + log.error("Error applying filters", e); throw e; } }; @@ -422,7 +422,7 @@ const ImageEditorOverlay = (props: IProps) => { }; }); } catch (e) { - logError(e, "Error loading canvas"); + log.error("Error loading canvas", e); } }; @@ -447,7 +447,7 @@ const ImageEditorOverlay = (props: IProps) => { canvas.toBlob(resolve, mimeType); }); } catch (e) { - logError(e, "Error exporting canvas to blob"); + log.error("Error exporting canvas to blob", e); throw e; } }; @@ -492,7 +492,7 @@ const ImageEditorOverlay = (props: IProps) => { ); downloadUsingAnchor(tempImgURL, editedFile.name); } catch (e) { - logError(e, "Error downloading edited photo"); + log.error("Error downloading edited photo", e); } }; @@ -520,7 +520,7 @@ const ImageEditorOverlay = (props: IProps) => { props.onClose(); props.closePhotoViewer(); } catch (e) { - logError(e, "Error saving copy to ente"); + log.error("Error saving copy to ente", e); } }; return ( diff --git a/web/apps/photos/src/components/PhotoViewer/index.tsx b/web/apps/photos/src/components/PhotoViewer/index.tsx index ffed1df8f..29da75e53 100644 --- a/web/apps/photos/src/components/PhotoViewer/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/index.tsx @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import Photoswipe from "photoswipe"; import PhotoswipeUIDefault from "photoswipe/dist/photoswipe-ui-default"; import { useContext, useEffect, useMemo, useRef, useState } from "react"; @@ -16,7 +16,6 @@ import { isSupportedRawFormat, } from "utils/file"; -import log from "@/next/log"; import { FlexWrapper } from "@ente/shared/components/Container"; import EnteSpinner from "@ente/shared/components/EnteSpinner"; import AlbumOutlined from "@mui/icons-material/AlbumOutlined"; @@ -496,7 +495,7 @@ function PhotoViewer(props: Iprops) { } needUpdate.current = true; } catch (e) { - logError(e, "onFavClick failed"); + log.error("onFavClick failed", e); } }; @@ -511,7 +510,7 @@ function PhotoViewer(props: Iprops) { updateItems(props.items.filter((item) => item.id !== file.id)); needUpdate.current = true; } catch (e) { - logError(e, "trashFile failed"); + log.error("trashFile failed", e); } }; @@ -562,7 +561,7 @@ function PhotoViewer(props: Iprops) { } } } catch (e) { - logError(e, "updateItems failed"); + log.error("updateItems failed", e); } }; @@ -573,7 +572,7 @@ function PhotoViewer(props: Iprops) { photoSwipe.updateSize(true); } } catch (e) { - logError(e, "refreshPhotoswipe failed"); + log.error("refreshPhotoswipe failed", e); } }; @@ -613,9 +612,10 @@ function PhotoViewer(props: Iprops) { } catch (e) { setExif({ key: file.src, value: null }); const fileExtension = getFileExtension(file.metadata.title); - logError(e, "checkExifAvailable failed", { - extension: fileExtension, - }); + log.error( + `checkExifAvailable failed for extension ${fileExtension}`, + e, + ); } }; diff --git a/web/apps/photos/src/components/Search/SearchBar/searchInput/MenuWithPeople.tsx b/web/apps/photos/src/components/Search/SearchBar/searchInput/MenuWithPeople.tsx index f57ce85cf..89bdce56a 100644 --- a/web/apps/photos/src/components/Search/SearchBar/searchInput/MenuWithPeople.tsx +++ b/web/apps/photos/src/components/Search/SearchBar/searchInput/MenuWithPeople.tsx @@ -25,7 +25,7 @@ const Caption = styled("span")` const MenuWithPeople = (props) => { const appContext = useContext(AppContext); - // addLogLine("props.selectProps.options: ", selectRef); + // log.info("props.selectProps.options: ", selectRef); const peopleSuggestions = props.selectProps.options.filter( (o) => o.type === SuggestionType.PERSON, ); diff --git a/web/apps/photos/src/components/Sidebar/AdvancedSettings.tsx b/web/apps/photos/src/components/Sidebar/AdvancedSettings.tsx index e854d70d6..6668fef1f 100644 --- a/web/apps/photos/src/components/Sidebar/AdvancedSettings.tsx +++ b/web/apps/photos/src/components/Sidebar/AdvancedSettings.tsx @@ -1,3 +1,4 @@ +import log from "@/next/log"; import ChevronRight from "@mui/icons-material/ChevronRight"; import ScienceIcon from "@mui/icons-material/Science"; import { Box, DialogProps, Stack, Typography } from "@mui/material"; @@ -9,7 +10,6 @@ import { t } from "i18next"; import { useContext, useEffect, useState } from "react"; import { VerticallyCenteredFlex } from "@ente/shared/components/Container"; -import { logError } from "@ente/shared/sentry"; import { EnteMenuItem } from "components/Menu/EnteMenuItem"; import { MenuItemGroup } from "components/Menu/MenuItemGroup"; import isElectron from "is-electron"; @@ -41,7 +41,7 @@ export default function AdvancedSettings({ open, onClose, onRootClose }) { try { appContext.setIsCFProxyDisabled(!appContext.isCFProxyDisabled); } catch (e) { - logError(e, "toggleFasterUpload failed"); + log.error("toggleFasterUpload failed", e); } }; const [indexingStatus, setIndexingStatus] = useState({ diff --git a/web/apps/photos/src/components/Sidebar/DebugSection.tsx b/web/apps/photos/src/components/Sidebar/DebugSection.tsx index 1295dc856..28c65ca8e 100644 --- a/web/apps/photos/src/components/Sidebar/DebugSection.tsx +++ b/web/apps/photos/src/components/Sidebar/DebugSection.tsx @@ -1,15 +1,12 @@ +import log from "@/next/log"; +import { savedLogs } from "@/next/log-web"; +import { downloadAsFile } from "@ente/shared/utils"; +import Typography from "@mui/material/Typography"; +import { EnteMenuItem } from "components/Menu/EnteMenuItem"; import { t } from "i18next"; import { AppContext } from "pages/_app"; import { useContext, useEffect, useState } from "react"; import { Trans } from "react-i18next"; - -import ElectronAPIs from "@/next/electron"; -import { savedLogs } from "@/next/log-web"; -import { addLogLine } from "@ente/shared/logging"; -import { downloadAsFile } from "@ente/shared/utils"; -import Typography from "@mui/material/Typography"; -import { EnteMenuItem } from "components/Menu/EnteMenuItem"; -import isElectron from "is-electron"; import { isInternalUser } from "utils/user"; import { testUpload } from "../../../tests/upload.test"; import { @@ -19,16 +16,12 @@ import { export default function DebugSection() { const appContext = useContext(AppContext); - const [appVersion, setAppVersion] = useState(null); + const [appVersion, setAppVersion] = useState(); + + const electron = globalThis.electron; useEffect(() => { - const main = async () => { - if (isElectron()) { - const appVersion = await ElectronAPIs.appVersion(); - setAppVersion(appVersion); - } - }; - main(); + electron?.appVersion().then((v) => setAppVersion(v)); }); const confirmLogDownload = () => @@ -46,8 +39,8 @@ export default function DebugSection() { }); const downloadLogs = () => { - addLogLine("Downloading logs"); - if (isElectron()) ElectronAPIs.openLogDirectory(); + log.info("Downloading logs"); + if (electron) electron.openLogDirectory(); else downloadAsFile(`debug_logs_${Date.now()}.txt`, savedLogs()); }; diff --git a/web/apps/photos/src/components/Sidebar/MapSetting/ModifyMapEnabled.tsx b/web/apps/photos/src/components/Sidebar/MapSetting/ModifyMapEnabled.tsx index 22aa8bbbb..0a4c0b9dc 100644 --- a/web/apps/photos/src/components/Sidebar/MapSetting/ModifyMapEnabled.tsx +++ b/web/apps/photos/src/components/Sidebar/MapSetting/ModifyMapEnabled.tsx @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { Box, DialogProps } from "@mui/material"; import { EnteDrawer } from "components/EnteDrawer"; import { AppContext } from "pages/_app"; @@ -14,7 +14,7 @@ const ModifyMapEnabled = ({ open, onClose, onRootClose, mapEnabled }) => { await updateMapEnabled(false); onClose(); } catch (e) { - logError(e, "Disable Map failed"); + log.error("Disable Map failed", e); somethingWentWrong(); } }; @@ -24,7 +24,7 @@ const ModifyMapEnabled = ({ open, onClose, onRootClose, mapEnabled }) => { await updateMapEnabled(true); onClose(); } catch (e) { - logError(e, "Enable Map failed"); + log.error("Enable Map failed", e); somethingWentWrong(); } }; diff --git a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx index 9160fe4a2..904eab747 100644 --- a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx +++ b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx @@ -1,3 +1,4 @@ +import log from "@/next/log"; import RecoveryKey from "@ente/shared/components/RecoveryKey"; import { ACCOUNTS_PAGES, @@ -21,7 +22,6 @@ import { generateEncryptionKey, } from "@ente/shared/crypto/internal/libsodium"; import { getAccountsURL } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import { THEME_COLOR } from "@ente/shared/themes/constants"; import { EnteMenuItem } from "components/Menu/EnteMenuItem"; import WatchFolder from "components/WatchFolder"; @@ -109,7 +109,7 @@ export default function UtilitySection({ closeSidebar }) { )}&token=${accountsToken}`, ); } catch (e) { - logError(e, "failed to redirect to accounts page"); + log.error("failed to redirect to accounts page", e); } }; diff --git a/web/apps/photos/src/components/Upload/Uploader.tsx b/web/apps/photos/src/components/Upload/Uploader.tsx index b1557c77b..4d81b1612 100644 --- a/web/apps/photos/src/components/Upload/Uploader.tsx +++ b/web/apps/photos/src/components/Upload/Uploader.tsx @@ -1,7 +1,6 @@ -import ElectronAPIs from "@/next/electron"; +import log from "@/next/log"; +import type { Electron } from "@/next/types/ipc"; import { CustomError } from "@ente/shared/error"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; import { isPromise } from "@ente/shared/utils"; import DiscFullIcon from "@mui/icons-material/DiscFull"; import UserNameInputDialog from "components/UserNameInputDialog"; @@ -133,6 +132,8 @@ export default function Uploader(props: Props) { const uploaderNameRef = useRef(null); const isDragAndDrop = useRef(false); + const electron = globalThis.electron; + const closeUploadProgress = () => setUploadProgressView(false); const showUserNameInputDialog = () => setUserNameInputDialogView(true); @@ -178,9 +179,7 @@ export default function Uploader(props: Props) { if (isElectron()) { ImportService.getPendingUploads().then( ({ files: electronFiles, collectionName, type }) => { - addLogLine( - `found pending desktop upload, resuming uploads`, - ); + log.info(`found pending desktop upload, resuming uploads`); resumeDesktopUpload(type, electronFiles, collectionName); }, ); @@ -211,29 +210,29 @@ export default function Uploader(props: Props) { pickedUploadType.current === PICKED_UPLOAD_TYPE.FOLDERS && props.webFolderSelectorFiles?.length > 0 ) { - addLogLine(`received folder upload request`); + log.info(`received folder upload request`); setWebFiles(props.webFolderSelectorFiles); } else if ( pickedUploadType.current === PICKED_UPLOAD_TYPE.FILES && props.webFileSelectorFiles?.length > 0 ) { - addLogLine(`received file upload request`); + log.info(`received file upload request`); setWebFiles(props.webFileSelectorFiles); } else if (props.dragAndDropFiles?.length > 0) { isDragAndDrop.current = true; - if (isElectron()) { + if (electron) { const main = async () => { try { - addLogLine(`uploading dropped files from desktop app`); + log.info(`uploading dropped files from desktop app`); // check and parse dropped files which are zip files let electronFiles = [] as ElectronFile[]; for (const file of props.dragAndDropFiles) { if (file.name.endsWith(".zip")) { const zipFiles = - await ElectronAPIs.getElectronFilesFromGoogleZip( + await electron.getElectronFilesFromGoogleZip( (file as any).path, ); - addLogLine( + log.info( `zip file - ${file.name} contains ${zipFiles.length} files`, ); electronFiles = [...electronFiles, ...zipFiles]; @@ -251,18 +250,18 @@ export default function Uploader(props: Props) { ); } } - addLogLine( + log.info( `uploading dropped files from desktop app - ${electronFiles.length} files found`, ); setElectronFiles(electronFiles); } catch (e) { - logError(e, "failed to upload desktop dropped files"); + log.error("failed to upload desktop dropped files", e); setWebFiles(props.dragAndDropFiles); } }; main(); } else { - addLogLine(`uploading dropped files from web app`); + log.info(`uploading dropped files from web app`); setWebFiles(props.dragAndDropFiles); } } @@ -278,7 +277,7 @@ export default function Uploader(props: Props) { webFiles?.length > 0 || appContext.sharedFiles?.length > 0 ) { - addLogLine( + log.info( `upload request type:${ electronFiles?.length > 0 ? "electronFiles" @@ -293,13 +292,13 @@ export default function Uploader(props: Props) { ); if (uploadManager.isUploadRunning()) { if (watchFolderService.isUploadRunning()) { - addLogLine( + log.info( "watchFolder upload was running, pausing it to run user upload", ); // pause watch folder service on user upload watchFolderService.pauseRunningSync(); } else { - addLogLine( + log.info( "an upload is already running, rejecting new upload request", ); // no-op @@ -371,7 +370,7 @@ export default function Uploader(props: Props) { uploaderName?: string, ) => { try { - addLogLine( + log.info( `upload file to an existing collection name:${collection.name}, collectionID:${collection.id}`, ); await preCollectionCreationAction(); @@ -387,7 +386,7 @@ export default function Uploader(props: Props) { uploaderName, ); } catch (e) { - logError(e, "Failed to upload files to existing collections"); + log.error("Failed to upload files to existing collections", e); } }; @@ -396,7 +395,7 @@ export default function Uploader(props: Props) { collectionName?: string, ) => { try { - addLogLine( + log.info( `upload file to an new collections strategy:${strategy} ,collectionName:${collectionName}`, ); await preCollectionCreationAction(); @@ -416,7 +415,7 @@ export default function Uploader(props: Props) { toUploadFiles.current, ); } - addLogLine( + log.info( `upload collections - [${[...collectionNameToFilesMap.keys()]}]`, ); try { @@ -446,7 +445,7 @@ export default function Uploader(props: Props) { } } catch (e) { closeUploadProgress(); - logError(e, "Failed to create album"); + log.error("Failed to create album", e); appContext.setDialogMessage({ title: t("ERROR"), @@ -461,7 +460,7 @@ export default function Uploader(props: Props) { ); toUploadFiles.current = null; } catch (e) { - logError(e, "Failed to upload files to new collections"); + log.error("Failed to upload files to new collections", e); } }; @@ -501,22 +500,22 @@ export default function Uploader(props: Props) { uploaderName?: string, ) => { try { - addLogLine("uploadFiles called"); + log.info("uploadFiles called"); preUploadAction(); if ( - isElectron() && + electron && !isPendingDesktopUpload.current && !watchFolderService.isUploadRunning() ) { await ImportService.setToUploadCollection(collections); if (zipPaths.current) { - await ElectronAPIs.setToUploadFiles( + await electron.setToUploadFiles( PICKED_UPLOAD_TYPE.ZIPS, zipPaths.current, ); zipPaths.current = null; } - await ElectronAPIs.setToUploadFiles( + await electron.setToUploadFiles( PICKED_UPLOAD_TYPE.FILES, filesWithCollectionToUploadIn.map( ({ file }) => (file as ElectronFile).path, @@ -543,9 +542,9 @@ export default function Uploader(props: Props) { watchFolderService.resumePausedSync(); } } - } catch (err) { - logError(err, "failed to upload files"); - showUserFacingError(err.message); + } catch (e) { + log.error("failed to upload files", e); + showUserFacingError(e.message); closeUploadProgress(); } finally { postUploadAction(); @@ -554,7 +553,7 @@ export default function Uploader(props: Props) { const retryFailed = async () => { try { - addLogLine("user retrying failed upload"); + log.info("user retrying failed upload"); const filesWithCollections = uploadManager.getFailedFilesWithCollections(); const uploaderName = uploadManager.getUploaderName(); @@ -564,9 +563,9 @@ export default function Uploader(props: Props) { filesWithCollections.collections, uploaderName, ); - } catch (err) { - logError(err, "retry failed files failed"); - showUserFacingError(err.message); + } catch (e) { + log.error("retry failed files failed", e); + showUserFacingError(e.message); closeUploadProgress(); } finally { postUploadAction(); @@ -629,7 +628,7 @@ export default function Uploader(props: Props) { ) => { try { if (accessedThroughSharedURL) { - addLogLine( + log.info( `uploading files to pulbic collection - ${props.uploadCollection.name} - ${props.uploadCollection.id}`, ); const uploaderName = await getPublicCollectionUploaderName( @@ -644,7 +643,7 @@ export default function Uploader(props: Props) { if (isPendingDesktopUpload.current) { isPendingDesktopUpload.current = false; if (pendingDesktopUploadCollectionName.current) { - addLogLine( + log.info( `upload pending files to collection - ${pendingDesktopUploadCollectionName.current}`, ); uploadFilesToNewCollections( @@ -653,7 +652,7 @@ export default function Uploader(props: Props) { ); pendingDesktopUploadCollectionName.current = null; } else { - addLogLine( + log.info( `pending upload - strategy - "multiple collections" `, ); uploadFilesToNewCollections( @@ -663,7 +662,7 @@ export default function Uploader(props: Props) { return; } if (isElectron() && pickedUploadType === PICKED_UPLOAD_TYPE.ZIPS) { - addLogLine("uploading zip files"); + log.info("uploading zip files"); uploadFilesToNewCollections( UPLOAD_STRATEGY.COLLECTION_PER_FOLDER, ); @@ -684,7 +683,7 @@ export default function Uploader(props: Props) { } let showNextModal = () => {}; if (importSuggestion.hasNestedFolders) { - addLogLine(`nested folders detected`); + log.info(`nested folders detected`); showNextModal = () => setChoiceModalView(true); } else { showNextModal = () => @@ -697,24 +696,27 @@ export default function Uploader(props: Props) { intent: CollectionSelectorIntent.upload, }); } catch (e) { - logError(e, "handleCollectionCreationAndUpload failed"); + log.error("handleCollectionCreationAndUpload failed", e); } }; - const handleDesktopUpload = async (type: PICKED_UPLOAD_TYPE) => { + const handleDesktopUpload = async ( + type: PICKED_UPLOAD_TYPE, + electron: Electron, + ) => { let files: ElectronFile[]; pickedUploadType.current = type; if (type === PICKED_UPLOAD_TYPE.FILES) { - files = await ElectronAPIs.showUploadFilesDialog(); + files = await electron.showUploadFilesDialog(); } else if (type === PICKED_UPLOAD_TYPE.FOLDERS) { - files = await ElectronAPIs.showUploadDirsDialog(); + files = await electron.showUploadDirsDialog(); } else { - const response = await ElectronAPIs.showUploadZipDialog(); + const response = await electron.showUploadZipDialog(); files = response.files; zipPaths.current = response.zipPaths; } if (files?.length > 0) { - addLogLine( + log.info( ` desktop upload for type:${type} and fileCount: ${files?.length} requested`, ); setElectronFiles(files); @@ -738,8 +740,8 @@ export default function Uploader(props: Props) { }; const handleUpload = (type) => () => { - if (isElectron()) { - handleDesktopUpload(type); + if (electron) { + handleDesktopUpload(type, electron); } else { handleWebUpload(type); } @@ -767,7 +769,7 @@ export default function Uploader(props: Props) { uploaderName, ); } catch (e) { - logError(e, "public upload failed "); + log.error("public upload failed ", e); } }; diff --git a/web/apps/photos/src/components/WatchFolder/index.tsx b/web/apps/photos/src/components/WatchFolder/index.tsx index 9c8d536e0..4ccfd4138 100644 --- a/web/apps/photos/src/components/WatchFolder/index.tsx +++ b/web/apps/photos/src/components/WatchFolder/index.tsx @@ -1,17 +1,14 @@ +import DialogTitleWithCloseButton from "@ente/shared/components/DialogBox/TitleWithCloseButton"; import { Button, Dialog, DialogContent, Stack } from "@mui/material"; +import UploadStrategyChoiceModal from "components/Upload/UploadStrategyChoiceModal"; +import { PICKED_UPLOAD_TYPE, UPLOAD_STRATEGY } from "constants/upload"; import { t } from "i18next"; import { AppContext } from "pages/_app"; import { useContext, useEffect, useState } from "react"; import watchFolderService from "services/watchFolder/watchFolderService"; import { WatchMapping } from "types/watchFolder"; -import { MappingList } from "./mappingList"; - -import ElectronAPIs from "@/next/electron"; -import DialogTitleWithCloseButton from "@ente/shared/components/DialogBox/TitleWithCloseButton"; -import UploadStrategyChoiceModal from "components/Upload/UploadStrategyChoiceModal"; -import { PICKED_UPLOAD_TYPE, UPLOAD_STRATEGY } from "constants/upload"; -import isElectron from "is-electron"; import { getImportSuggestion } from "utils/upload"; +import { MappingList } from "./mappingList"; interface Iprops { open: boolean; @@ -24,10 +21,10 @@ export default function WatchFolder({ open, onClose }: Iprops) { const [choiceModalOpen, setChoiceModalOpen] = useState(false); const appContext = useContext(AppContext); + const electron = globalThis.electron; + useEffect(() => { - if (!isElectron()) { - return; - } + if (!electron) return; watchFolderService.getWatchMappings().then((m) => setMappings(m)); }, []); @@ -52,8 +49,10 @@ export default function WatchFolder({ open, onClose }: Iprops) { }; const addFolderForWatching = async (path: string) => { + if (!electron) return; + setInputFolderPath(path); - const files = await ElectronAPIs.getDirFiles(path); + const files = await electron.getDirFiles(path); const analysisResult = getImportSuggestion( PICKED_UPLOAD_TYPE.FOLDERS, files, diff --git a/web/apps/photos/src/components/pages/gallery/Avatar.tsx b/web/apps/photos/src/components/pages/gallery/Avatar.tsx index d3bbcb6df..caa9b8b78 100644 --- a/web/apps/photos/src/components/pages/gallery/Avatar.tsx +++ b/web/apps/photos/src/components/pages/gallery/Avatar.tsx @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { styled } from "@mui/material"; import { useTheme } from "@mui/material/styles"; import { GalleryContext } from "pages/gallery"; @@ -47,7 +47,7 @@ const Avatar: React.FC = ({ file, email, opacity }) => { // getting email from in-memory id-email map const email = userIDToEmailMap.get(file.ownerID); if (!email) { - logError(Error(), "email not found in userIDToEmailMap"); + log.error("email not found in userIDToEmailMap"); return; } const colorIndex = @@ -58,8 +58,7 @@ const Avatar: React.FC = ({ file, email, opacity }) => { } else if (file.ownerID === user.id) { const uploaderName = file.pubMagicMetadata.data.uploaderName; if (!uploaderName) { - logError( - Error(), + log.error( "uploaderName not found in file.pubMagicMetadata.data", ); return; @@ -67,8 +66,8 @@ const Avatar: React.FC = ({ file, email, opacity }) => { setUserLetter(uploaderName[0].toUpperCase()); setColorCode(PUBLIC_COLLECTED_FILES_AVATAR_COLOR_CODE); } - } catch (err) { - logError(err, "AvatarIcon.tsx - useLayoutEffect file failed"); + } catch (e) { + log.error("AvatarIcon.tsx - useLayoutEffect file failed", e); } }, [file]); @@ -87,15 +86,15 @@ const Avatar: React.FC = ({ file, email, opacity }) => { (key) => userIDToEmailMap.get(key) === email, ); if (!id) { - logError(Error(), `ID not found for email: ${email}`); + log.error(`ID not found for email: ${email}`); return; } const colorIndex = id % theme.colors.avatarColors.length; const colorCode = theme.colors.avatarColors[colorIndex]; setUserLetter(email[0].toUpperCase()); setColorCode(colorCode); - } catch (err) { - logError(err, "AvatarIcon.tsx - useLayoutEffect email failed"); + } catch (e) { + log.error("AvatarIcon.tsx - useLayoutEffect email failed", e); } }, [email]); diff --git a/web/apps/photos/src/components/pages/gallery/PlanSelector/card/index.tsx b/web/apps/photos/src/components/pages/gallery/PlanSelector/card/index.tsx index 41e577675..2ef3c361f 100644 --- a/web/apps/photos/src/components/pages/gallery/PlanSelector/card/index.tsx +++ b/web/apps/photos/src/components/pages/gallery/PlanSelector/card/index.tsx @@ -1,6 +1,6 @@ +import log from "@/next/log"; import { SUPPORT_EMAIL } from "@ente/shared/constants/urls"; import { useLocalState } from "@ente/shared/hooks/useLocalState"; -import { logError } from "@ente/shared/sentry"; import { LS_KEYS } from "@ente/shared/storage/localStorage"; import { Link, Stack } from "@mui/material"; import { PLAN_PERIOD } from "constants/gallery"; @@ -92,7 +92,7 @@ function PlanSelectorCard(props: Props) { } setPlans(plans); } catch (e) { - logError(e, "plan selector modal open failed"); + log.error("plan selector modal open failed", e); props.closeModal(); appContext.setDialogMessage({ title: t("OPEN_PLAN_SELECTOR_MODAL_FAILED"), diff --git a/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx b/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx index 1750d30e2..8704258f8 100644 --- a/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx +++ b/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx @@ -1,7 +1,7 @@ +import log from "@/next/log"; import { Overlay } from "@ente/shared/components/Container"; import { CustomError } from "@ente/shared/error"; import useLongPress from "@ente/shared/hooks/useLongPress"; -import { logError } from "@ente/shared/sentry"; import { formatDateRelative } from "@ente/shared/time/format"; import AlbumOutlined from "@mui/icons-material/AlbumOutlined"; import PlayCircleOutlineOutlinedIcon from "@mui/icons-material/PlayCircleOutlineOutlined"; @@ -271,7 +271,7 @@ export default function PreviewCard(props: IProps) { updateURL(file.id, url); } catch (e) { if (e.message !== CustomError.URL_ALREADY_SET) { - logError(e, "preview card useEffect failed"); + log.error("preview card useEffect failed", e); } // no-op } diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index c8f2ce355..4594b2e20 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -1,6 +1,6 @@ import { CustomHead } from "@/next/components/Head"; -import ElectronAPIs from "@/next/electron"; import { setupI18n } from "@/next/i18n"; +import log from "@/next/log"; import { logStartupBanner } from "@/next/log-web"; import { AppUpdateInfo } from "@/next/types/ipc"; import { @@ -23,12 +23,9 @@ import EnteSpinner from "@ente/shared/components/EnteSpinner"; import { MessageContainer } from "@ente/shared/components/MessageContainer"; import AppNavbar from "@ente/shared/components/Navbar/app"; import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages"; -import { CustomError } from "@ente/shared/error"; import { Events, eventBus } from "@ente/shared/events"; import { useLocalState } from "@ente/shared/hooks/useLocalState"; -import { addLogLine } from "@ente/shared/logging"; import HTTPService from "@ente/shared/network/HTTPService"; -import { logError } from "@ente/shared/sentry"; import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; import { getLocalMapEnabled, @@ -156,7 +153,8 @@ export default function App({ Component, pageProps }: AppProps) { }, []); useEffect(() => { - if (isElectron()) { + const electron = globalThis.electron; + if (electron) { const showUpdateDialog = (updateInfo: AppUpdateInfo) => { if (updateInfo.autoUpdatable) { setDialogMessage( @@ -176,7 +174,7 @@ export default function App({ Component, pageProps }: AppProps) { }); } }; - ElectronAPIs.registerUpdateEventListener(showUpdateDialog); + electron.registerUpdateEventListener(showUpdateDialog); } }, []); @@ -190,7 +188,7 @@ export default function App({ Component, pageProps }: AppProps) { setMlSearchEnabled(mlSearchConfig.enabled); mlWorkManager.setMlSearchEnabled(mlSearchConfig.enabled); } catch (e) { - logError(e, "Error while loading mlSearchEnabled"); + log.error("Error while loading mlSearchEnabled", e); } }; loadMlSearchState(); @@ -200,7 +198,7 @@ export default function App({ Component, pageProps }: AppProps) { mlWorkManager.setMlSearchEnabled(false); }); } catch (e) { - logError(e, "Error while subscribing to logout event"); + log.error("Error while subscribing to logout event", e); } }, []); @@ -214,10 +212,10 @@ export default function App({ Component, pageProps }: AppProps) { } const initExport = async () => { try { - addLogLine("init export"); + log.info("init export"); const token = getToken(); if (!token) { - addLogLine( + log.info( "User not logged in, not starting export continuous sync job", ); return; @@ -238,11 +236,11 @@ export default function App({ Component, pageProps }: AppProps) { exportService.enableContinuousExport(); } if (isExportInProgress(exportRecord.stage)) { - addLogLine("export was in progress, resuming"); + log.info("export was in progress, resuming"); exportService.scheduleExport(); } } catch (e) { - logError(e, "init export failed"); + log.error("init export failed", e); } }; initExport(); @@ -251,7 +249,7 @@ export default function App({ Component, pageProps }: AppProps) { exportService.disableContinuousExport(); }); } catch (e) { - logError(e, "Error while subscribing to logout event"); + log.error("Error while subscribing to logout event", e); } }, []); @@ -268,9 +266,7 @@ export default function App({ Component, pageProps }: AppProps) { const redirectAction = redirectMap.get(redirect); window.location.href = await redirectAction(); } else { - logError(CustomError.BAD_REQUEST, "invalid redirection", { - redirect, - }); + log.error(`invalid redirection ${redirect}`); } }; @@ -337,7 +333,7 @@ export default function App({ Component, pageProps }: AppProps) { setMlSearchEnabled(enabled); mlWorkManager.setMlSearchEnabled(enabled); } catch (e) { - logError(e, "Error while updating mlSearchEnabled"); + log.error("Error while updating mlSearchEnabled", e); } }; @@ -347,7 +343,7 @@ export default function App({ Component, pageProps }: AppProps) { setLocalMapEnabled(enabled); setMapEnabled(enabled); } catch (e) { - logError(e, "Error while updating mapEnabled"); + log.error("Error while updating mapEnabled", e); } }; diff --git a/web/apps/photos/src/pages/gallery/index.tsx b/web/apps/photos/src/pages/gallery/index.tsx index 606216afa..69b833802 100644 --- a/web/apps/photos/src/pages/gallery/index.tsx +++ b/web/apps/photos/src/pages/gallery/index.tsx @@ -60,38 +60,11 @@ import { sortFiles, } from "utils/file"; -import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages"; -import { CustomError } from "@ente/shared/error"; -import { logError } from "@ente/shared/sentry"; -import CollectionNamer, { - CollectionNamerAttributes, -} from "components/Collections/CollectionNamer"; -import Uploader from "components/Upload/Uploader"; -import PlanSelector from "components/pages/gallery/PlanSelector"; -import { - ALL_SECTION, - ARCHIVE_SECTION, - CollectionSummaryType, - DUMMY_UNCATEGORIZED_COLLECTION, - HIDDEN_ITEMS_SECTION, - TRASH_SECTION, -} from "constants/collection"; -import { AppContext } from "pages/_app"; -import { getLocalTrashedFiles, syncTrash } from "services/trashService"; -import { - COLLECTION_OPS_TYPE, - constructCollectionNameMap, - getArchivedCollections, - getDefaultHiddenCollectionIDs, - getSelectedCollection, - handleCollectionOps, - hasNonSystemCollections, - splitNormalAndHiddenCollections, -} from "utils/collection"; - -import ElectronAPIs from "@/next/electron"; +import log from "@/next/log"; import { APPS } from "@ente/shared/apps/constants"; import { CenteredFlex } from "@ente/shared/components/Container"; +import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages"; +import { CustomError } from "@ente/shared/error"; import useFileInput from "@ente/shared/hooks/useFileInput"; import useMemoSingleThreaded from "@ente/shared/hooks/useMemoSingleThreaded"; import InMemoryStore, { MS_KEYS } from "@ente/shared/storage/InMemoryStore"; @@ -101,6 +74,9 @@ import { User } from "@ente/shared/user/types"; import { isPromise } from "@ente/shared/utils"; import AuthenticateUserModal from "components/AuthenticateUserModal"; import Collections from "components/Collections"; +import CollectionNamer, { + CollectionNamerAttributes, +} from "components/Collections/CollectionNamer"; import ExportModal from "components/ExportModal"; import { FilesDownloadProgress, @@ -112,16 +88,27 @@ import FixCreationTime, { import GalleryEmptyState from "components/GalleryEmptyState"; import { ITEM_TYPE, TimeStampListItem } from "components/PhotoList"; import SearchResultInfo from "components/Search/SearchResultInfo"; +import Uploader from "components/Upload/Uploader"; import UploadInputs from "components/UploadSelectorInputs"; import { GalleryNavbar } from "components/pages/gallery/Navbar"; +import PlanSelector from "components/pages/gallery/PlanSelector"; +import { + ALL_SECTION, + ARCHIVE_SECTION, + CollectionSummaryType, + DUMMY_UNCATEGORIZED_COLLECTION, + HIDDEN_ITEMS_SECTION, + TRASH_SECTION, +} from "constants/collection"; import { SYNC_INTERVAL_IN_MICROSECONDS } from "constants/gallery"; -import isElectron from "is-electron"; +import { AppContext } from "pages/_app"; import { ClipService } from "services/clipService"; import { constructUserIDToEmailMap } from "services/collectionService"; import downloadManager from "services/download"; import { syncEmbeddings } from "services/embeddingService"; import { syncEntities } from "services/entityService"; import locationSearchService from "services/locationSearchService"; +import { getLocalTrashedFiles, syncTrash } from "services/trashService"; import uploadManager from "services/upload/uploadManager"; import { Collection, CollectionSummaries } from "types/collection"; import { EnteFile } from "types/file"; @@ -134,6 +121,16 @@ import { } from "types/gallery"; import { Search, SearchResultSummary, UpdateSearch } from "types/search"; import { FamilyData } from "types/user"; +import { + COLLECTION_OPS_TYPE, + constructCollectionNameMap, + getArchivedCollections, + getDefaultHiddenCollectionIDs, + getSelectedCollection, + handleCollectionOps, + hasNonSystemCollections, + splitNormalAndHiddenCollections, +} from "utils/collection"; import ComlinkSearchWorker from "utils/comlink/ComlinkSearchWorker"; import { isArchivedFile } from "utils/magicMetadata"; import { getSessionExpiredMessage } from "utils/ui"; @@ -321,6 +318,7 @@ export default function Gallery() { return; } preloadImage("/images/subscription-card-background"); + const electron = globalThis.electron; const main = async () => { const valid = await validateKey(); if (!valid) { @@ -363,9 +361,9 @@ export default function Gallery() { syncInterval.current = setInterval(() => { syncWithRemote(false, true); }, SYNC_INTERVAL_IN_MICROSECONDS); - if (isElectron()) { + if (electron) { void ClipService.setupOnFileUploadListener(); - ElectronAPIs.registerForegroundEventListener(() => { + electron.registerForegroundEventListener(() => { syncWithRemote(false, true); }); } @@ -373,8 +371,8 @@ export default function Gallery() { main(); return () => { clearInterval(syncInterval.current); - if (isElectron()) { - ElectronAPIs.registerForegroundEventListener(() => {}); + if (electron) { + electron.registerForegroundEventListener(() => {}); ClipService.removeOnFileUploadListener(); } }; @@ -719,7 +717,7 @@ export default function Gallery() { router.push(PAGES.CREDENTIALS); break; default: - logError(e, "syncWithRemote failed"); + log.error("syncWithRemote failed", e); } } finally { setTempDeletedFileIds(new Set()); @@ -871,7 +869,7 @@ export default function Gallery() { clearSelection(); await syncWithRemote(false, true); } catch (e) { - logError(e, "collection ops failed", { ops }); + log.error(`collection ops (${ops}) failed`, e); setDialogMessage({ title: t("ERROR"), @@ -916,7 +914,7 @@ export default function Gallery() { clearSelection(); await syncWithRemote(false, true); } catch (e) { - logError(e, "file ops failed", { ops }); + log.error(`file ops (${ops}) failed`, e); setDialogMessage({ title: t("ERROR"), @@ -935,7 +933,7 @@ export default function Gallery() { const collection = await createAlbum(collectionName); await collectionOpsHelper(ops)(collection); } catch (e) { - logError(e, "create and collection ops failed", { ops }); + log.error(`create and collection ops (${ops}) failed`, e); setDialogMessage({ title: t("ERROR"), diff --git a/web/apps/photos/src/pages/index.tsx b/web/apps/photos/src/pages/index.tsx index 1b46f199b..f29020086 100644 --- a/web/apps/photos/src/pages/index.tsx +++ b/web/apps/photos/src/pages/index.tsx @@ -1,4 +1,4 @@ -import ElectronAPIs from "@/next/electron"; +import log from "@/next/log"; import Login from "@ente/accounts/components/Login"; import SignUp from "@ente/accounts/components/SignUp"; import { APPS } from "@ente/shared/apps/constants"; @@ -7,14 +7,12 @@ import EnteSpinner from "@ente/shared/components/EnteSpinner"; import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages"; import { saveKeyInSessionStore } from "@ente/shared/crypto/helpers"; import { getAlbumsURL } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import localForage from "@ente/shared/storage/localForage"; import { getData, LS_KEYS } from "@ente/shared/storage/localStorage"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { getKey, SESSION_KEYS } from "@ente/shared/storage/sessionStorage"; import { Button, styled, Typography, TypographyProps } from "@mui/material"; import { t } from "i18next"; -import isElectron from "is-electron"; import { useRouter } from "next/router"; import { CarouselProvider, DotGroup, Slide, Slider } from "pure-react-carousel"; import "pure-react-carousel/dist/react-carousel.es.css"; @@ -132,11 +130,12 @@ export default function LandingPage() { const handleNormalRedirect = async () => { const user = getData(LS_KEYS.USER); let key = getKey(SESSION_KEYS.ENCRYPTION_KEY); - if (!key && isElectron()) { + const electron = globalThis.electron; + if (!key && electron) { try { - key = await ElectronAPIs.getEncryptionKey(); + key = await electron.getEncryptionKey(); } catch (e) { - logError(e, "getEncryptionKey failed"); + log.error("getEncryptionKey failed", e); } if (key) { await saveKeyInSessionStore( @@ -160,7 +159,7 @@ export default function LandingPage() { try { await localForage.ready(); } catch (e) { - logError(e, "usage in incognito mode tried"); + log.error("usage in incognito mode tried", e); appContext.setDialogMessage({ title: t("LOCAL_STORAGE_NOT_ACCESSIBLE"), diff --git a/web/apps/photos/src/pages/shared-albums/index.tsx b/web/apps/photos/src/pages/shared-albums/index.tsx index 5056f77eb..756377672 100644 --- a/web/apps/photos/src/pages/shared-albums/index.tsx +++ b/web/apps/photos/src/pages/shared-albums/index.tsx @@ -1,3 +1,4 @@ +import log from "@/next/log"; import { CenteredFlex, SpaceBetweenFlex, @@ -46,7 +47,6 @@ import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages"; import { ENTE_WEBSITE_LINK } from "@ente/shared/constants/urls"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import useFileInput from "@ente/shared/hooks/useFileInput"; -import { logError } from "@ente/shared/sentry"; import AddPhotoAlternateOutlined from "@mui/icons-material/AddPhotoAlternateOutlined"; import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined"; import MoreHoriz from "@mui/icons-material/MoreHoriz"; @@ -292,7 +292,7 @@ export default function PublicCollectionGallery() { setFilesDownloadProgressAttributes, ); } catch (e) { - logError(e, "failed to downloads shared album all files"); + log.error("failed to downloads shared album all files", e); } }; @@ -417,7 +417,7 @@ export default function PublicCollectionGallery() { setPublicCollection(null); setPublicFiles(null); } else { - logError(e, "failed to sync public album with remote"); + log.error("failed to sync public album with remote", e); } } finally { appContext.finishLoading(); @@ -441,7 +441,7 @@ export default function PublicCollectionGallery() { publicUrl.memLimit, ); } catch (e) { - logError(e, "failed to derive key for verifyLinkPassword"); + log.error("failed to derive key for verifyLinkPassword", e); setFieldError(`${t("UNKNOWN_ERROR")} ${e.message}`); return; } @@ -468,7 +468,7 @@ export default function PublicCollectionGallery() { await syncWithRemote(); appContext.finishLoading(); } catch (e) { - logError(e, "failed to verifyLinkPassword"); + log.error("failed to verifyLinkPassword", e); setFieldError(`${t("UNKNOWN_ERROR")} ${e.message}`); } }; @@ -528,7 +528,7 @@ export default function PublicCollectionGallery() { ); clearSelection(); } catch (e) { - logError(e, "failed to download selected files"); + log.error("failed to download selected files", e); } }; diff --git a/web/apps/photos/src/services/billingService.ts b/web/apps/photos/src/services/billingService.ts index a9af851b2..090eca17c 100644 --- a/web/apps/photos/src/services/billingService.ts +++ b/web/apps/photos/src/services/billingService.ts @@ -1,6 +1,6 @@ +import log from "@/next/log"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint, getPaymentsURL } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import { LS_KEYS, removeData, @@ -40,7 +40,7 @@ class billingService { const { plans } = response.data; return plans; } catch (e) { - logError(e, "failed to get plans"); + log.error("failed to get plans", e); } } @@ -56,7 +56,7 @@ class billingService { const { subscription } = response.data; setData(LS_KEYS.SUBSCRIPTION, subscription); } catch (e) { - logError(e, "failed to get user's subscription details"); + log.error("failed to get user's subscription details", e); } } @@ -69,7 +69,7 @@ class billingService { PaymentActionType.Buy, ); } catch (e) { - logError(e, "unable to buy subscription"); + log.error("unable to buy subscription", e); throw e; } } @@ -83,7 +83,7 @@ class billingService { PaymentActionType.Update, ); } catch (e) { - logError(e, "subscription update failed"); + log.error("subscription update failed", e); throw e; } } @@ -101,7 +101,7 @@ class billingService { const { subscription } = response.data; setData(LS_KEYS.SUBSCRIPTION, subscription); } catch (e) { - logError(e, "subscription cancel failed"); + log.error("subscription cancel failed", e); throw e; } } @@ -119,7 +119,7 @@ class billingService { const { subscription } = response.data; setData(LS_KEYS.SUBSCRIPTION, subscription); } catch (e) { - logError(e, "failed to activate subscription"); + log.error("failed to activate subscription", e); throw e; } } @@ -147,9 +147,9 @@ class billingService { const { subscription } = response.data; setData(LS_KEYS.SUBSCRIPTION, subscription); return subscription; - } catch (err) { - logError(err, "Error while verifying subscription"); - throw err; + } catch (e) { + log.error("Error while verifying subscription", e); + throw e; } } @@ -163,7 +163,7 @@ class billingService { }); removeData(LS_KEYS.FAMILY_DATA); } catch (e) { - logError(e, "/family/leave failed"); + log.error("/family/leave failed", e); throw e; } } @@ -177,7 +177,7 @@ class billingService { const redirectURL = this.getRedirectURL(); window.location.href = `${getPaymentsURL()}?productID=${productID}&paymentToken=${paymentToken}&action=${action}&redirectURL=${redirectURL}`; } catch (e) { - logError(e, "unable to get payments url"); + log.error("unable to get payments url", e); throw e; } } @@ -194,7 +194,7 @@ class billingService { ); window.location.href = response.data.url; } catch (e) { - logError(e, "unable to get customer portal url"); + log.error("unable to get customer portal url", e); throw e; } } diff --git a/web/apps/photos/src/services/clipService.ts b/web/apps/photos/src/services/clipService.ts index 278c406d7..53e026d4f 100644 --- a/web/apps/photos/src/services/clipService.ts +++ b/web/apps/photos/src/services/clipService.ts @@ -1,9 +1,8 @@ -import ElectronAPIs from "@/next/electron"; +import { ensureElectron } from "@/next/electron"; +import log from "@/next/log"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import { CustomError } from "@ente/shared/error"; import { Events, eventBus } from "@ente/shared/events"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; import { FILE_TYPE } from "constants/file"; import isElectron from "is-electron"; @@ -63,36 +62,36 @@ class ClipServiceImpl { return; } if (this.onFileUploadedHandler) { - addLogLine("file upload listener already setup"); + log.info("file upload listener already setup"); return; } - addLogLine("setting up file upload listener"); + log.info("setting up file upload listener"); this.onFileUploadedHandler = (args) => { this.runLocalFileClipExtraction(args); }; eventBus.on(Events.FILE_UPLOADED, this.onFileUploadedHandler, this); - addLogLine("setup file upload listener successfully"); + log.info("setup file upload listener successfully"); } catch (e) { - logError(e, "failed to setup clip service"); + log.error("failed to setup clip service", e); } }; removeOnFileUploadListener = async () => { try { if (!this.onFileUploadedHandler) { - addLogLine("file upload listener already removed"); + log.info("file upload listener already removed"); return; } - addLogLine("removing file upload listener"); + log.info("removing file upload listener"); eventBus.removeListener( Events.FILE_UPLOADED, this.onFileUploadedHandler, this, ); this.onFileUploadedHandler = null; - addLogLine("removed file upload listener successfully"); + log.info("removed file upload listener successfully"); } catch (e) { - logError(e, "failed to remove clip service"); + log.error("failed to remove clip service", e); } }; @@ -107,7 +106,7 @@ class ClipServiceImpl { } return this.clipExtractionStatus; } catch (e) { - logError(e, "failed to get clip indexing status"); + log.error("failed to get clip indexing status", e); } }; @@ -121,13 +120,13 @@ class ClipServiceImpl { ) => { try { if (this.embeddingExtractionInProgress) { - addLogLine( + log.info( "clip embedding extraction already in progress, scheduling re-run", ); this.reRunNeeded = true; return; } else { - addLogLine( + log.info( "clip embedding extraction not in progress, starting clip embedding extraction", ); } @@ -139,7 +138,7 @@ class ClipServiceImpl { this.embeddingExtractionInProgress = null; if (!canceller.signal.aborted && this.reRunNeeded) { this.reRunNeeded = false; - addLogLine("re-running clip embedding extraction"); + log.info("re-running clip embedding extraction"); setTimeout( () => this.scheduleImageEmbeddingExtraction(), 0, @@ -148,7 +147,7 @@ class ClipServiceImpl { } } catch (e) { if (e.message !== CustomError.REQUEST_CANCELLED) { - logError(e, "failed to schedule clip embedding extraction"); + log.error("failed to schedule clip embedding extraction", e); } } }; @@ -158,12 +157,12 @@ class ClipServiceImpl { model: Model = Model.ONNX_CLIP, ): Promise => { try { - return ElectronAPIs.computeTextEmbedding(model, text); + return ensureElectron().computeTextEmbedding(model, text); } catch (e) { if (e?.message?.includes(CustomError.UNSUPPORTED_PLATFORM)) { this.unsupportedPlatform = true; } - logError(e, "failed to compute text embedding"); + log.error("failed to compute text embedding", e); throw e; } }; @@ -174,7 +173,7 @@ class ClipServiceImpl { ) => { try { if (this.unsupportedPlatform) { - addLogLine( + log.info( `skipping clip embedding extraction, platform unsupported`, ); return; @@ -194,15 +193,15 @@ class ClipServiceImpl { pending: pendingFiles.length, }); if (pendingFiles.length === 0) { - addLogLine("no clip embedding extraction needed, all done"); + log.info("no clip embedding extraction needed, all done"); return; } - addLogLine( + log.info( `starting clip embedding extraction for ${pendingFiles.length} files`, ); for (const file of pendingFiles) { try { - addLogLine( + log.info( `extracting clip embedding for file: ${file.metadata.title} fileID: ${file.id}`, ); if (canceller.signal.aborted) { @@ -210,7 +209,7 @@ class ClipServiceImpl { } const embeddingData = await this.extractFileClipImageEmbedding(model, file); - addLogLine( + log.info( `successfully extracted clip embedding for file: ${file.metadata.title} fileID: ${file.id} embedding length: ${embeddingData?.length}`, ); await this.encryptAndUploadEmbedding( @@ -219,14 +218,14 @@ class ClipServiceImpl { embeddingData, ); this.onSuccessStatusUpdater(); - addLogLine( + log.info( `successfully put clip embedding to server for file: ${file.metadata.title} fileID: ${file.id}`, ); } catch (e) { if (e?.message !== CustomError.REQUEST_CANCELLED) { - logError( - e, + log.error( "failed to extract clip embedding for file", + e, ); } if ( @@ -244,7 +243,7 @@ class ClipServiceImpl { } } catch (e) { if (e.message !== CustomError.REQUEST_CANCELLED) { - logError(e, "failed to extract clip embedding"); + log.error("failed to extract clip embedding", e); } throw e; } @@ -258,24 +257,24 @@ class ClipServiceImpl { model: Model = Model.ONNX_CLIP, ) { const { enteFile, localFile } = arg; - addLogLine( + log.info( `clip embedding extraction onFileUploadedHandler file: ${enteFile.metadata.title} fileID: ${enteFile.id}`, enteFile.id, ); if (enteFile.metadata.fileType === FILE_TYPE.VIDEO) { - addLogLine( + log.info( `skipping video file for clip embedding extraction file: ${enteFile.metadata.title} fileID: ${enteFile.id}`, ); return; } const extension = enteFile.metadata.title.split(".").pop(); if (!extension || !["jpg", "jpeg"].includes(extension)) { - addLogLine( + log.info( `skipping non jpg file for clip embedding extraction file: ${enteFile.metadata.title} fileID: ${enteFile.id}`, ); return; } - addLogLine( + log.info( `queuing up for local clip embedding extraction for file: ${enteFile.metadata.title} fileID: ${enteFile.id}`, ); try { @@ -290,11 +289,11 @@ class ClipServiceImpl { embedding, ); }); - addLogLine( + log.info( `successfully extracted clip embedding for file: ${enteFile.metadata.title} fileID: ${enteFile.id}`, ); } catch (e) { - logError(e, "Failed in ML onFileUploadedHandler"); + log.error("Failed in ML onFileUploadedHandler", e); } } @@ -305,7 +304,10 @@ class ClipServiceImpl { const file = await localFile .arrayBuffer() .then((buffer) => new Uint8Array(buffer)); - const embedding = await ElectronAPIs.computeImageEmbedding(model, file); + const embedding = await ensureElectron().computeImageEmbedding( + model, + file, + ); return embedding; }; @@ -322,7 +324,7 @@ class ClipServiceImpl { const comlinkCryptoWorker = await ComlinkCryptoWorker.getInstance(); const { file: encryptedEmbeddingData } = await comlinkCryptoWorker.encryptEmbedding(embeddingData, file.key); - addLogLine( + log.info( `putting clip embedding to server for file: ${file.metadata.title} fileID: ${file.id}`, ); await putEmbedding({ @@ -345,7 +347,7 @@ class ClipServiceImpl { file: EnteFile, ) => { const thumb = await downloadManager.getThumbnail(file); - const embedding = await ElectronAPIs.computeImageEmbedding( + const embedding = await ensureElectron().computeImageEmbedding( model, thumb, ); diff --git a/web/apps/photos/src/services/collectionService.ts b/web/apps/photos/src/services/collectionService.ts index 7a9a251ef..0812ca8f9 100644 --- a/web/apps/photos/src/services/collectionService.ts +++ b/web/apps/photos/src/services/collectionService.ts @@ -2,10 +2,10 @@ import { getEndpoint } from "@ente/shared/network/api"; import localForage from "@ente/shared/storage/localForage"; import { getData, LS_KEYS } from "@ente/shared/storage/localStorage"; +import log from "@/next/log"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import { CustomError } from "@ente/shared/error"; import HTTPService from "@ente/shared/network/HTTPService"; -import { logError } from "@ente/shared/sentry"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { getActualKey } from "@ente/shared/user"; import { User } from "@ente/shared/user/types"; @@ -198,9 +198,10 @@ const getCollections = async ( try { return await getCollectionWithSecrets(collection, key); } catch (e) { - logError(e, `decryption failed for collection`, { - collectionID: collection.id, - }); + log.error( + `decryption failed for collection with ID ${collection.id}`, + e, + ); return collection; } }, @@ -212,7 +213,7 @@ const getCollections = async ( ); return collections; } catch (e) { - logError(e, "getCollections failed"); + log.error("getCollections failed", e); throw e; } }; @@ -340,7 +341,7 @@ export const getCollection = async ( ); return collectionWithSecrets; } catch (e) { - logError(e, "failed to get collection"); + log.error("failed to get collection", e); throw e; } }; @@ -462,7 +463,7 @@ const createCollection = async ( ); return decryptedCreatedCollection; } catch (e) { - logError(e, "create collection failed"); + log.error("create collection failed", e); throw e; } }; @@ -480,7 +481,7 @@ const postCollection = async ( ); return response.data.collection; } catch (e) { - logError(e, "post Collection failed "); + log.error("post Collection failed ", e); } }; @@ -496,7 +497,7 @@ export const addToFavorites = async (file: EnteFile) => { } await addToCollection(favCollection, [file]); } catch (e) { - logError(e, "failed to add to favorite"); + log.error("failed to add to favorite", e); } }; @@ -508,7 +509,7 @@ export const removeFromFavorites = async (file: EnteFile) => { } await removeFromCollection(favCollection.id, [file]); } catch (e) { - logError(e, "remove from favorite failed"); + log.error("remove from favorite failed", e); } }; @@ -537,7 +538,7 @@ export const addToCollection = async ( ); } } catch (e) { - logError(e, "Add to collection Failed "); + log.error("Add to collection Failed ", e); throw e; } }; @@ -567,7 +568,7 @@ export const restoreToCollection = async ( ); } } catch (e) { - logError(e, "restore to collection Failed "); + log.error("restore to collection Failed ", e); throw e; } }; @@ -598,7 +599,7 @@ export const moveToCollection = async ( ); } } catch (e) { - logError(e, "move to collection Failed "); + log.error("move to collection Failed ", e); throw e; } }; @@ -649,7 +650,7 @@ export const removeFromCollection = async ( await removeUserFiles(collectionID, userFiles, allFiles); } } catch (e) { - logError(e, "remove from collection failed "); + log.error("remove from collection failed ", e); throw e; } }; @@ -715,7 +716,7 @@ export const removeUserFiles = async ( leftFiles, ); } catch (e) { - logError(e, "remove user files failed "); + log.error("remove user files failed ", e); throw e; } }; @@ -742,7 +743,7 @@ export const removeNonUserFiles = async ( ); } } catch (e) { - logError(e, "remove non user files failed "); + log.error("remove non user files failed ", e); throw e; } }; @@ -768,7 +769,7 @@ export const deleteCollection = async ( { "X-Auth-Token": token }, ); } catch (e) { - logError(e, "delete collection failed "); + log.error("delete collection failed ", e); throw e; } }; @@ -784,7 +785,7 @@ export const leaveSharedAlbum = async (collectionID: number) => { { "X-Auth-Token": token }, ); } catch (e) { - logError(e, "leave shared album failed "); + log.error("leave shared album failed ", e); throw e; } }; @@ -976,7 +977,7 @@ export const shareCollection = async ( }, ); } catch (e) { - logError(e, "share collection failed "); + log.error("share collection failed ", e); throw e; } }; @@ -1000,7 +1001,7 @@ export const unshareCollection = async ( }, ); } catch (e) { - logError(e, "unshare collection failed "); + log.error("unshare collection failed ", e); } }; @@ -1023,7 +1024,7 @@ export const createShareableURL = async (collection: Collection) => { ); return resp.data.result as PublicURL; } catch (e) { - logError(e, "createShareableURL failed "); + log.error("createShareableURL failed ", e); throw e; } }; @@ -1043,7 +1044,7 @@ export const deleteShareableURL = async (collection: Collection) => { }, ); } catch (e) { - logError(e, "deleteShareableURL failed "); + log.error("deleteShareableURL failed ", e); throw e; } }; @@ -1066,7 +1067,7 @@ export const updateShareableURL = async ( ); return res.data.result as PublicURL; } catch (e) { - logError(e, "updateShareableURL failed "); + log.error("updateShareableURL failed ", e); throw e; } }; @@ -1392,7 +1393,7 @@ export async function moveToHiddenCollection(files: EnteFile[]) { await moveToCollection(collectionID, hiddenCollection, files); } } catch (e) { - logError(e, "move to hidden collection failed "); + log.error("move to hidden collection failed ", e); throw e; } } @@ -1411,7 +1412,7 @@ export async function unhideToCollection( await moveToCollection(collectionID, collection, files); } } catch (e) { - logError(e, "unhide to collection failed "); + log.error("unhide to collection failed ", e); throw e; } } @@ -1436,7 +1437,7 @@ export const constructUserIDToEmailMap = ( }); return userIDToEmailMap; } catch (e) { - logError("Error Mapping UserId to email:", e); + log.error("Error Mapping UserId to email:", e); return new Map(); } }; diff --git a/web/apps/photos/src/services/deduplicationService.ts b/web/apps/photos/src/services/deduplicationService.ts index e261f8e77..9d8ab399f 100644 --- a/web/apps/photos/src/services/deduplicationService.ts +++ b/web/apps/photos/src/services/deduplicationService.ts @@ -1,6 +1,6 @@ +import log from "@/next/log"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { FILE_TYPE } from "constants/file"; import { EnteFile } from "types/file"; @@ -64,7 +64,7 @@ export async function getDuplicates( return result; } catch (e) { - logError(e, "failed to get duplicate files"); + log.error("failed to get duplicate files", e); } } @@ -156,7 +156,7 @@ async function fetchDuplicateFileIDs() { ); return (response.data as DuplicatesResponse).duplicates; } catch (e) { - logError(e, "failed to fetch duplicate file IDs"); + log.error("failed to fetch duplicate file IDs", e); } } diff --git a/web/apps/photos/src/services/download/index.ts b/web/apps/photos/src/services/download/index.ts index d89de7851..d262c74aa 100644 --- a/web/apps/photos/src/services/download/index.ts +++ b/web/apps/photos/src/services/download/index.ts @@ -1,22 +1,20 @@ -import { EnteFile } from "types/file"; -import { - generateStreamFromArrayBuffer, - getRenderableFileURL, -} from "utils/file"; - +import log from "@/next/log"; import { APPS } from "@ente/shared/apps/constants"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker"; import { CustomError } from "@ente/shared/error"; import { Events, eventBus } from "@ente/shared/events"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; import { CacheStorageService } from "@ente/shared/storage/cacheStorage"; import { CACHES } from "@ente/shared/storage/cacheStorage/constants"; import { LimitedCache } from "@ente/shared/storage/cacheStorage/types"; import { Remote } from "comlink"; import { FILE_TYPE } from "constants/file"; import isElectron from "is-electron"; +import { EnteFile } from "types/file"; +import { + generateStreamFromArrayBuffer, + getRenderableFileURL, +} from "utils/file"; import { isInternalUser } from "utils/user"; import { PhotosDownloadClient } from "./clients/photos"; import { PublicAlbumsDownloadClient } from "./clients/publicAlbums"; @@ -80,7 +78,7 @@ class DownloadManagerImpl { ) { try { if (this.ready) { - addLogLine("DownloadManager already initialized"); + log.info("DownloadManager already initialized"); return; } this.downloadClient = createDownloadClient(app, tokens, timeout); @@ -90,14 +88,14 @@ class DownloadManagerImpl { this.ready = true; eventBus.on(Events.LOGOUT, this.logoutHandler.bind(this), this); } catch (e) { - logError(e, "DownloadManager init failed"); + log.error("DownloadManager init failed", e); throw e; } } private async logoutHandler() { try { - addLogLine("downloadManger logoutHandler started"); + log.info("downloadManger logoutHandler started"); this.ready = false; this.cryptoWorker = null; this.downloadClient = null; @@ -106,9 +104,9 @@ class DownloadManagerImpl { this.thumbnailObjectURLPromises.clear(); this.fileDownloadProgress.clear(); this.progressUpdater = () => {}; - addLogLine("downloadManager logoutHandler completed"); + log.info("downloadManager logoutHandler completed"); } catch (e) { - logError(e, "downloadManager logoutHandler failed"); + log.error("downloadManager logoutHandler failed", e); } } @@ -138,7 +136,7 @@ class DownloadManagerImpl { return new Uint8Array(await cacheResp.arrayBuffer()); } } catch (e) { - logError(e, "failed to get cached thumbnail"); + log.error("failed to get cached thumbnail", e); throw e; } } @@ -153,7 +151,7 @@ class DownloadManagerImpl { ); return cacheResp?.clone(); } catch (e) { - logError(e, "failed to get cached file"); + log.error("failed to get cached file", e); throw e; } } @@ -185,12 +183,12 @@ class DownloadManagerImpl { this.thumbnailCache ?.put(file.id.toString(), new Response(thumb)) .catch((e) => { - logError(e, "thumb cache put failed"); + log.error("thumb cache put failed", e); // TODO: handle storage full exception. }); return thumb; } catch (e) { - logError(e, "getThumbnail failed"); + log.error("getThumbnail failed", e); throw e; } } @@ -215,7 +213,7 @@ class DownloadManagerImpl { return thumb; } catch (e) { this.thumbnailObjectURLPromises.delete(file.id); - logError(e, "get DownloadManager preview Failed"); + log.error("get DownloadManager preview Failed", e); throw e; } } @@ -253,7 +251,7 @@ class DownloadManagerImpl { return fileURLs; } catch (e) { this.fileConversionPromises.delete(file.id); - logError(e, "download manager getFileForPreview Failed"); + log.error("download manager getFileForPreview Failed", e); throw e; } }; @@ -291,7 +289,7 @@ class DownloadManagerImpl { } } catch (e) { this.fileObjectURLPromises.delete(file.id); - logError(e, "download manager getFile Failed"); + log.error("download manager getFile Failed", e); throw e; } } @@ -300,7 +298,7 @@ class DownloadManagerImpl { file: EnteFile, ): Promise> { try { - addLogLine(`download attempted for fileID:${file.id}`); + log.info(`download attempted for fileID:${file.id}`); const onDownloadProgress = this.trackDownloadProgress( file.id, file.info?.fileSize, @@ -321,7 +319,7 @@ class DownloadManagerImpl { this.diskFileCache .put(file.id.toString(), encrypted.clone()) .catch((e) => { - logError(e, "file cache put failed"); + log.error("file cache put failed", e); // TODO: handle storage full exception. }); } @@ -338,15 +336,9 @@ class DownloadManagerImpl { return generateStreamFromArrayBuffer(decrypted); } catch (e) { if (e.message === CustomError.PROCESSING_FAILED) { - logError(e, "Failed to process file", { - fileID: file.id, - fromMobile: - !!file.metadata.localID || - !!file.metadata.deviceFolder || - !!file.metadata.version, - }); - addLogLine( - `Failed to process file with fileID:${file.id}, localID: ${file.metadata.localID}, version: ${file.metadata.version}, deviceFolder:${file.metadata.deviceFolder} with error: ${e.message}`, + log.error( + `Failed to process file with fileID:${file.id}, localID: ${file.metadata.localID}, version: ${file.metadata.version}, deviceFolder:${file.metadata.deviceFolder}`, + e, ); } throw e; @@ -360,7 +352,7 @@ class DownloadManagerImpl { this.diskFileCache .put(file.id.toString(), resp.clone()) .catch((e) => { - logError(e, "file cache put failed"); + log.error("file cache put failed", e); }); } } @@ -430,22 +422,9 @@ class DownloadManagerImpl { e.message === CustomError.PROCESSING_FAILED ) { - logError( + log.error( + `Failed to process file ${file.id} from localID: ${file.metadata.localID} version: ${file.metadata.version} deviceFolder:${file.metadata.deviceFolder}`, e, - "Failed to process file", - { - fileID: file.id, - fromMobile: - !!file.metadata - .localID || - !!file.metadata - .deviceFolder || - !!file.metadata - .version, - }, - ); - addLogLine( - `Failed to process file ${file.id} from localID: ${file.metadata.localID} version: ${file.metadata.version} deviceFolder:${file.metadata.deviceFolder} with error: ${e.message}`, ); } throw e; @@ -471,22 +450,9 @@ class DownloadManagerImpl { e.message === CustomError.PROCESSING_FAILED ) { - logError( + log.error( + `Failed to process file ${file.id} from localID: ${file.metadata.localID} version: ${file.metadata.version} deviceFolder:${file.metadata.deviceFolder}`, e, - "Failed to process file", - { - fileID: file.id, - fromMobile: - !!file.metadata - .localID || - !!file.metadata - .deviceFolder || - !!file.metadata - .version, - }, - ); - addLogLine( - `Failed to process file ${file.id} from localID: ${file.metadata.localID} version: ${file.metadata.version} deviceFolder:${file.metadata.deviceFolder} with error: ${e.message}`, ); } throw e; @@ -495,7 +461,10 @@ class DownloadManagerImpl { controller.close(); } } catch (e) { - logError(e, "Failed to process file chunk"); + log.error( + "Failed to process file chunk", + e, + ); controller.error(e); } }); @@ -503,14 +472,14 @@ class DownloadManagerImpl { push(); } catch (e) { - logError(e, "Failed to process file stream"); + log.error("Failed to process file stream", e); controller.error(e); } }, }); return stream; } catch (e) { - logError(e, "Failed to download file"); + log.error("Failed to download file", e); throw e; } } @@ -549,7 +518,7 @@ async function openThumbnailCache() { try { return await CacheStorageService.open(CACHES.THUMBS); } catch (e) { - logError(e, "Failed to open thumbnail cache"); + log.error("Failed to open thumbnail cache", e); if (isInternalUser()) { throw e; } else { @@ -565,7 +534,7 @@ async function openDiskFileCache() { } return await CacheStorageService.open(CACHES.FILES); } catch (e) { - logError(e, "Failed to open file cache"); + log.error("Failed to open file cache", e); if (isInternalUser()) { throw e; } else { diff --git a/web/apps/photos/src/services/embeddingService.ts b/web/apps/photos/src/services/embeddingService.ts index 68d065aec..882cdd16c 100644 --- a/web/apps/photos/src/services/embeddingService.ts +++ b/web/apps/photos/src/services/embeddingService.ts @@ -1,9 +1,8 @@ +import log from "@/next/log"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import { CustomError } from "@ente/shared/error"; -import { addLogLine } from "@ente/shared/logging"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import localForage from "@ente/shared/storage/localForage"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { @@ -68,10 +67,10 @@ export const syncEmbeddings = async (models: Model[] = [Model.ONNX_CLIP]) => { fileIdToKeyMap.set(file.id, file.key); }); await cleanupDeletedEmbeddings(allLocalFiles, allEmbeddings); - addLogLine(`Syncing embeddings localCount: ${allEmbeddings.length}`); + log.info(`Syncing embeddings localCount: ${allEmbeddings.length}`); for (const model of models) { let modelLastSinceTime = await getModelEmbeddingSyncTime(model); - addLogLine( + log.info( `Syncing ${model} model's embeddings sinceTime: ${modelLastSinceTime}`, ); let response: GetEmbeddingDiffResponse; @@ -107,18 +106,13 @@ export const syncEmbeddings = async (models: Model[] = [Model.ONNX_CLIP]) => { embedding: decryptedData, } as Embedding; } catch (e) { - let info: Record; + let hasHiddenAlbums = false; if (e.message === CustomError.FILE_NOT_FOUND) { - const hasHiddenAlbums = - hiddenAlbums?.length > 0; - info = { - hasHiddenAlbums, - }; + hasHiddenAlbums = hiddenAlbums?.length > 0; } - logError( + log.error( + `decryptEmbedding failed for file (hasHiddenAlbums: ${hasHiddenAlbums})`, e, - "decryptEmbedding failed for file", - info, ); } }), @@ -132,13 +126,13 @@ export const syncEmbeddings = async (models: Model[] = [Model.ONNX_CLIP]) => { } await localForage.setItem(EMBEDDINGS_TABLE, allEmbeddings); await setModelEmbeddingSyncTime(model, modelLastSinceTime); - addLogLine( + log.info( `Syncing embeddings syncedEmbeddingsCount: ${allEmbeddings.length}`, ); } while (response.diff.length === DIFF_LIMIT); } } catch (e) { - logError(e, "Sync embeddings failed"); + log.error("Sync embeddings failed", e); } }; @@ -164,7 +158,7 @@ export const getEmbeddingsDiff = async ( ); return await response.data; } catch (e) { - logError(e, "get embeddings diff failed"); + log.error("get embeddings diff failed", e); throw e; } }; @@ -187,7 +181,7 @@ export const putEmbedding = async ( ); return resp.data; } catch (e) { - logError(e, "put embedding failed"); + log.error("put embedding failed", e); throw e; } }; @@ -205,7 +199,7 @@ export const cleanupDeletedEmbeddings = async ( activeFileIds.has(embedding.fileID), ); if (allLocalEmbeddings.length !== remainingEmbeddings.length) { - addLogLine( + log.info( `cleanupDeletedEmbeddings embeddingsCount: ${allLocalEmbeddings.length} remainingEmbeddingsCount: ${remainingEmbeddings.length}`, ); await localForage.setItem(EMBEDDINGS_TABLE, remainingEmbeddings); diff --git a/web/apps/photos/src/services/entityService.ts b/web/apps/photos/src/services/entityService.ts index 64ead657e..31607110e 100644 --- a/web/apps/photos/src/services/entityService.ts +++ b/web/apps/photos/src/services/entityService.ts @@ -1,8 +1,7 @@ +import log from "@/next/log"; import ComlinkCryptoWorker from "@ente/shared/crypto"; -import { addLogLine } from "@ente/shared/logging"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import localForage from "@ente/shared/storage/localForage"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { getActualKey } from "@ente/shared/user"; @@ -82,7 +81,7 @@ const getEntityKey = async (type: EntityType) => { localForage.setItem(ENTITY_KEY_TABLES[type], decryptedEntityKey); return decryptedEntityKey; } catch (e) { - logError(e, "Get entity key failed"); + log.error("Get entity key failed", e); throw e; } }; @@ -92,7 +91,7 @@ export const getLatestEntities = async (type: EntityType) => { await syncEntity(type); return await getLocalEntity(type); } catch (e) { - logError(e, "Sync entities failed"); + log.error("Sync entities failed", e); throw e; } }; @@ -101,7 +100,7 @@ export const syncEntities = async () => { try { await syncEntity(EntityType.LOCATION_TAG); } catch (e) { - logError(e, "Sync entities failed"); + log.error("Sync entities failed", e); throw e; } }; @@ -109,11 +108,11 @@ export const syncEntities = async () => { const syncEntity = async (type: EntityType): Promise> => { try { let entities = await getLocalEntity(type); - addLogLine( + log.info( `Syncing ${type} entities localEntitiesCount: ${entities.length}`, ); let syncTime = await getEntityLastSyncTime(type); - addLogLine(`Syncing ${type} entities syncTime: ${syncTime}`); + log.info(`Syncing ${type} entities syncTime: ${syncTime}`); let response: EntitySyncDiffResponse; do { response = await getEntityDiff(type, syncTime); @@ -157,12 +156,12 @@ const syncEntity = async (type: EntityType): Promise> => { } await localForage.setItem(ENTITY_TABLES[type], nonDeletedEntities); await localForage.setItem(ENTITY_SYNC_TIME_TABLES[type], syncTime); - addLogLine( + log.info( `Syncing ${type} entities syncedEntitiesCount: ${nonDeletedEntities.length}`, ); } while (response.diff.length === DIFF_LIMIT); } catch (e) { - logError(e, "Sync entity failed"); + log.error("Sync entity failed", e); } }; @@ -189,7 +188,7 @@ const getEntityDiff = async ( return resp.data; } catch (e) { - logError(e, "Get entity diff failed"); + log.error("Get entity diff failed", e); throw e; } }; diff --git a/web/apps/photos/src/services/export/index.ts b/web/apps/photos/src/services/export/index.ts index c1fa2cbe1..f2e90139a 100644 --- a/web/apps/photos/src/services/export/index.ts +++ b/web/apps/photos/src/services/export/index.ts @@ -1,7 +1,29 @@ -import { logError } from "@ente/shared/sentry"; +import { ensureElectron } from "@/next/electron"; +import log from "@/next/log"; +import { CustomError } from "@ente/shared/error"; +import { Events, eventBus } from "@ente/shared/events"; import { LS_KEYS, getData, setData } from "@ente/shared/storage/localStorage"; +import { User } from "@ente/shared/user/types"; import { sleep } from "@ente/shared/utils"; +import QueueProcessor, { + CancellationStatus, + RequestCanceller, +} from "@ente/shared/utils/queueProcessor"; +import { ExportStage } from "constants/export"; +import { FILE_TYPE } from "constants/file"; +import { Collection } from "types/collection"; +import { + ExportProgress, + ExportRecord, + ExportSettings, + ExportUIUpdaters, +} from "types/export"; import { EnteFile } from "types/file"; +import { + constructCollectionNameMap, + getCollectionUserFacingName, + getNonEmptyPersonalCollections, +} from "utils/collection"; import { convertCollectionIDExportNameObjectToMap, convertFileIDExportNameObjectToMap, @@ -25,41 +47,16 @@ import { isLivePhotoExportName, parseLivePhotoExportName, } from "utils/export"; -import { getAllLocalCollections } from "../collectionService"; -import downloadManager from "../download"; -import { getAllLocalFiles } from "../fileService"; - import { generateStreamFromArrayBuffer, getPersonalFiles, getUpdatedEXIFFileForDownload, mergeMetadata, } from "utils/file"; +import { getAllLocalCollections } from "../collectionService"; +import downloadManager from "../download"; +import { getAllLocalFiles } from "../fileService"; import { decodeLivePhoto } from "../livePhotoService"; - -import ElectronAPIs from "@/next/electron"; -import { CustomError } from "@ente/shared/error"; -import { Events, eventBus } from "@ente/shared/events"; -import { addLogLine } from "@ente/shared/logging"; -import { User } from "@ente/shared/user/types"; -import QueueProcessor, { - CancellationStatus, - RequestCanceller, -} from "@ente/shared/utils/queueProcessor"; -import { ExportStage } from "constants/export"; -import { FILE_TYPE } from "constants/file"; -import { Collection } from "types/collection"; -import { - ExportProgress, - ExportRecord, - ExportSettings, - ExportUIUpdaters, -} from "types/export"; -import { - constructCollectionNameMap, - getCollectionUserFacingName, - getNonEmptyPersonalCollections, -} from "utils/collection"; import { migrateExport } from "./migration"; const EXPORT_RECORD_FILE_NAME = "export_status.json"; @@ -102,7 +99,7 @@ class ExportService { this.exportSettings = exportSettings; return exportSettings; } catch (e) { - logError(e, "getExportSettings failed"); + log.error("getExportSettings failed", e); throw e; } } @@ -114,7 +111,7 @@ class ExportService { this.exportSettings = newSettings; setData(LS_KEYS.EXPORT, newSettings); } catch (e) { - logError(e, "updateExportSettings failed"); + log.error("updateExportSettings failed", e); throw e; } } @@ -125,11 +122,11 @@ class ExportService { updateProgress: (progress: ExportProgress) => void, ) { try { - addLogLine("running migration"); + log.info("running migration"); await migrateExport(exportDir, exportRecord, updateProgress); - addLogLine("migration completed"); + log.info("migration completed"); } catch (e) { - logError(e, "migration failed"); + log.error("migration failed", e); throw e; } } @@ -160,16 +157,16 @@ class ExportService { async changeExportDirectory() { try { - const newRootDir = await ElectronAPIs.selectDirectory(); + const newRootDir = await ensureElectron().selectDirectory(); if (!newRootDir) { throw Error(CustomError.SELECT_FOLDER_ABORTED); } const newExportDir = `${newRootDir}/${ENTE_EXPORT_DIRECTORY}`; - await ElectronAPIs.checkExistsAndCreateDir(newExportDir); + await ensureElectron().checkExistsAndCreateDir(newExportDir); return newExportDir; } catch (e) { if (e.message !== CustomError.SELECT_FOLDER_ABORTED) { - logError(e, "changeExportDirectory failed"); + log.error("changeExportDirectory failed", e); } throw e; } @@ -178,10 +175,10 @@ class ExportService { enableContinuousExport() { try { if (this.continuousExportEventHandler) { - addLogLine("continuous export already enabled"); + log.info("continuous export already enabled"); return; } - addLogLine("enabling continuous export"); + log.info("enabling continuous export"); this.continuousExportEventHandler = () => { this.scheduleExport(); }; @@ -191,7 +188,7 @@ class ExportService { this.continuousExportEventHandler, ); } catch (e) { - logError(e, "failed to enableContinuousExport "); + log.error("failed to enableContinuousExport ", e); throw e; } } @@ -199,17 +196,17 @@ class ExportService { disableContinuousExport() { try { if (!this.continuousExportEventHandler) { - addLogLine("continuous export already disabled"); + log.info("continuous export already disabled"); return; } - addLogLine("disabling continuous export"); + log.info("disabling continuous export"); eventBus.removeListener( Events.LOCAL_FILES_UPDATED, this.continuousExportEventHandler, ); this.continuousExportEventHandler = null; } catch (e) { - logError(e, "failed to disableContinuousExport"); + log.error("failed to disableContinuousExport", e); throw e; } } @@ -239,7 +236,7 @@ class ExportService { ); return unExportedFiles; } catch (e) { - logError(e, "getUpdateFileLists failed"); + log.error("getUpdateFileLists failed", e); throw e; } }; @@ -271,30 +268,30 @@ class ExportService { const pendingExports = await this.getPendingExports(exportRecord); this.uiUpdater.setPendingExports(pendingExports); } catch (e) { - logError(e, "postExport failed"); + log.error("postExport failed", e); } } async stopRunningExport() { try { - addLogLine("user requested export cancellation"); + log.info("user requested export cancellation"); this.exportInProgress.exec(); this.exportInProgress = null; this.reRunNeeded = false; await this.postExport(); } catch (e) { - logError(e, "stopRunningExport failed"); + log.error("stopRunningExport failed", e); } } scheduleExport = async () => { try { if (this.exportInProgress) { - addLogLine("export in progress, scheduling re-run"); + log.info("export in progress, scheduling re-run"); this.reRunNeeded = true; return; } else { - addLogLine("export not in progress, starting export"); + log.info("export not in progress, starting export"); } const isCanceled: CancellationStatus = { status: false }; @@ -307,22 +304,22 @@ class ExportService { try { const exportFolder = this.getExportSettings()?.folder; await this.preExport(exportFolder); - addLogLine("export started"); + log.info("export started"); await this.runExport(exportFolder, isCanceled); - addLogLine("export completed"); + log.info("export completed"); } finally { if (isCanceled.status) { - addLogLine("export cancellation done"); + log.info("export cancellation done"); if (!this.exportInProgress) { await this.postExport(); } } else { await this.postExport(); - addLogLine("resetting export in progress after completion"); + log.info("resetting export in progress after completion"); this.exportInProgress = null; if (this.reRunNeeded) { this.reRunNeeded = false; - addLogLine("re-running export"); + log.info("re-running export"); setTimeout(() => this.scheduleExport(), 0); } } @@ -332,7 +329,7 @@ class ExportService { e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST && e.message !== CustomError.EXPORT_STOPPED ) { - logError(e, "scheduleExport failed"); + log.error("scheduleExport failed", e); } } }; @@ -390,7 +387,7 @@ class ExportService { exportRecord, ); - addLogLine( + log.info( `personal files:${personalFiles.length} unexported files: ${filesToExport.length}, deleted exported files: ${removedFileUIDs.length}, renamed collections: ${renamedCollections.length}, deleted collections: ${deletedExportedCollections.length}`, ); let success = 0; @@ -416,7 +413,7 @@ class ExportService { }; if (renamedCollections?.length > 0) { this.updateExportStage(ExportStage.RENAMING_COLLECTION_FOLDERS); - addLogLine(`renaming ${renamedCollections.length} collections`); + log.info(`renaming ${renamedCollections.length} collections`); await this.collectionRenamer( exportFolder, collectionIDExportNameMap, @@ -427,7 +424,7 @@ class ExportService { if (removedFileUIDs?.length > 0) { this.updateExportStage(ExportStage.TRASHING_DELETED_FILES); - addLogLine(`trashing ${removedFileUIDs.length} files`); + log.info(`trashing ${removedFileUIDs.length} files`); await this.fileTrasher( exportFolder, collectionIDExportNameMap, @@ -437,7 +434,7 @@ class ExportService { } if (filesToExport?.length > 0) { this.updateExportStage(ExportStage.EXPORTING_FILES); - addLogLine(`exporting ${filesToExport.length} files`); + log.info(`exporting ${filesToExport.length} files`); await this.fileExporter( filesToExport, collectionIDNameMap, @@ -452,7 +449,7 @@ class ExportService { this.updateExportStage( ExportStage.TRASHING_DELETED_COLLECTIONS, ); - addLogLine( + log.info( `removing ${deletedExportedCollections.length} collections`, ); await this.collectionRemover( @@ -466,7 +463,7 @@ class ExportService { e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST && e.message !== CustomError.EXPORT_STOPPED ) { - logError(e, "runExport failed"); + log.error("runExport failed", e); } throw e; } @@ -497,7 +494,7 @@ class ExportService { exportFolder, getCollectionUserFacingName(collection), ); - addLogLine( + log.info( `renaming collection with id ${collection.id} from ${oldCollectionExportName} to ${newCollectionExportName}`, ); const newCollectionExportPath = getCollectionExportPath( @@ -515,7 +512,7 @@ class ExportService { newCollectionExportName, ); try { - await ElectronAPIs.rename( + await ensureElectron().rename( oldCollectionExportPath, newCollectionExportPath, ); @@ -531,11 +528,11 @@ class ExportService { ); throw e; } - addLogLine( + log.info( `renaming collection with id ${collection.id} from ${oldCollectionExportName} to ${newCollectionExportName} successful`, ); } catch (e) { - logError(e, "collectionRenamer failed a collection"); + log.error("collectionRenamer failed a collection", e); if ( e.message === CustomError.UPDATE_EXPORTED_RECORD_FAILED || @@ -552,7 +549,7 @@ class ExportService { e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST && e.message !== CustomError.EXPORT_STOPPED ) { - logError(e, "collectionRenamer failed"); + log.error("collectionRenamer failed", e); } throw e; } @@ -575,7 +572,7 @@ class ExportService { throw Error(CustomError.EXPORT_STOPPED); } await this.verifyExportFolderExists(exportFolder); - addLogLine( + log.info( `removing collection with id ${collectionID} from export folder`, ); const collectionExportName = @@ -600,11 +597,13 @@ class ExportService { ); try { // delete the collection metadata folder - await ElectronAPIs.deleteFolder( + await ensureElectron().deleteFolder( getMetadataFolderExportPath(collectionExportPath), ); // delete the collection folder - await ElectronAPIs.deleteFolder(collectionExportPath); + await ensureElectron().deleteFolder( + collectionExportPath, + ); } catch (e) { await this.addCollectionExportedRecord( exportFolder, @@ -613,11 +612,11 @@ class ExportService { ); throw e; } - addLogLine( + log.info( `removing collection with id ${collectionID} from export folder successful`, ); } catch (e) { - logError(e, "collectionRemover failed a collection"); + log.error("collectionRemover failed a collection", e); if ( e.message === CustomError.UPDATE_EXPORTED_RECORD_FAILED || @@ -634,7 +633,7 @@ class ExportService { e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST && e.message !== CustomError.EXPORT_STOPPED ) { - logError(e, "collectionRemover failed"); + log.error("collectionRemover failed", e); } throw e; } @@ -651,7 +650,7 @@ class ExportService { ): Promise { try { for (const file of files) { - addLogLine( + log.info( `exporting file ${file.metadata.title} with id ${ file.id } from collection ${collectionIDNameMap.get( @@ -687,10 +686,10 @@ class ExportService { exportDir, collectionExportName, ); - await ElectronAPIs.checkExistsAndCreateDir( + await ensureElectron().checkExistsAndCreateDir( collectionExportPath, ); - await ElectronAPIs.checkExistsAndCreateDir( + await ensureElectron().checkExistsAndCreateDir( getMetadataFolderExportPath(collectionExportPath), ); await this.downloadAndSave( @@ -699,7 +698,7 @@ class ExportService { file, ); incrementSuccess(); - addLogLine( + log.info( `exporting file ${file.metadata.title} with id ${ file.id } from collection ${collectionIDNameMap.get( @@ -708,7 +707,7 @@ class ExportService { ); } catch (e) { incrementFailed(); - logError(e, "export failed for a file"); + log.error("export failed for a file", e); if ( e.message === CustomError.UPDATE_EXPORTED_RECORD_FAILED || @@ -725,7 +724,7 @@ class ExportService { e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST && e.message !== CustomError.EXPORT_STOPPED ) { - logError(e, "fileExporter failed"); + log.error("fileExporter failed", e); } throw e; } @@ -744,7 +743,7 @@ class ExportService { ); for (const fileUID of removedFileUIDs) { await this.verifyExportFolderExists(exportDir); - addLogLine(`trashing file with id ${fileUID}`); + log.info(`trashing file with id ${fileUID}`); if (isCanceled.status) { throw Error(CustomError.EXPORT_STOPPED); } @@ -766,11 +765,11 @@ class ExportService { collectionExportPath, imageExportName, ); - addLogLine( + log.info( `moving image file ${imageExportPath} to trash folder`, ); if (await this.exists(imageExportPath)) { - await ElectronAPIs.moveFile( + await ensureElectron().moveFile( imageExportPath, await getTrashedFileExportPath( exportDir, @@ -785,7 +784,7 @@ class ExportService { if ( await this.exists(imageMetadataFileExportPath) ) { - await ElectronAPIs.moveFile( + await ensureElectron().moveFile( imageMetadataFileExportPath, await getTrashedFileExportPath( exportDir, @@ -798,11 +797,11 @@ class ExportService { collectionExportPath, videoExportName, ); - addLogLine( + log.info( `moving video file ${videoExportPath} to trash folder`, ); if (await this.exists(videoExportPath)) { - await ElectronAPIs.moveFile( + await ensureElectron().moveFile( videoExportPath, await getTrashedFileExportPath( exportDir, @@ -815,7 +814,7 @@ class ExportService { if ( await this.exists(videoMetadataFileExportPath) ) { - await ElectronAPIs.moveFile( + await ensureElectron().moveFile( videoMetadataFileExportPath, await getTrashedFileExportPath( exportDir, @@ -833,11 +832,11 @@ class ExportService { exportDir, fileExportPath, ); - addLogLine( + log.info( `moving file ${fileExportPath} to ${trashedFilePath} trash folder`, ); if (await this.exists(fileExportPath)) { - await ElectronAPIs.moveFile( + await ensureElectron().moveFile( fileExportPath, trashedFilePath, ); @@ -845,7 +844,7 @@ class ExportService { const metadataFileExportPath = getMetadataFileExportPath(fileExportPath); if (await this.exists(metadataFileExportPath)) { - await ElectronAPIs.moveFile( + await ensureElectron().moveFile( metadataFileExportPath, await getTrashedFileExportPath( exportDir, @@ -862,9 +861,9 @@ class ExportService { ); throw e; } - addLogLine(`trashing file with id ${fileUID} successful`); + log.info(`trashing file with id ${fileUID} successful`); } catch (e) { - logError(e, "trashing failed for a file"); + log.error("trashing failed for a file", e); if ( e.message === CustomError.UPDATE_EXPORTED_RECORD_FAILED || @@ -881,7 +880,7 @@ class ExportService { e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST && e.message !== CustomError.EXPORT_STOPPED ) { - logError(e, "fileTrasher failed"); + log.error("fileTrasher failed", e); } throw e; } @@ -904,7 +903,7 @@ class ExportService { await this.updateExportRecord(folder, exportRecord); } catch (e) { if (e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST) { - logError(e, "addFileExportedRecord failed"); + log.error("addFileExportedRecord failed", e); } throw e; } @@ -928,7 +927,7 @@ class ExportService { await this.updateExportRecord(folder, exportRecord); } catch (e) { if (e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST) { - logError(e, "addCollectionExportedRecord failed"); + log.error("addCollectionExportedRecord failed", e); } throw e; } @@ -947,7 +946,7 @@ class ExportService { await this.updateExportRecord(folder, exportRecord); } catch (e) { if (e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST) { - logError(e, "removeCollectionExportedRecord failed"); + log.error("removeCollectionExportedRecord failed", e); } throw e; } @@ -964,7 +963,7 @@ class ExportService { await this.updateExportRecord(folder, exportRecord); } catch (e) { if (e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST) { - logError(e, "removeFileExportedRecord failed"); + log.error("removeFileExportedRecord failed", e); } throw e; } @@ -984,7 +983,7 @@ class ExportService { try { const exportRecord = await this.getExportRecord(folder); const newRecord: ExportRecord = { ...exportRecord, ...newData }; - await ElectronAPIs.saveFileToDisk( + await ensureElectron().saveFileToDisk( `${folder}/${EXPORT_RECORD_FILE_NAME}`, JSON.stringify(newRecord, null, 2), ); @@ -993,7 +992,7 @@ class ExportService { if (e.message === CustomError.EXPORT_FOLDER_DOES_NOT_EXIST) { throw e; } - logError(e, "error updating Export Record"); + log.error("error updating Export Record", e); throw Error(CustomError.UPDATE_EXPORTED_RECORD_FAILED); } } @@ -1006,7 +1005,7 @@ class ExportService { return this.createEmptyExportRecord(exportRecordJSONPath); } const recordFile = - await ElectronAPIs.readTextFile(exportRecordJSONPath); + await ensureElectron().readTextFile(exportRecordJSONPath); try { return JSON.parse(recordFile); } catch (e) { @@ -1021,7 +1020,7 @@ class ExportService { return await this.getExportRecord(folder, false); } if (e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST) { - logError(e, "export Record JSON parsing failed"); + log.error("export Record JSON parsing failed", e); } throw e; } @@ -1042,8 +1041,8 @@ class ExportService { exportFolder, collectionExportName, ); - await ElectronAPIs.checkExistsAndCreateDir(collectionExportPath); - await ElectronAPIs.checkExistsAndCreateDir( + await ensureElectron().checkExistsAndCreateDir(collectionExportPath); + await ensureElectron().checkExistsAndCreateDir( getMetadataFolderExportPath(collectionExportPath), ); @@ -1090,7 +1089,7 @@ class ExportService { fileExportName, file, ); - await ElectronAPIs.saveStreamToDisk( + await ensureElectron().saveStreamToDisk( getFileExportPath(collectionExportPath, fileExportName), updatedFileStream, ); @@ -1100,7 +1099,7 @@ class ExportService { } } } catch (e) { - logError(e, "download and save failed"); + log.error("download and save failed", e); throw e; } } @@ -1138,7 +1137,7 @@ class ExportService { imageExportName, file, ); - await ElectronAPIs.saveStreamToDisk( + await ensureElectron().saveStreamToDisk( getFileExportPath(collectionExportPath, imageExportName), imageStream, ); @@ -1150,12 +1149,12 @@ class ExportService { file, ); try { - await ElectronAPIs.saveStreamToDisk( + await ensureElectron().saveStreamToDisk( getFileExportPath(collectionExportPath, videoExportName), videoStream, ); } catch (e) { - await ElectronAPIs.deleteFile( + await ensureElectron().deleteFile( getFileExportPath(collectionExportPath, imageExportName), ); throw e; @@ -1171,7 +1170,7 @@ class ExportService { fileExportName: string, file: EnteFile, ) { - await ElectronAPIs.saveFileToDisk( + await ensureElectron().saveFileToDisk( getFileMetadataExportPath(collectionExportPath, fileExportName), getGoogleLikeMetadataFile(fileExportName, file), ); @@ -1182,15 +1181,15 @@ class ExportService { }; exists = (path: string) => { - return ElectronAPIs.fs.exists(path); + return ensureElectron().fs.exists(path); }; rename = (oldPath: string, newPath: string) => { - return ElectronAPIs.rename(oldPath, newPath); + return ensureElectron().rename(oldPath, newPath); }; checkExistsAndCreateDir = (path: string) => { - return ElectronAPIs.checkExistsAndCreateDir(path); + return ensureElectron().checkExistsAndCreateDir(path); }; exportFolderExists = async (exportFolder: string) => { @@ -1204,7 +1203,7 @@ class ExportService { } } catch (e) { if (e.message !== CustomError.EXPORT_FOLDER_DOES_NOT_EXIST) { - logError(e, "verifyExportFolderExists failed"); + log.error("verifyExportFolderExists failed", e); } throw e; } @@ -1212,7 +1211,7 @@ class ExportService { private createEmptyExportRecord = async (exportRecordJSONPath: string) => { const exportRecord: ExportRecord = NULL_EXPORT_RECORD; - await ElectronAPIs.saveFileToDisk( + await ensureElectron().saveFileToDisk( exportRecordJSONPath, JSON.stringify(exportRecord, null, 2), ); diff --git a/web/apps/photos/src/services/ffmpeg/ffmpegFactory.ts b/web/apps/photos/src/services/ffmpeg/ffmpegFactory.ts index decd32521..49aee9868 100644 --- a/web/apps/photos/src/services/ffmpeg/ffmpegFactory.ts +++ b/web/apps/photos/src/services/ffmpeg/ffmpegFactory.ts @@ -1,5 +1,3 @@ -import ElectronAPIs from "@/next/electron"; -import isElectron from "is-electron"; import { ElectronFile } from "types/upload"; import ComlinkFFmpegWorker from "utils/comlink/ComlinkFFmpegWorker"; @@ -16,10 +14,11 @@ class FFmpegFactory { private client: IFFmpeg; async getFFmpegClient() { if (!this.client) { - if (isElectron()) { + const electron = globalThis.electron; + if (electron) { this.client = { run(cmd, inputFile, outputFilename, dontTimeout) { - return ElectronAPIs.runFFmpegCmd( + return electron.runFFmpegCmd( cmd, inputFile, outputFilename, diff --git a/web/apps/photos/src/services/ffmpeg/ffmpegService.ts b/web/apps/photos/src/services/ffmpeg/ffmpegService.ts index f6addc134..0a6a66cb0 100644 --- a/web/apps/photos/src/services/ffmpeg/ffmpegService.ts +++ b/web/apps/photos/src/services/ffmpeg/ffmpegService.ts @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { FFMPEG_PLACEHOLDER, INPUT_PATH_PLACEHOLDER, @@ -40,7 +40,7 @@ export async function generateVideoThumbnail( seekTime--; } } catch (e) { - logError(e, "ffmpeg generateVideoThumbnail failed"); + log.error("ffmpeg generateVideoThumbnail failed", e); throw e; } } @@ -72,7 +72,7 @@ export async function extractVideoMetadata(file: File | ElectronFile) { new Uint8Array(await metadata.arrayBuffer()), ); } catch (e) { - logError(e, "ffmpeg extractVideoMetadata failed"); + log.error("ffmpeg extractVideoMetadata failed", e); throw e; } } @@ -94,7 +94,7 @@ export async function convertToMP4(file: File | ElectronFile) { true, ); } catch (e) { - logError(e, "ffmpeg convertToMP4 failed"); + log.error("ffmpeg convertToMP4 failed", e); throw e; } } diff --git a/web/apps/photos/src/services/fileService.ts b/web/apps/photos/src/services/fileService.ts index 62d5e309e..83bd505c9 100644 --- a/web/apps/photos/src/services/fileService.ts +++ b/web/apps/photos/src/services/fileService.ts @@ -1,11 +1,9 @@ -import { getEndpoint } from "@ente/shared/network/api"; -import localForage from "@ente/shared/storage/localForage"; - +import log from "@/next/log"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import { Events, eventBus } from "@ente/shared/events"; -import { addLogLine } from "@ente/shared/logging"; import HTTPService from "@ente/shared/network/HTTPService"; -import { logError } from "@ente/shared/sentry"; +import { getEndpoint } from "@ente/shared/network/api"; +import localForage from "@ente/shared/storage/localForage"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { REQUEST_BATCH_SIZE } from "constants/api"; import { Collection } from "types/collection"; @@ -48,18 +46,19 @@ const setLocalFiles = async (type: "normal" | "hidden", files: EnteFile[]) => { try { eventBus.emit(Events.LOCAL_FILES_UPDATED); } catch (e) { - logError(e, "Error in localFileUpdated handlers"); + log.error("Error in localFileUpdated handlers", e); } } catch (e1) { try { const storageEstimate = await navigator.storage.estimate(); - logError(e1, "failed to save files to indexedDB", { - storageEstimate, - }); - addLogLine(`storage estimate ${JSON.stringify(storageEstimate)}`); + log.error( + `failed to save files to indexedDB (storageEstimate was ${storageEstimate}`, + e1, + ); + log.info(`storage estimate ${JSON.stringify(storageEstimate)}`); } catch (e2) { - logError(e1, "failed to save files to indexedDB"); - logError(e2, "failed to get storage stats"); + log.error("failed to save files to indexedDB", e1); + log.error("failed to get storage stats", e2); } throw e1; } @@ -151,7 +150,7 @@ export const getFiles = async ( } while (resp.data.hasMore); return decryptedFiles; } catch (e) { - logError(e, "Get files failed"); + log.error("Get files failed", e); throw e; } }; @@ -192,7 +191,7 @@ export const trashFiles = async (filesToTrash: EnteFile[]) => { ); } } catch (e) { - logError(e, "trash file failed"); + log.error("trash file failed", e); throw e; } }; @@ -216,7 +215,7 @@ export const deleteFromTrash = async (filesToDelete: number[]) => { ); } } catch (e) { - logError(e, "deleteFromTrash failed"); + log.error("deleteFromTrash failed", e); throw e; } }; diff --git a/web/apps/photos/src/services/heic-convert/service.ts b/web/apps/photos/src/services/heic-convert/service.ts index 8b8988500..0dc650612 100644 --- a/web/apps/photos/src/services/heic-convert/service.ts +++ b/web/apps/photos/src/services/heic-convert/service.ts @@ -1,8 +1,7 @@ import { convertBytesToHumanReadable } from "@/next/file"; +import log from "@/next/log"; import { ComlinkWorker } from "@/next/worker/comlink-worker"; import { CustomError } from "@ente/shared/error"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; import { retryAsyncFunction } from "@ente/shared/utils"; import QueueProcessor from "@ente/shared/utils/queueProcessor"; import { getDedicatedConvertWorker } from "utils/comlink/ComlinkConvertWorker"; @@ -46,7 +45,7 @@ class HEICConverter { await worker.convertHEICToJPEG( fileBlob, ); - addLogLine( + log.info( `originalFileSize:${convertBytesToHumanReadable( fileBlob?.size, )},convertedFileSize:${convertBytesToHumanReadable( @@ -65,17 +64,19 @@ class HEICConverter { }, ); if (!convertedHEIC || convertedHEIC?.size === 0) { - logError( - Error(`converted heic fileSize is Zero`), - "converted heic fileSize is Zero", - { - originalFileSize: convertBytesToHumanReadable( - fileBlob?.size ?? 0, - ), - convertedFileSize: convertBytesToHumanReadable( - convertedHEIC?.size ?? 0, - ), - }, + log.error( + `converted heic fileSize is Zero - ${JSON.stringify( + { + originalFileSize: + convertBytesToHumanReadable( + fileBlob?.size ?? 0, + ), + convertedFileSize: + convertBytesToHumanReadable( + convertedHEIC?.size ?? 0, + ), + }, + )}`, ); } await new Promise((resolve) => { @@ -87,7 +88,7 @@ class HEICConverter { this.workerPool.push(convertWorker); return convertedHEIC; } catch (e) { - logError(e, "heic conversion failed"); + log.error("heic conversion failed", e); convertWorker.terminate(); this.workerPool.push(getDedicatedConvertWorker()); throw e; diff --git a/web/apps/photos/src/services/heicConversionService.ts b/web/apps/photos/src/services/heicConversionService.ts index bccdb0ca0..189781494 100644 --- a/web/apps/photos/src/services/heicConversionService.ts +++ b/web/apps/photos/src/services/heicConversionService.ts @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import WasmHEICConverterService from "./heic-convert/service"; class HeicConversionService { @@ -6,7 +6,7 @@ class HeicConversionService { try { return await WasmHEICConverterService.convert(heicFileData); } catch (e) { - logError(e, "failed to convert heic file"); + log.error("failed to convert heic file", e); throw e; } } diff --git a/web/apps/photos/src/services/importService.ts b/web/apps/photos/src/services/importService.ts index 833e1b3e2..6d2c46a85 100644 --- a/web/apps/photos/src/services/importService.ts +++ b/web/apps/photos/src/services/importService.ts @@ -1,5 +1,5 @@ -import ElectronAPIs from "@/next/electron"; -import { logError } from "@ente/shared/sentry"; +import { ensureElectron } from "@/next/electron"; +import log from "@/next/log"; import { PICKED_UPLOAD_TYPE } from "constants/upload"; import { Collection } from "types/collection"; import { ElectronFile, FileWithCollection } from "types/upload"; @@ -14,13 +14,13 @@ class ImportService { async getPendingUploads(): Promise { try { const pendingUploads = - (await ElectronAPIs.getPendingUploads()) as PendingUploads; + (await ensureElectron().getPendingUploads()) as PendingUploads; return pendingUploads; } catch (e) { if (e?.message?.includes("ENOENT: no such file or directory")) { // ignore } else { - logError(e, "failed to getPendingUploads "); + log.error("failed to getPendingUploads ", e); } return { files: [], collectionName: null, type: null }; } @@ -40,7 +40,7 @@ class ImportService { if (collections.length === 1) { collectionName = collections[0].name; } - await ElectronAPIs.setToUploadCollection(collectionName); + await ensureElectron().setToUploadCollection(collectionName); } async updatePendingUploads(files: FileWithCollection[]) { @@ -57,16 +57,17 @@ class ImportService { filePaths.push((fileWithCollection.file as ElectronFile).path); } } - await ElectronAPIs.setToUploadFiles( + await ensureElectron().setToUploadFiles( PICKED_UPLOAD_TYPE.FILES, filePaths, ); } async cancelRemainingUploads() { - await ElectronAPIs.setToUploadCollection(null); - await ElectronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.ZIPS, []); - await ElectronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.FILES, []); + const electron = ensureElectron(); + await electron.setToUploadCollection(null); + await electron.setToUploadFiles(PICKED_UPLOAD_TYPE.ZIPS, []); + await electron.setToUploadFiles(PICKED_UPLOAD_TYPE.FILES, []); } } diff --git a/web/apps/photos/src/services/locationSearchService.ts b/web/apps/photos/src/services/locationSearchService.ts index bfc6990da..2aa2b6bac 100644 --- a/web/apps/photos/src/services/locationSearchService.ts +++ b/web/apps/photos/src/services/locationSearchService.ts @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { LocationTagData } from "types/entity"; import { Location } from "types/upload"; @@ -30,7 +30,7 @@ class LocationSearchService { }); await this.citiesPromise; } catch (e) { - logError(e, "LocationSearchService loadCities failed"); + log.error("LocationSearchService loadCities failed", e); this.citiesPromise = null; } } @@ -47,7 +47,7 @@ class LocationSearchService { .startsWith(searchTerm.toLowerCase()); }); } catch (e) { - logError(e, "LocationSearchService searchCities failed"); + log.error("LocationSearchService searchCities failed", e); throw e; } } diff --git a/web/apps/photos/src/services/machineLearning/blazeFaceDetectionService.ts b/web/apps/photos/src/services/machineLearning/blazeFaceDetectionService.ts index 2a82efb0a..615ed5b4c 100644 --- a/web/apps/photos/src/services/machineLearning/blazeFaceDetectionService.ts +++ b/web/apps/photos/src/services/machineLearning/blazeFaceDetectionService.ts @@ -1,4 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; +import log from "@/next/log"; import { GraphModel } from "@tensorflow/tfjs-converter"; import * as tf from "@tensorflow/tfjs-core"; import { @@ -60,7 +60,7 @@ class BlazeFaceDetectionService implements FaceDetectionService { inputHeight: BLAZEFACE_INPUT_SIZE, inputWidth: BLAZEFACE_INPUT_SIZE, }); - addLogLine( + log.info( "loaded blazeFaceModel: ", // await this.blazeFaceModel, // eslint-disable-next-line @typescript-eslint/await-thenable @@ -121,20 +121,20 @@ class BlazeFaceDetectionService implements FaceDetectionService { let desiredDist = desiredRightEyeX - this.desiredLeftEye[0]; desiredDist *= this.desiredFaceSize; const scale = desiredDist / dist; - // addLogLine("scale: ", scale); + // log.info("scale: ", scale); const eyesCenter = []; eyesCenter[0] = Math.floor((leftEye[0] + rightEye[0]) / 2); eyesCenter[1] = Math.floor((leftEye[1] + rightEye[1]) / 2); - // addLogLine("eyesCenter: ", eyesCenter); + // log.info("eyesCenter: ", eyesCenter); const faceWidth = this.desiredFaceSize / scale; const faceHeight = this.desiredFaceSize / scale; - // addLogLine("faceWidth: ", faceWidth, "faceHeight: ", faceHeight) + // log.info("faceWidth: ", faceWidth, "faceHeight: ", faceHeight) const tx = eyesCenter[0] - faceWidth * 0.5; const ty = eyesCenter[1] - faceHeight * this.desiredLeftEye[1]; - // addLogLine("tx: ", tx, "ty: ", ty); + // log.info("tx: ", tx, "ty: ", ty); return new Box({ left: tx, @@ -155,7 +155,7 @@ class BlazeFaceDetectionService implements FaceDetectionService { const normalizedImage = tf.sub(tf.div(reshapedImage, 127.5), 1.0); // eslint-disable-next-line @typescript-eslint/await-thenable const results = await this.blazeFaceBackModel.predict(normalizedImage); - // addLogLine('onFacesDetected: ', results); + // log.info('onFacesDetected: ', results); return results; } @@ -180,7 +180,7 @@ class BlazeFaceDetectionService implements FaceDetectionService { const inBox = newBox(0, 0, resized.width, resized.height); const toBox = newBox(0, 0, imageBitmap.width, imageBitmap.height); const transform = computeTransformToBox(inBox, toBox); - // addLogLine("1st pass: ", { transform }); + // log.info("1st pass: ", { transform }); const faceDetections: Array = faces?.map((f) => { const box = transformBox(normFaceBox(f), transform); @@ -223,7 +223,7 @@ class BlazeFaceDetectionService implements FaceDetectionService { ); let selected = pass2Detections?.[0]; if (pass2Detections?.length > 1) { - // addLogLine('2nd pass >1 face', pass2Detections.length); + // log.info('2nd pass >1 face', pass2Detections.length); selected = getNearestDetection( pass1Detection, pass2Detections, @@ -234,7 +234,7 @@ class BlazeFaceDetectionService implements FaceDetectionService { // we might miss 1st pass face actually having score within threshold // it is ok as results will be consistent with 2nd pass only detections if (selected && selected.probability >= BLAZEFACE_SCORE_THRESHOLD) { - // addLogLine("pass2: ", { imageBox, paddedBox, transform, selected }); + // log.info("pass2: ", { imageBox, paddedBox, transform, selected }); detections.push(selected); } } diff --git a/web/apps/photos/src/services/machineLearning/clusteringService.ts b/web/apps/photos/src/services/machineLearning/clusteringService.ts index d4c0b4ea1..03931b63b 100644 --- a/web/apps/photos/src/services/machineLearning/clusteringService.ts +++ b/web/apps/photos/src/services/machineLearning/clusteringService.ts @@ -26,7 +26,7 @@ class ClusteringService { epsilon: number = 1.0, minPts: number = 2, ): ClusteringResults { - // addLogLine("distanceFunction", DBSCAN._); + // log.info("distanceFunction", DBSCAN._); const clusters = this.dbscan.run(dataset, epsilon, minPts); const noise = this.dbscan.noise; return { clusters, noise }; diff --git a/web/apps/photos/src/services/machineLearning/dbscanClusteringService.ts b/web/apps/photos/src/services/machineLearning/dbscanClusteringService.ts index b2343bdd5..33298eef3 100644 --- a/web/apps/photos/src/services/machineLearning/dbscanClusteringService.ts +++ b/web/apps/photos/src/services/machineLearning/dbscanClusteringService.ts @@ -22,7 +22,7 @@ class DbscanClusteringService implements ClusteringService { input: ClusteringInput, config: ClusteringConfig, ): Promise { - // addLogLine('Clustering input: ', input); + // log.info('Clustering input: ', input); const dbscan = new DBSCAN(); const clusters = dbscan.run( input, diff --git a/web/apps/photos/src/services/machineLearning/faceService.ts b/web/apps/photos/src/services/machineLearning/faceService.ts index 1355ca494..a5e20804d 100644 --- a/web/apps/photos/src/services/machineLearning/faceService.ts +++ b/web/apps/photos/src/services/machineLearning/faceService.ts @@ -1,4 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; +import log from "@/next/log"; import { DetectedFace, Face, @@ -51,7 +51,7 @@ class FaceService { ); const faceDetections = await syncContext.faceDetectionService.detectFaces(imageBitmap); - // addLogLine('3 TF Memory stats: ',JSON.stringify(tf.memory())); + // log.info('3 TF Memory stats: ',JSON.stringify(tf.memory())); // TODO: reenable faces filtering based on width const detectedFaces = faceDetections?.map((detection) => { return { @@ -66,7 +66,7 @@ class FaceService { // ?.filter((f) => // f.box.width > syncContext.config.faceDetection.minFaceSize // ); - addLogLine("[MLService] Detected Faces: ", newMlFile.faces?.length); + log.info("[MLService] Detected Faces: ", newMlFile.faces?.length); } async syncFileFaceCrops( @@ -128,8 +128,8 @@ class FaceService { face.detection, ); } - addLogLine("[MLService] alignedFaces: ", newMlFile.faces?.length); - // addLogLine('4 TF Memory stats: ',JSON.stringify(tf.memory())); + log.info("[MLService] alignedFaces: ", newMlFile.faces?.length); + // log.info('4 TF Memory stats: ',JSON.stringify(tf.memory())); } async syncFileFaceEmbeddings( @@ -168,8 +168,8 @@ class FaceService { faceImages.forEach((faceImage) => faceImage.close()); newMlFile.faces.forEach((f, i) => (f.embedding = embeddings[i])); - addLogLine("[MLService] facesWithEmbeddings: ", newMlFile.faces.length); - // addLogLine('5 TF Memory stats: ',JSON.stringify(tf.memory())); + log.info("[MLService] facesWithEmbeddings: ", newMlFile.faces.length); + // log.info('5 TF Memory stats: ',JSON.stringify(tf.memory())); } async saveFaceCrop( @@ -210,14 +210,14 @@ class FaceService { const clusteringConfig = syncContext.config.faceClustering; if (!allFaces || allFaces.length < clusteringConfig.minInputSize) { - addLogLine( + log.info( "[MLService] Too few faces to cluster, not running clustering: ", allFaces.length, ); return; } - addLogLine("Running clustering allFaces: ", allFaces.length); + log.info("Running clustering allFaces: ", allFaces.length); syncContext.mlLibraryData.faceClusteringResults = await syncContext.faceClusteringService.cluster( allFaces.map((f) => Array.from(f.embedding)), @@ -225,7 +225,7 @@ class FaceService { ); syncContext.mlLibraryData.faceClusteringMethod = syncContext.faceClusteringService.method; - addLogLine( + log.info( "[MLService] Got face clustering results: ", JSON.stringify(syncContext.mlLibraryData.faceClusteringResults), ); diff --git a/web/apps/photos/src/services/machineLearning/hdbscanClusteringService.ts b/web/apps/photos/src/services/machineLearning/hdbscanClusteringService.ts index da7808d45..21e211825 100644 --- a/web/apps/photos/src/services/machineLearning/hdbscanClusteringService.ts +++ b/web/apps/photos/src/services/machineLearning/hdbscanClusteringService.ts @@ -22,7 +22,7 @@ class HdbscanClusteringService implements ClusteringService { input: ClusteringInput, config: ClusteringConfig, ): Promise { - // addLogLine('Clustering input: ', input); + // log.info('Clustering input: ', input); const hdbscan = new Hdbscan({ input, diff --git a/web/apps/photos/src/services/machineLearning/imageSceneService.ts b/web/apps/photos/src/services/machineLearning/imageSceneService.ts index 65438a5b9..d0ee6ec41 100644 --- a/web/apps/photos/src/services/machineLearning/imageSceneService.ts +++ b/web/apps/photos/src/services/machineLearning/imageSceneService.ts @@ -1,4 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; +import log from "@/next/log"; import * as tfjsConverter from "@tensorflow/tfjs-converter"; import * as tf from "@tensorflow/tfjs-core"; import { SCENE_DETECTION_IMAGE_SIZE } from "constants/mlConfig"; @@ -26,7 +26,7 @@ class ImageScene implements SceneDetectionService { } private async init() { - addLogLine(`[${this.workerID}]`, "ImageScene init called"); + log.info(`[${this.workerID}]`, "ImageScene init called"); if (this.model) { return; } @@ -38,7 +38,7 @@ class ImageScene implements SceneDetectionService { this.model = await tfjsConverter.loadGraphModel( "/models/imagescene/model.json", ); - addLogLine( + log.info( `[${this.workerID}]`, "loaded ImageScene model", tf.getBackend(), @@ -52,10 +52,7 @@ class ImageScene implements SceneDetectionService { } private async getImageSceneModel() { - addLogLine( - `[${this.workerID}]`, - "ImageScene getImageSceneModel called", - ); + log.info(`[${this.workerID}]`, "ImageScene getImageSceneModel called"); if (!this.ready) { this.ready = this.init(); } diff --git a/web/apps/photos/src/services/machineLearning/machineLearningFactory.ts b/web/apps/photos/src/services/machineLearning/machineLearningFactory.ts index 52d42821a..7edc38127 100644 --- a/web/apps/photos/src/services/machineLearning/machineLearningFactory.ts +++ b/web/apps/photos/src/services/machineLearning/machineLearningFactory.ts @@ -1,8 +1,8 @@ import { haveWindow } from "@/next/env"; +import log from "@/next/log"; import { ComlinkWorker } from "@/next/worker/comlink-worker"; import { getDedicatedCryptoWorker } from "@ente/shared/crypto"; import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker"; -import { addLogLine } from "@ente/shared/logging"; import PQueue from "p-queue"; import { EnteFile } from "types/file"; import { @@ -198,7 +198,7 @@ export class LocalMLSyncContext implements MLSyncContext { this.concurrency = concurrency || getConcurrency(); - addLogLine("Using concurrency: ", this.concurrency); + log.info("Using concurrency: ", this.concurrency); // timeout is added on downloads // timeout on queue will keep the operation open till worker is terminated this.syncQueue = new PQueue({ concurrency: this.concurrency }); diff --git a/web/apps/photos/src/services/machineLearning/machineLearningService.ts b/web/apps/photos/src/services/machineLearning/machineLearningService.ts index a76c740e1..891db3eff 100644 --- a/web/apps/photos/src/services/machineLearning/machineLearningService.ts +++ b/web/apps/photos/src/services/machineLearning/machineLearningService.ts @@ -1,7 +1,6 @@ +import log from "@/next/log"; import { APPS } from "@ente/shared/apps/constants"; import { CustomError, parseUploadErrorCodes } from "@ente/shared/error"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; import "@tensorflow/tfjs-backend-cpu"; import "@tensorflow/tfjs-backend-webgl"; import * as tf from "@tensorflow/tfjs-core"; @@ -79,10 +78,10 @@ class MachineLearningService { tsne: syncContext.tsne, error: syncContext.error, }; - // addLogLine('[MLService] sync results: ', mlSyncResult); + // log.info('[MLService] sync results: ', mlSyncResult); // await syncContext.dispose(); - addLogLine("Final TF Memory stats: ", JSON.stringify(tf.memory())); + log.info("Final TF Memory stats: ", JSON.stringify(tf.memory())); return mlSyncResult; } @@ -140,7 +139,7 @@ class MachineLearningService { let updated = false; if (newFileIds.length > 0) { - addLogLine("newFiles: ", newFileIds.length); + log.info("newFiles: ", newFileIds.length); const newFiles = newFileIds.map((fileId) => this.newMlData(fileId)); await mlIDbStorage.putAllFiles(newFiles, tx); updated = true; @@ -154,7 +153,7 @@ class MachineLearningService { } if (removedFileIds.length > 0) { - addLogLine("removedFiles: ", removedFileIds.length); + log.info("removedFiles: ", removedFileIds.length); await mlIDbStorage.removeAllFiles(removedFileIds, tx); updated = true; } @@ -166,7 +165,7 @@ class MachineLearningService { await mlIDbStorage.incrementIndexVersion("files"); } - addLogLine("syncLocalFiles", Date.now() - startTime, "ms"); + log.info("syncLocalFiles", Date.now() - startTime, "ms"); } private async getOutOfSyncFiles(syncContext: MLSyncContext) { @@ -177,13 +176,13 @@ class MachineLearningService { MAX_ML_SYNC_ERROR_COUNT, ); - addLogLine("fileIds: ", JSON.stringify(fileIds)); + log.info("fileIds: ", JSON.stringify(fileIds)); const localFilesMap = await this.getLocalFilesMap(syncContext); syncContext.outOfSyncFiles = fileIds.map((fileId) => localFilesMap.get(fileId), ); - addLogLine("getOutOfSyncFiles", Date.now() - startTime, "ms"); + log.info("getOutOfSyncFiles", Date.now() - startTime, "ms"); } private async syncFiles(syncContext: MLSyncContext) { @@ -206,7 +205,7 @@ class MachineLearningService { syncContext.error = error; } await syncContext.syncQueue.onIdle(); - addLogLine("allFaces: ", syncContext.nSyncedFaces); + log.info("allFaces: ", syncContext.nSyncedFaces); // TODO: In case syncJob has to use multiple ml workers // do in same transaction with each file update @@ -217,32 +216,32 @@ class MachineLearningService { private async getSyncContext(token: string, userID: number) { if (!this.syncContext) { - addLogLine("Creating syncContext"); + log.info("Creating syncContext"); this.syncContext = getMLSyncConfig().then((mlSyncConfig) => MLFactory.getMLSyncContext(token, userID, mlSyncConfig, true), ); } else { - addLogLine("reusing existing syncContext"); + log.info("reusing existing syncContext"); } return this.syncContext; } private async getLocalSyncContext(token: string, userID: number) { if (!this.localSyncContext) { - addLogLine("Creating localSyncContext"); + log.info("Creating localSyncContext"); this.localSyncContext = getMLSyncConfig().then((mlSyncConfig) => MLFactory.getMLSyncContext(token, userID, mlSyncConfig, false), ); } else { - addLogLine("reusing existing localSyncContext"); + log.info("reusing existing localSyncContext"); } return this.localSyncContext; } public async closeLocalSyncContext() { if (this.localSyncContext) { - addLogLine("Closing localSyncContext"); + log.info("Closing localSyncContext"); const syncContext = await this.localSyncContext; await syncContext.dispose(); this.localSyncContext = undefined; @@ -294,7 +293,7 @@ class MachineLearningService { syncContext.nSyncedFiles += 1; return mlFileData; } catch (e) { - logError(e, "ML syncFile failed"); + log.error("ML syncFile failed", e); let error = e; console.error( "Error in ml sync, fileId: ", @@ -320,7 +319,7 @@ class MachineLearningService { await this.persistMLFileSyncError(syncContext, enteFile, error); syncContext.nSyncedFiles += 1; } finally { - addLogLine("TF Memory stats: ", JSON.stringify(tf.memory())); + log.info("TF Memory stats: ", JSON.stringify(tf.memory())); } } @@ -362,13 +361,13 @@ class MachineLearningService { newMlFile.lastErrorMessage = undefined; await this.persistMLFileData(syncContext, newMlFile); } catch (e) { - logError(e, "ml detection failed"); + log.error("ml detection failed", e); newMlFile.mlVersion = oldMlFile.mlVersion; throw e; } finally { fileContext.tfImage && fileContext.tfImage.dispose(); fileContext.imageBitmap && fileContext.imageBitmap.close(); - // addLogLine('8 TF Memory stats: ',JSON.stringify(tf.memory())); + // log.info('8 TF Memory stats: ',JSON.stringify(tf.memory())); // TODO: enable once faceId changes go in // await removeOldFaceCrops( @@ -387,7 +386,7 @@ class MachineLearningService { await tf.ready(); - addLogLine("01 TF Memory stats: ", JSON.stringify(tf.memory())); + log.info("01 TF Memory stats: ", JSON.stringify(tf.memory())); this.initialized = true; } @@ -464,7 +463,7 @@ class MachineLearningService { await FaceService.syncFileFaceEmbeddings(syncContext, fileContext); } - addLogLine( + log.info( `face detection time taken ${fileContext.enteFile.id}`, Date.now() - startTime, "ms", diff --git a/web/apps/photos/src/services/machineLearning/mlWorkManager.ts b/web/apps/photos/src/services/machineLearning/mlWorkManager.ts index 47bd602c0..37b7c7d13 100644 --- a/web/apps/photos/src/services/machineLearning/mlWorkManager.ts +++ b/web/apps/photos/src/services/machineLearning/mlWorkManager.ts @@ -1,7 +1,6 @@ +import log from "@/next/log"; import { ComlinkWorker } from "@/next/worker/comlink-worker"; import { eventBus, Events } from "@ente/shared/events"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; import { getToken, getUserID } from "@ente/shared/storage/localStorage/helpers"; import { FILE_TYPE } from "constants/file"; import debounce from "debounce"; @@ -51,7 +50,7 @@ class MLWorkManager { public async setMlSearchEnabled(enabled: boolean) { if (!this.mlSearchEnabled && enabled) { - addLogLine("Enabling MLWorkManager"); + log.info("Enabling MLWorkManager"); this.mlSearchEnabled = true; logQueueStats(this.liveSyncQueue, "livesync"); @@ -70,7 +69,7 @@ class MLWorkManager { await this.startSyncJob(); } else if (this.mlSearchEnabled && !enabled) { - addLogLine("Disabling MLWorkManager"); + log.info("Disabling MLWorkManager"); this.mlSearchEnabled = false; this.liveSyncQueue.removeAllListeners(); @@ -92,23 +91,23 @@ class MLWorkManager { // Handlers private async appStartHandler() { - addLogLine("appStartHandler"); + log.info("appStartHandler"); try { this.startSyncJob(); } catch (e) { - logError(e, "Failed in ML appStart Handler"); + log.error("Failed in ML appStart Handler", e); } } private async logoutHandler() { - addLogLine("logoutHandler"); + log.info("logoutHandler"); try { this.stopSyncJob(); this.mlSyncJob = undefined; await this.terminateLiveSyncWorker(); await mlIDbStorage.clearMLDB(); } catch (e) { - logError(e, "Failed in ML logout Handler"); + log.error("Failed in ML logout Handler", e); } } @@ -119,9 +118,9 @@ class MLWorkManager { if (!this.mlSearchEnabled) { return; } - addLogLine("fileUploadedHandler: ", arg.enteFile.id); + log.info("fileUploadedHandler: ", arg.enteFile.id); if (arg.enteFile.metadata.fileType !== FILE_TYPE.IMAGE) { - addLogLine("Skipping non image file for local file processing"); + log.info("Skipping non image file for local file processing"); return; } try { @@ -134,7 +133,7 @@ class MLWorkManager { } private async localFilesUpdatedHandler() { - addLogLine("Local files updated"); + log.info("Local files updated"); this.startSyncJob(); } @@ -165,7 +164,7 @@ class MLWorkManager { } private async onLiveSyncIdle() { - addLogLine("Live sync idle"); + log.info("Live sync idle"); await this.terminateLiveSyncWorker(); this.mlSearchEnabled && this.startSyncJob(); } @@ -206,7 +205,7 @@ class MLWorkManager { // TODO: skipping is not required if we are caching chunks through service worker // currently worker chunk itself is not loaded when network is not there if (!navigator.onLine) { - addLogLine( + log.info( "Skipping ml-sync job run as not connected to internet.", ); return { @@ -227,25 +226,25 @@ class MLWorkManager { !!mlSyncResult.error || mlSyncResult.nOutOfSyncFiles < 1, mlSyncResult, }; - addLogLine("ML Sync Job result: ", JSON.stringify(jobResult)); + log.info("ML Sync Job result: ", JSON.stringify(jobResult)); // TODO: redirect/refresh to gallery in case of session_expired, stop ml sync job return jobResult; } catch (e) { - logError(e, "Failed to run MLSync Job"); + log.error("Failed to run MLSync Job", e); } } public async startSyncJob() { try { - addLogLine("MLWorkManager.startSyncJob"); + log.info("MLWorkManager.startSyncJob"); if (!this.mlSearchEnabled) { - addLogLine("ML Search disabled, not starting ml sync job"); + log.info("ML Search disabled, not starting ml sync job"); return; } if (!getToken()) { - addLogLine("User not logged in, not starting ml sync job"); + log.info("User not logged in, not starting ml sync job"); return; } const mlSyncJobConfig = await getMLSyncJobConfig(); @@ -256,17 +255,17 @@ class MLWorkManager { } this.mlSyncJob.start(); } catch (e) { - logError(e, "Failed to start MLSync Job"); + log.error("Failed to start MLSync Job", e); } } public stopSyncJob(terminateWorker: boolean = true) { try { - addLogLine("MLWorkManager.stopSyncJob"); + log.info("MLWorkManager.stopSyncJob"); this.mlSyncJob?.stop(); terminateWorker && this.terminateSyncJobWorker(); } catch (e) { - logError(e, "Failed to stop MLSync Job"); + log.error("Failed to stop MLSync Job", e); } } } diff --git a/web/apps/photos/src/services/machineLearning/mobileFaceNetEmbeddingService.ts b/web/apps/photos/src/services/machineLearning/mobileFaceNetEmbeddingService.ts index 52eabbd8e..455882365 100644 --- a/web/apps/photos/src/services/machineLearning/mobileFaceNetEmbeddingService.ts +++ b/web/apps/photos/src/services/machineLearning/mobileFaceNetEmbeddingService.ts @@ -1,4 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; +import log from "@/next/log"; import * as tf from "@tensorflow/tfjs-core"; import { TFLiteModel } from "@tensorflow/tfjs-tflite"; import { MOBILEFACENET_FACE_SIZE } from "constants/mlConfig"; @@ -37,7 +37,7 @@ class MobileFaceNetEmbeddingService implements FaceEmbeddingService { "/models/mobilefacenet/mobilefacenet.tflite", ); - addLogLine("loaded mobileFaceNetModel: ", tf.getBackend()); + log.info("loaded mobileFaceNetModel: ", tf.getBackend()); } private async getMobileFaceNetModel() { diff --git a/web/apps/photos/src/services/machineLearning/objectService.ts b/web/apps/photos/src/services/machineLearning/objectService.ts index c9eee2887..97d7895a5 100644 --- a/web/apps/photos/src/services/machineLearning/objectService.ts +++ b/web/apps/photos/src/services/machineLearning/objectService.ts @@ -1,4 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; +import log from "@/next/log"; import { DetectedObject, MLSyncContext, @@ -61,7 +61,7 @@ class ObjectService { syncContext.config.sceneDetection.minScore, )), ); - // addLogLine('3 TF Memory stats: ',JSON.stringify(tf.memory())); + // log.info('3 TF Memory stats: ',JSON.stringify(tf.memory())); // TODO: reenable faces filtering based on width const detectedObjects = objectDetections?.map((detection) => { return { @@ -77,13 +77,13 @@ class ObjectService { // ?.filter((f) => // f.box.width > syncContext.config.faceDetection.minFaceSize // ); - addLogLine( + log.info( `object detection time taken ${fileContext.enteFile.id}`, Date.now() - startTime, "ms", ); - addLogLine("[MLService] Detected Objects: ", newMlFile.objects?.length); + log.info("[MLService] Detected Objects: ", newMlFile.objects?.length); } async getAllSyncedObjectsMap(syncContext: MLSyncContext) { @@ -115,9 +115,9 @@ class ObjectService { async syncThingsIndex(syncContext: MLSyncContext) { const filesVersion = await mlIDbStorage.getIndexVersion("files"); - addLogLine("things", await mlIDbStorage.getIndexVersion("things")); + log.info("things", await mlIDbStorage.getIndexVersion("things")); if (filesVersion <= (await mlIDbStorage.getIndexVersion("things"))) { - addLogLine( + log.info( "[MLService] Skipping people index as already synced to latest version", ); return; diff --git a/web/apps/photos/src/services/machineLearning/peopleService.ts b/web/apps/photos/src/services/machineLearning/peopleService.ts index d5a470807..dbd2706bc 100644 --- a/web/apps/photos/src/services/machineLearning/peopleService.ts +++ b/web/apps/photos/src/services/machineLearning/peopleService.ts @@ -1,4 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; +import log from "@/next/log"; import { Face, MLSyncContext, Person } from "types/machineLearning"; import { findFirstIfSorted, @@ -20,7 +20,7 @@ class PeopleService { syncContext.faceClusteringService.method, ) ) { - addLogLine( + log.info( "[MLService] Skipping people index as already synced to latest version", ); return; @@ -84,7 +84,7 @@ class PeopleService { faces.forEach((face) => { face.personId = person.id; }); - // addLogLine("Creating person: ", person, faces); + // log.info("Creating person: ", person, faces); } await mlIDbStorage.updateFaces(allFacesMap); diff --git a/web/apps/photos/src/services/machineLearning/readerService.ts b/web/apps/photos/src/services/machineLearning/readerService.ts index d141cf057..e3c8e95c4 100644 --- a/web/apps/photos/src/services/machineLearning/readerService.ts +++ b/web/apps/photos/src/services/machineLearning/readerService.ts @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { FILE_TYPE } from "constants/file"; import { MLSyncContext, MLSyncFileContext } from "types/machineLearning"; import { @@ -16,7 +16,7 @@ class ReaderService { if (fileContext.imageBitmap) { return fileContext.imageBitmap; } - // addLogLine('1 TF Memory stats: ',JSON.stringify(tf.memory())); + // log.info('1 TF Memory stats: ',JSON.stringify(tf.memory())); if (fileContext.localFile) { if ( fileContext.enteFile.metadata.fileType !== FILE_TYPE.IMAGE @@ -47,11 +47,11 @@ class ReaderService { fileContext.newMlFile.imageSource = syncContext.config.imageSource; const { width, height } = fileContext.imageBitmap; fileContext.newMlFile.imageDimensions = { width, height }; - // addLogLine('2 TF Memory stats: ',JSON.stringify(tf.memory())); + // log.info('2 TF Memory stats: ',JSON.stringify(tf.memory())); return fileContext.imageBitmap; } catch (e) { - logError(e, "failed to create image bitmap"); + log.error("failed to create image bitmap", e); throw e; } } diff --git a/web/apps/photos/src/services/machineLearning/ssdMobileNetV2Service.ts b/web/apps/photos/src/services/machineLearning/ssdMobileNetV2Service.ts index 4adde7707..186656532 100644 --- a/web/apps/photos/src/services/machineLearning/ssdMobileNetV2Service.ts +++ b/web/apps/photos/src/services/machineLearning/ssdMobileNetV2Service.ts @@ -1,3 +1,4 @@ +import log from "@/next/log"; import * as tf from "@tensorflow/tfjs-core"; import { ObjectDetection, @@ -6,7 +7,6 @@ import { Versioned, } from "types/machineLearning"; -import { addLogLine } from "@ente/shared/logging"; import * as SSDMobileNet from "@tensorflow-models/coco-ssd"; import { OBJECT_DETECTION_IMAGE_SIZE } from "constants/mlConfig"; import { resizeToSquare } from "utils/image"; @@ -28,7 +28,7 @@ class SSDMobileNetV2 implements ObjectDetectionService { base: "mobilenet_v2", modelUrl: "/models/ssdmobilenet/model.json", }); - addLogLine("loaded ssdMobileNetV2Model", tf.getBackend()); + log.info("loaded ssdMobileNetV2Model", tf.getBackend()); } private async getSSDMobileNetV2Model() { diff --git a/web/apps/photos/src/services/publicCollectionService.ts b/web/apps/photos/src/services/publicCollectionService.ts index 580382dc4..2cf42254f 100644 --- a/web/apps/photos/src/services/publicCollectionService.ts +++ b/web/apps/photos/src/services/publicCollectionService.ts @@ -1,8 +1,8 @@ +import log from "@/next/log"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import { CustomError, parseSharingErrorCodes } from "@ente/shared/error"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import localForage from "@ente/shared/storage/localForage"; import { Collection, CollectionPublicMagicMetadata } from "types/collection"; import { EncryptedEnteFile, EnteFile } from "types/file"; @@ -223,14 +223,14 @@ export const syncPublicFiles = async ( setPublicFiles([...sortFiles(mergeMetadata(files), sortAsc)]); } catch (e) { const parsedError = parseSharingErrorCodes(e); - logError(e, "failed to sync shared collection files"); + log.error("failed to sync shared collection files", e); if (parsedError.message === CustomError.TOKEN_EXPIRED) { throw e; } } return [...sortFiles(mergeMetadata(files), sortAsc)]; } catch (e) { - logError(e, "failed to get local or sync shared collection files"); + log.error("failed to get local or sync shared collection files", e); throw e; } }; @@ -294,7 +294,7 @@ const getPublicFiles = async ( } while (resp.data.hasMore); return decryptedFiles; } catch (e) { - logError(e, "Get public files failed"); + log.error("Get public files failed", e); throw e; } }; @@ -347,7 +347,7 @@ export const getPublicCollection = async ( await saveReferralCode(referralCode); return [collection, referralCode]; } catch (e) { - logError(e, "failed to get public collection"); + log.error("failed to get public collection", e); throw e; } }; @@ -366,7 +366,7 @@ export const verifyPublicCollectionPassword = async ( const jwtToken = resp.data.jwtToken; return jwtToken; } catch (e) { - logError(e, "failed to verify public collection password"); + log.error("failed to verify public collection password", e); throw e; } }; diff --git a/web/apps/photos/src/services/readerService.ts b/web/apps/photos/src/services/readerService.ts index 04c59cfec..e410144cf 100644 --- a/web/apps/photos/src/services/readerService.ts +++ b/web/apps/photos/src/services/readerService.ts @@ -1,5 +1,5 @@ import { convertBytesToHumanReadable } from "@/next/file"; -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { ElectronFile } from "types/upload"; export async function getUint8ArrayView( @@ -8,9 +8,10 @@ export async function getUint8ArrayView( try { return new Uint8Array(await file.arrayBuffer()); } catch (e) { - logError(e, "reading file blob failed", { - fileSize: convertBytesToHumanReadable(file.size), - }); + log.error( + `Failed to read file blob of size ${convertBytesToHumanReadable(file.size)}`, + e, + ); throw e; } } diff --git a/web/apps/photos/src/services/searchService.ts b/web/apps/photos/src/services/searchService.ts index 0b6d3a5fb..692b4ac84 100644 --- a/web/apps/photos/src/services/searchService.ts +++ b/web/apps/photos/src/services/searchService.ts @@ -1,11 +1,8 @@ -import * as chrono from "chrono-node"; -import { t } from "i18next"; -import { getAllPeople } from "utils/machineLearning"; - +import log from "@/next/log"; import { CustomError } from "@ente/shared/error"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; +import * as chrono from "chrono-node"; import { FILE_TYPE } from "constants/file"; +import { t } from "i18next"; import { Collection } from "types/collection"; import { Model } from "types/embedding"; import { EntityType, LocationTag, LocationTagData } from "types/entity"; @@ -21,6 +18,7 @@ import { } from "types/search"; import ComlinkSearchWorker from "utils/comlink/ComlinkSearchWorker"; import { getUniqueFiles } from "utils/file"; +import { getAllPeople } from "utils/machineLearning"; import { getMLSyncConfig } from "utils/machineLearning/config"; import { getFormattedDate } from "utils/search"; import mlIDbStorage from "utils/storage/mlIDbStorage"; @@ -64,7 +62,7 @@ export const getAutoCompleteSuggestions = return convertSuggestionsToOptions(suggestions); } catch (e) { - logError(e, "getAutoCompleteSuggestions failed"); + log.error("getAutoCompleteSuggestions failed", e); return []; } }; @@ -159,7 +157,7 @@ function getYearSuggestion(searchPhrase: string): Suggestion[] { ]; } } catch (e) { - logError(e, "getYearSuggestion failed"); + log.error("getYearSuggestion failed", e); } } return []; @@ -175,7 +173,7 @@ export async function getAllPeopleSuggestion(): Promise> { hide: true, })); } catch (e) { - logError(e, "getAllPeopleSuggestion failed"); + log.error("getAllPeopleSuggestion failed", e); return []; } } @@ -205,7 +203,7 @@ export async function getIndexStatusSuggestion(): Promise { hide: true, }; } catch (e) { - logError(e, "getIndexStatusSuggestion failed"); + log.error("getIndexStatusSuggestion failed", e); } } @@ -319,7 +317,7 @@ async function getClipSuggestion(searchPhrase: string): Promise { }; } catch (e) { if (!e.message?.includes(CustomError.MODEL_DOWNLOAD_PENDING)) { - logError(e, "getClipSuggestion failed"); + log.error("getClipSuggestion failed", e); } return null; } @@ -383,7 +381,7 @@ async function searchLocationTag(searchPhrase: string): Promise { locationTag.data.name.toLowerCase().includes(searchPhrase), ); if (matchedLocationTags.length > 0) { - addLogLine( + log.info( `Found ${matchedLocationTags.length} location tags for search phrase`, ); } diff --git a/web/apps/photos/src/services/trashService.ts b/web/apps/photos/src/services/trashService.ts index 5137bbdd5..7088bc086 100644 --- a/web/apps/photos/src/services/trashService.ts +++ b/web/apps/photos/src/services/trashService.ts @@ -1,16 +1,14 @@ +import log from "@/next/log"; +import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import localForage from "@ente/shared/storage/localForage"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { Collection } from "types/collection"; -import { SetFiles } from "types/gallery"; -import { decryptFile, sortTrashFiles } from "utils/file"; -import { getCollection } from "./collectionService"; - -import HTTPService from "@ente/shared/network/HTTPService"; import { EnteFile } from "types/file"; +import { SetFiles } from "types/gallery"; import { EncryptedTrashItem, Trash } from "types/trash"; -import { mergeMetadata } from "utils/file"; +import { decryptFile, mergeMetadata, sortTrashFiles } from "utils/file"; +import { getCollection } from "./collectionService"; const TRASH = "file-trash"; const TRASH_TIME = "trash-time"; @@ -135,7 +133,7 @@ export const updateTrash = async ( } while (resp.data.hasMore); return updatedTrash; } catch (e) { - logError(e, "Get trash files failed"); + log.error("Get trash files failed", e); } return currentTrash; }; @@ -170,7 +168,7 @@ export const emptyTrash = async () => { }, ); } catch (e) { - logError(e, "empty trash failed"); + log.error("empty trash failed", e); throw e; } }; diff --git a/web/apps/photos/src/services/typeDetectionService.ts b/web/apps/photos/src/services/typeDetectionService.ts index 4417276fd..5ff8f0169 100644 --- a/web/apps/photos/src/services/typeDetectionService.ts +++ b/web/apps/photos/src/services/typeDetectionService.ts @@ -1,6 +1,5 @@ -import { convertBytesToHumanReadable } from "@/next/file"; +import log from "@/next/log"; import { CustomError } from "@ente/shared/error"; -import { logError } from "@ente/shared/sentry"; import { FILE_TYPE } from "constants/file"; import { KNOWN_NON_MEDIA_FORMATS, @@ -10,7 +9,6 @@ import FileType, { FileTypeResult } from "file-type"; import { ElectronFile, FileTypeInfo } from "types/upload"; import { getFileExtension } from "utils/file"; import { getUint8ArrayView } from "./readerService"; -import { getFileSize } from "./upload/fileService"; const TYPE_VIDEO = "video"; const TYPE_IMAGE = "image"; @@ -51,7 +49,6 @@ export async function getFileType( }; } catch (e) { const fileFormat = getFileExtension(receivedFile.name); - const fileSize = convertBytesToHumanReadable(getFileSize(receivedFile)); const whiteListedFormat = WHITELISTED_FILE_FORMATS.find( (a) => a.exactType === fileFormat, ); @@ -62,16 +59,10 @@ export async function getFileType( throw Error(CustomError.UNSUPPORTED_FILE_FORMAT); } if (e.message === CustomError.NON_MEDIA_FILE) { - logError(e, "unsupported file format", { - fileFormat, - fileSize, - }); + log.error(`unsupported file format ${fileFormat}`, e); throw Error(CustomError.UNSUPPORTED_FILE_FORMAT); } - logError(e, "type detection failed", { - fileFormat, - fileSize, - }); + log.error(`type detection failed for format ${fileFormat}`, e); throw Error(CustomError.TYPE_DETECTION_FAILED(fileFormat)); } } diff --git a/web/apps/photos/src/services/updateCreationTimeWithExif.ts b/web/apps/photos/src/services/updateCreationTimeWithExif.ts index a24ba90cf..667ae44f4 100644 --- a/web/apps/photos/src/services/updateCreationTimeWithExif.ts +++ b/web/apps/photos/src/services/updateCreationTimeWithExif.ts @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { validateAndGetCreationUnixTimeInMicroSeconds } from "@ente/shared/time"; import type { FixOption } from "components/FixCreationTime"; import { FILE_TYPE } from "constants/file"; @@ -88,7 +88,7 @@ export async function updateCreationTimeWithExif( updateExistingFilePubMetadata(file, updatedFile); } } catch (e) { - logError(e, "failed to updated a CreationTime With Exif"); + log.error("failed to updated a CreationTime With Exif", e); completedWithError = true; } finally { setProgressTracker({ @@ -98,7 +98,7 @@ export async function updateCreationTimeWithExif( } } } catch (e) { - logError(e, "update CreationTime With Exif failed"); + log.error("update CreationTime With Exif failed", e); completedWithError = true; } return completedWithError; diff --git a/web/apps/photos/src/services/upload/exifService.ts b/web/apps/photos/src/services/upload/exifService.ts index 7fffb473b..a26075b3a 100644 --- a/web/apps/photos/src/services/upload/exifService.ts +++ b/web/apps/photos/src/services/upload/exifService.ts @@ -1,5 +1,5 @@ +import log from "@/next/log"; import { CustomError } from "@ente/shared/error"; -import { logError } from "@ente/shared/sentry"; import { validateAndGetCreationUnixTimeInMicroSeconds } from "@ente/shared/time"; import { EXIFLESS_FORMATS, NULL_LOCATION } from "constants/upload"; import exifr from "exifr"; @@ -67,13 +67,15 @@ export async function getParsedExifData( return parseExifData(filteredExifData); } catch (e) { if (e.message === EXIFR_UNSUPPORTED_FILE_FORMAT_MESSAGE) { - logError(e, "exif library unsupported format", { - fileType: fileTypeInfo.exactType, - }); + log.error( + `exif library unsupported format ${fileTypeInfo.exactType}`, + e, + ); } else { - logError(e, "get parsed exif data failed", { - fileType: fileTypeInfo.exactType, - }); + log.error( + `get parsed exif data failed for file type ${fileTypeInfo.exactType}`, + e, + ); throw e; } } @@ -128,13 +130,13 @@ function parseExifData(exifData: RawEXIFData): ParsedEXIFData { parsedExif.imageWidth = ImageWidth; parsedExif.imageHeight = ImageHeight; } else { - logError( - new Error("ImageWidth or ImageHeight is not a number"), - "Image dimension parsing failed", - { - ImageWidth, - ImageHeight, - }, + log.error( + `Image dimension parsing failed - ImageWidth or ImageHeight is not a number ${JSON.stringify( + { + ImageWidth, + ImageHeight, + }, + )}`, ); } } else if (ExifImageWidth && ExifImageHeight) { @@ -145,13 +147,13 @@ function parseExifData(exifData: RawEXIFData): ParsedEXIFData { parsedExif.imageWidth = ExifImageWidth; parsedExif.imageHeight = ExifImageHeight; } else { - logError( - new Error("ExifImageWidth or ExifImageHeight is not a number"), - "Image dimension parsing failed", - { - ExifImageWidth, - ExifImageHeight, - }, + log.error( + `Image dimension parsing failed - ExifImageWidth or ExifImageHeight is not a number ${JSON.stringify( + { + ExifImageWidth, + ExifImageHeight, + }, + )}`, ); } } else if (PixelXDimension && PixelYDimension) { @@ -162,13 +164,13 @@ function parseExifData(exifData: RawEXIFData): ParsedEXIFData { parsedExif.imageWidth = PixelXDimension; parsedExif.imageHeight = PixelYDimension; } else { - logError( - new Error("PixelXDimension or PixelYDimension is not a number"), - "Image dimension parsing failed", - { - PixelXDimension, - PixelYDimension, - }, + log.error( + `Image dimension parsing failed - PixelXDimension or PixelYDimension is not a number ${JSON.stringify( + { + PixelXDimension, + PixelYDimension, + }, + )}`, ); } } @@ -229,9 +231,7 @@ function parseEXIFDate(dateTimeString: string) { } return date; } catch (e) { - logError(e, "parseEXIFDate failed", { - dateTimeString, - }); + log.error(`Failed to parseEXIFDate ${dateTimeString}`, e); return null; } } @@ -265,12 +265,15 @@ export function parseEXIFLocation( ); return { latitude, longitude }; } catch (e) { - logError(e, "parseEXIFLocation failed", { - gpsLatitude, - gpsLatitudeRef, - gpsLongitude, - gpsLongitudeRef, - }); + log.error( + `Failed to parseEXIFLocation ${JSON.stringify({ + gpsLatitude, + gpsLatitudeRef, + gpsLongitude, + gpsLongitudeRef, + })}`, + e, + ); return NULL_LOCATION; } } @@ -330,7 +333,7 @@ export async function updateFileCreationDateInEXIF( const exifInsertedFile = piexif.insert(exifBytes, imageDataURL); return dataURIToBlob(exifInsertedFile); } catch (e) { - logError(e, "updateFileModifyDateInEXIF failed"); + log.error("updateFileModifyDateInEXIF failed", e); return fileBlob; } } diff --git a/web/apps/photos/src/services/upload/fileService.ts b/web/apps/photos/src/services/upload/fileService.ts index b7c4dff3d..dacccdccb 100644 --- a/web/apps/photos/src/services/upload/fileService.ts +++ b/web/apps/photos/src/services/upload/fileService.ts @@ -1,7 +1,9 @@ import { getFileNameSize } from "@/next/file"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; +import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker"; +import { Remote } from "comlink"; import { FILE_READER_CHUNK_SIZE, MULTIPART_PART_SIZE } from "constants/upload"; +import { EncryptedMagicMetadata } from "types/magicMetadata"; import { DataStream, ElectronFile, @@ -13,10 +15,6 @@ import { ParsedMetadataJSON, ParsedMetadataJSONMap, } from "types/upload"; - -import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker"; -import { Remote } from "comlink"; -import { EncryptedMagicMetadata } from "types/magicMetadata"; import { getElectronFileStream, getFileStream, @@ -47,7 +45,7 @@ export async function readFile( rawFile, fileTypeInfo, ); - addLogLine(`reading file data ${getFileNameSize(rawFile)} `); + log.info(`reading file data ${getFileNameSize(rawFile)} `); let filedata: Uint8Array | DataStream; if (!(rawFile instanceof File)) { if (rawFile.size > MULTIPART_PART_SIZE) { @@ -64,7 +62,7 @@ export async function readFile( filedata = await getUint8ArrayView(rawFile); } - addLogLine(`read file data successfully ${getFileNameSize(rawFile)} `); + log.info(`read file data successfully ${getFileNameSize(rawFile)} `); return { filedata, @@ -152,7 +150,7 @@ export async function encryptFile( }; return result; } catch (e) { - logError(e, "Error encrypting files"); + log.error("Error encrypting files", e); throw e; } } diff --git a/web/apps/photos/src/services/upload/hashService.tsx b/web/apps/photos/src/services/upload/hashService.tsx index 623bf8609..aa275fb34 100644 --- a/web/apps/photos/src/services/upload/hashService.tsx +++ b/web/apps/photos/src/services/upload/hashService.tsx @@ -1,8 +1,7 @@ import { getFileNameSize } from "@/next/file"; +import log from "@/next/log"; import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker"; import { CustomError } from "@ente/shared/error"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; import { Remote } from "comlink"; import { FILE_READER_CHUNK_SIZE } from "constants/upload"; import { getElectronFileStream, getFileStream } from "services/readerService"; @@ -13,7 +12,7 @@ export async function getFileHash( file: File | ElectronFile, ) { try { - addLogLine(`getFileHash called for ${getFileNameSize(file)}`); + log.info(`getFileHash called for ${getFileNameSize(file)}`); let filedata: DataStream; if (file instanceof File) { filedata = getFileStream(file, FILE_READER_CHUNK_SIZE); @@ -38,14 +37,12 @@ export async function getFileHash( throw Error(CustomError.CHUNK_MORE_THAN_EXPECTED); } const hash = await worker.completeChunkHashing(hashState); - addLogLine( + log.info( `file hashing completed successfully ${getFileNameSize(file)}`, ); return hash; } catch (e) { - logError(e, "getFileHash failed"); - addLogLine( - `file hashing failed ${getFileNameSize(file)} ,${e.message} `, - ); + log.error("getFileHash failed", e); + log.info(`file hashing failed ${getFileNameSize(file)} ,${e.message} `); } } diff --git a/web/apps/photos/src/services/upload/livePhotoService.ts b/web/apps/photos/src/services/upload/livePhotoService.ts index 52fbc93d8..392b5b9c8 100644 --- a/web/apps/photos/src/services/upload/livePhotoService.ts +++ b/web/apps/photos/src/services/upload/livePhotoService.ts @@ -1,6 +1,6 @@ +import log from "@/next/log"; import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker"; import { CustomError } from "@ente/shared/error"; -import { logError } from "@ente/shared/sentry"; import { Remote } from "comlink"; import { FILE_TYPE } from "constants/file"; import { LIVE_PHOTO_ASSET_SIZE_LIMIT } from "constants/upload"; @@ -213,7 +213,7 @@ export async function clusterLivePhotoFiles(mediaFiles: FileWithCollection[]) { if (e.message === CustomError.UPLOAD_CANCELLED) { throw e; } else { - logError(e, "failed to cluster live photo"); + log.error("failed to cluster live photo", e); throw e; } } @@ -265,15 +265,13 @@ function areFilesLivePhotoAssets( ) { return true; } else { - logError( - new Error(CustomError.TOO_LARGE_LIVE_PHOTO_ASSETS), - CustomError.TOO_LARGE_LIVE_PHOTO_ASSETS, - { + log.error( + `${CustomError.TOO_LARGE_LIVE_PHOTO_ASSETS} - ${JSON.stringify({ fileSizes: [ firstFileIdentifier.size, secondFileIdentifier.size, ], - }, + })}`, ); } } diff --git a/web/apps/photos/src/services/upload/metadataService.ts b/web/apps/photos/src/services/upload/metadataService.ts index f51ca15c2..9bd2a63c0 100644 --- a/web/apps/photos/src/services/upload/metadataService.ts +++ b/web/apps/photos/src/services/upload/metadataService.ts @@ -1,5 +1,5 @@ +import log from "@/next/log"; import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker"; -import { logError } from "@ente/shared/sentry"; import { parseDateFromFusedDateString, tryToParseDateTime, @@ -109,7 +109,7 @@ export async function getImageMetadata( height: exifData?.imageHeight ?? null, }; } catch (e) { - logError(e, "getExifData failed"); + log.error("getExifData failed", e); } return imageMetadata; } @@ -206,7 +206,7 @@ export async function parseMetadataJSON(receivedFile: File | ElectronFile) { } return parsedMetadataJSON; } catch (e) { - logError(e, "parseMetadataJSON failed"); + log.error("parseMetadataJSON failed", e); // ignore } } @@ -237,7 +237,7 @@ export function extractDateFromFileName(filename: string): number { } return validateAndGetCreationUnixTimeInMicroSeconds(parsedDate); } catch (e) { - logError(e, "failed to extract date From FileName "); + log.error("failed to extract date From FileName ", e); return null; } } @@ -250,7 +250,7 @@ function convertSignalNameToFusedDateString(filename: string) { const EDITED_FILE_SUFFIX = "-edited"; /* - Get the original file name for edited file to associate it to original file's metadataJSON file + Get the original file name for edited file to associate it to original file's metadataJSON file as edited file doesn't have their own metadata file */ function getFileOriginalName(fileName: string) { diff --git a/web/apps/photos/src/services/upload/publicUploadHttpClient.ts b/web/apps/photos/src/services/upload/publicUploadHttpClient.ts index 3144d7893..f7d87c51c 100644 --- a/web/apps/photos/src/services/upload/publicUploadHttpClient.ts +++ b/web/apps/photos/src/services/upload/publicUploadHttpClient.ts @@ -1,7 +1,7 @@ +import log from "@/next/log"; import { CustomError, handleUploadError } from "@ente/shared/error"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import { EnteFile } from "types/file"; import { MultipartUploadURLs, UploadFile, UploadURL } from "types/upload"; import { retryHTTPCall } from "utils/upload/uploadRetrier"; @@ -39,7 +39,7 @@ class PublicUploadHttpClient { ); return response.data; } catch (e) { - logError(e, "upload public File Failed"); + log.error("upload public File Failed", e); throw e; } } @@ -78,7 +78,7 @@ class PublicUploadHttpClient { } return this.uploadURLFetchInProgress; } catch (e) { - logError(e, "fetch public upload-url failed "); + log.error("fetch public upload-url failed ", e); throw e; } } @@ -107,7 +107,7 @@ class PublicUploadHttpClient { return response.data["urls"]; } catch (e) { - logError(e, "fetch public multipart-upload-url failed"); + log.error("fetch public multipart-upload-url failed", e); throw e; } } diff --git a/web/apps/photos/src/services/upload/thumbnailService.ts b/web/apps/photos/src/services/upload/thumbnailService.ts index 4c39d36ab..071ef3078 100644 --- a/web/apps/photos/src/services/upload/thumbnailService.ts +++ b/web/apps/photos/src/services/upload/thumbnailService.ts @@ -1,8 +1,7 @@ -import ElectronAPIs from "@/next/electron"; +import { ensureElectron } from "@/next/electron"; import { convertBytesToHumanReadable, getFileNameSize } from "@/next/file"; +import log from "@/next/log"; import { CustomError } from "@ente/shared/error"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; import { FILE_TYPE } from "constants/file"; import { BLACK_THUMBNAIL_BASE64 } from "constants/upload"; import isElectron from "is-electron"; @@ -30,7 +29,7 @@ export async function generateThumbnail( fileTypeInfo: FileTypeInfo, ): Promise<{ thumbnail: Uint8Array; hasStaticThumbnail: boolean }> { try { - addLogLine(`generating thumbnail for ${getFileNameSize(file)}`); + log.info(`generating thumbnail for ${getFileNameSize(file)}`); let hasStaticThumbnail = false; let thumbnail: Uint8Array; try { @@ -40,32 +39,26 @@ export async function generateThumbnail( thumbnail = await generateVideoThumbnail(file, fileTypeInfo); } if (thumbnail.length > 1.5 * MAX_THUMBNAIL_SIZE) { - logError( - Error("thumbnail_too_large"), - "thumbnail greater than max limit", - { + log.error( + `thumbnail greater than max limit - ${JSON.stringify({ thumbnailSize: convertBytesToHumanReadable( thumbnail.length, ), fileSize: convertBytesToHumanReadable(file.size), fileType: fileTypeInfo.exactType, - }, + })}`, ); } if (thumbnail.length === 0) { throw Error("EMPTY THUMBNAIL"); } - addLogLine( + log.info( `thumbnail successfully generated ${getFileNameSize(file)}`, ); } catch (e) { - logError(e, "uploading static thumbnail", { - fileFormat: fileTypeInfo.exactType, - }); - addLogLine( - `thumbnail generation failed ${getFileNameSize(file)} error: ${ - e.message - }`, + log.error( + `thumbnail generation failed ${getFileNameSize(file)} with format ${fileTypeInfo.exactType}`, + e, ); thumbnail = Uint8Array.from(atob(BLACK_THUMBNAIL_BASE64), (c) => c.charCodeAt(0), @@ -74,7 +67,7 @@ export async function generateThumbnail( } return { thumbnail, hasStaticThumbnail }; } catch (e) { - logError(e, "Error generating static thumbnail"); + log.error("Error generating static thumbnail", e); throw e; } } @@ -105,12 +98,12 @@ const generateImageThumbnailInElectron = async ( ): Promise => { try { const startTime = Date.now(); - const thumb = await ElectronAPIs.generateImageThumbnail( + const thumb = await ensureElectron().generateImageThumbnail( inputFile, maxDimension, maxSize, ); - addLogLine( + log.info( `originalFileSize:${convertBytesToHumanReadable( inputFile?.size, )},thumbFileSize:${convertBytesToHumanReadable( @@ -125,7 +118,7 @@ const generateImageThumbnailInElectron = async ( e.message !== CustomError.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED ) { - logError(e, "failed to generate image thumbnail natively"); + log.error("failed to generate image thumbnail natively", e); } throw e; } @@ -142,12 +135,12 @@ export async function generateImageThumbnailUsingCanvas( let timeout = null; const isHEIC = isFileHEIC(fileTypeInfo.exactType); if (isHEIC) { - addLogLine(`HEICConverter called for ${getFileNameSize(file)}`); + log.info(`HEICConverter called for ${getFileNameSize(file)}`); const convertedBlob = await HeicConversionService.convert( new Blob([await file.arrayBuffer()]), ); file = new File([convertedBlob], file.name); - addLogLine(`${getFileNameSize(file)} successfully converted`); + log.info(`${getFileNameSize(file)} successfully converted`); } let image = new Image(); imageURL = URL.createObjectURL(new Blob([await file.arrayBuffer()])); @@ -198,24 +191,25 @@ async function generateVideoThumbnail( ) { let thumbnail: Uint8Array; try { - addLogLine( + log.info( `ffmpeg generateThumbnail called for ${getFileNameSize(file)}`, ); const thumbnail = await FFmpegService.generateVideoThumbnail(file); - addLogLine( + log.info( `ffmpeg thumbnail successfully generated ${getFileNameSize(file)}`, ); return await getUint8ArrayView(thumbnail); } catch (e) { - addLogLine( + log.info( `ffmpeg thumbnail generated failed ${getFileNameSize( file, )} error: ${e.message}`, ); - logError(e, "failed to generate thumbnail using ffmpeg", { - fileFormat: fileTypeInfo.exactType, - }); + log.error( + `failed to generate thumbnail using ffmpeg for format ${fileTypeInfo.exactType}`, + e, + ); thumbnail = await generateVideoThumbnailUsingCanvas(file); } return thumbnail; @@ -265,7 +259,7 @@ export async function generateVideoThumbnailUsingCanvas( const err = Error( `${CustomError.THUMBNAIL_GENERATION_FAILED} err: ${e}`, ); - logError(e, CustomError.THUMBNAIL_GENERATION_FAILED); + log.error(CustomError.THUMBNAIL_GENERATION_FAILED, e); reject(err); } }); diff --git a/web/apps/photos/src/services/upload/uploadHttpClient.ts b/web/apps/photos/src/services/upload/uploadHttpClient.ts index 3855562dd..7ba35dc0d 100644 --- a/web/apps/photos/src/services/upload/uploadHttpClient.ts +++ b/web/apps/photos/src/services/upload/uploadHttpClient.ts @@ -1,7 +1,7 @@ +import log from "@/next/log"; import { CustomError, handleUploadError } from "@ente/shared/error"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint, getUploadEndpoint } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { EnteFile } from "types/file"; import { MultipartUploadURLs, UploadFile, UploadURL } from "types/upload"; @@ -30,7 +30,7 @@ class UploadHttpClient { ); return response.data; } catch (e) { - logError(e, "upload Files Failed"); + log.error("upload Files Failed", e); throw e; } } @@ -60,7 +60,7 @@ class UploadHttpClient { } return this.uploadURLFetchInProgress; } catch (e) { - logError(e, "fetch upload-url failed "); + log.error("fetch upload-url failed ", e); throw e; } } @@ -83,7 +83,7 @@ class UploadHttpClient { return response.data["urls"]; } catch (e) { - logError(e, "fetch multipart-upload-url failed"); + log.error("fetch multipart-upload-url failed", e); throw e; } } @@ -108,7 +108,7 @@ class UploadHttpClient { return fileUploadURL.objectKey; } catch (e) { if (e.message !== CustomError.UPLOAD_CANCELLED) { - logError(e, "putFile to dataStore failed "); + log.error("putFile to dataStore failed ", e); } throw e; } @@ -134,7 +134,7 @@ class UploadHttpClient { return fileUploadURL.objectKey; } catch (e) { if (e.message !== CustomError.UPLOAD_CANCELLED) { - logError(e, "putFile to dataStore failed "); + log.error("putFile to dataStore failed ", e); } throw e; } @@ -156,7 +156,7 @@ class UploadHttpClient { ); if (!resp?.headers?.etag) { const err = Error(CustomError.ETAG_MISSING); - logError(err, "putFile in parts failed"); + log.error("putFile in parts failed", err); throw err; } return resp; @@ -164,7 +164,7 @@ class UploadHttpClient { return response.headers.etag as string; } catch (e) { if (e.message !== CustomError.UPLOAD_CANCELLED) { - logError(e, "put filePart failed"); + log.error("put filePart failed", e); } throw e; } @@ -188,7 +188,7 @@ class UploadHttpClient { ); if (!resp?.data?.etag) { const err = Error(CustomError.ETAG_MISSING); - logError(err, "putFile in parts failed"); + log.error("putFile in parts failed", err); throw err; } return resp; @@ -196,7 +196,7 @@ class UploadHttpClient { return response.data.etag as string; } catch (e) { if (e.message !== CustomError.UPLOAD_CANCELLED) { - logError(e, "put filePart failed"); + log.error("put filePart failed", e); } throw e; } @@ -210,7 +210,7 @@ class UploadHttpClient { }), ); } catch (e) { - logError(e, "put file in parts failed"); + log.error("put file in parts failed", e); throw e; } } @@ -229,7 +229,7 @@ class UploadHttpClient { ), ); } catch (e) { - logError(e, "put file in parts failed"); + log.error("put file in parts failed", e); throw e; } } diff --git a/web/apps/photos/src/services/upload/uploadManager.ts b/web/apps/photos/src/services/upload/uploadManager.ts index ec9163201..82b761091 100644 --- a/web/apps/photos/src/services/upload/uploadManager.ts +++ b/web/apps/photos/src/services/upload/uploadManager.ts @@ -1,34 +1,10 @@ -import { CustomError } from "@ente/shared/error"; -import { Events, eventBus } from "@ente/shared/events"; -import { logError } from "@ente/shared/sentry"; -import { Collection } from "types/collection"; -import { EncryptedEnteFile, EnteFile } from "types/file"; -import { SetFiles } from "types/gallery"; -import { - FileWithCollection, - ParsedMetadataJSON, - ParsedMetadataJSONMap, - PublicUploadProps, -} from "types/upload"; -import { decryptFile, getUserOwnedFiles, sortFiles } from "utils/file"; -import { - areFileWithCollectionsSame, - segregateMetadataAndMediaFiles, -} from "utils/upload"; -import { getLocalFiles } from "../fileService"; -import { - getMetadataJSONMapKeyForJSON, - parseMetadataJSON, -} from "./metadataService"; -import UIService from "./uiService"; -import UploadService from "./uploadService"; -import uploader from "./uploader"; - import { getFileNameSize } from "@/next/file"; +import log from "@/next/log"; import { ComlinkWorker } from "@/next/worker/comlink-worker"; import { getDedicatedCryptoWorker } from "@ente/shared/crypto"; import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker"; -import { addLogLine } from "@ente/shared/logging"; +import { CustomError } from "@ente/shared/error"; +import { Events, eventBus } from "@ente/shared/events"; import { Remote } from "comlink"; import { UPLOAD_RESULT, UPLOAD_STAGES } from "constants/upload"; import isElectron from "is-electron"; @@ -39,9 +15,30 @@ import { } from "services/publicCollectionService"; import { getDisableCFUploadProxyFlag } from "services/userService"; import watchFolderService from "services/watchFolder/watchFolderService"; +import { Collection } from "types/collection"; +import { EncryptedEnteFile, EnteFile } from "types/file"; +import { SetFiles } from "types/gallery"; +import { + FileWithCollection, + ParsedMetadataJSON, + ParsedMetadataJSONMap, + PublicUploadProps, +} from "types/upload"; import { ProgressUpdater } from "types/upload/ui"; -import uiService from "./uiService"; +import { decryptFile, getUserOwnedFiles, sortFiles } from "utils/file"; +import { + areFileWithCollectionsSame, + segregateMetadataAndMediaFiles, +} from "utils/upload"; +import { getLocalFiles } from "../fileService"; +import { + getMetadataJSONMapKeyForJSON, + parseMetadataJSON, +} from "./metadataService"; +import { default as UIService, default as uiService } from "./uiService"; import uploadCancelService from "./uploadCancelService"; +import UploadService from "./uploadService"; +import uploader from "./uploader"; const MAX_CONCURRENT_UPLOADS = 4; @@ -126,7 +123,7 @@ class UploadManager { this.uploadInProgress = true; await this.updateExistingFilesAndCollections(collections); this.uploaderName = uploaderName; - addLogLine( + log.info( `received ${filesWithCollectionToUploadIn.length} files to upload`, ); uiService.setFilenames( @@ -139,8 +136,8 @@ class UploadManager { ); const { metadataJSONFiles, mediaFiles } = segregateMetadataAndMediaFiles(filesWithCollectionToUploadIn); - addLogLine(`has ${metadataJSONFiles.length} metadata json files`); - addLogLine(`has ${mediaFiles.length} media files`); + log.info(`has ${metadataJSONFiles.length} metadata json files`); + log.info(`has ${mediaFiles.length} media files`); if (metadataJSONFiles.length) { UIService.setUploadStage( UPLOAD_STAGES.READING_GOOGLE_METADATA_FILES, @@ -152,11 +149,11 @@ class UploadManager { ); } if (mediaFiles.length) { - addLogLine(`clusterLivePhotoFiles started`); + log.info(`clusterLivePhotoFiles started`); const analysedMediaFiles = await UploadService.clusterLivePhotoFiles(mediaFiles); - addLogLine(`clusterLivePhotoFiles ended`); - addLogLine( + log.info(`clusterLivePhotoFiles ended`); + log.info( `got live photos: ${ mediaFiles.length !== analysedMediaFiles.length }`, @@ -183,7 +180,7 @@ class UploadManager { await ImportService.cancelRemainingUploads(); } } else { - logError(e, "uploading failed with error"); + log.error("uploading failed with error", e); throw e; } } finally { @@ -200,14 +197,14 @@ class UploadManager { return false; } } catch (e) { - logError(e, " failed to return shouldCloseProgressBar"); + log.error(" failed to return shouldCloseProgressBar", e); return false; } } private async parseMetadataJSONFiles(metadataFiles: FileWithCollection[]) { try { - addLogLine(`parseMetadataJSONFiles function executed `); + log.info(`parseMetadataJSONFiles function executed `); UIService.reset(metadataFiles.length); @@ -216,7 +213,7 @@ class UploadManager { if (uploadCancelService.isUploadCancelationRequested()) { throw Error(CustomError.UPLOAD_CANCELLED); } - addLogLine( + log.info( `parsing metadata json file ${getFileNameSize(file)}`, ); @@ -231,7 +228,7 @@ class UploadManager { ); UIService.increaseFileUploaded(); } - addLogLine( + log.info( `successfully parsed metadata json file ${getFileNameSize( file, )}`, @@ -241,8 +238,8 @@ class UploadManager { throw e; } else { // and don't break for subsequent files just log and move on - logError(e, "parsing failed for a file"); - addLogLine( + log.error("parsing failed for a file", e); + log.info( `failed to parse metadata json file ${getFileNameSize( file, )} error: ${e.message}`, @@ -252,14 +249,14 @@ class UploadManager { } } catch (e) { if (e.message !== CustomError.UPLOAD_CANCELLED) { - logError(e, "error seeding MetadataMap"); + log.error("error seeding MetadataMap", e); } throw e; } } private async uploadMediaFiles(mediaFiles: FileWithCollection[]) { - addLogLine(`uploadMediaFiles called`); + log.info(`uploadMediaFiles called`); this.filesToBeUploaded = [...this.filesToBeUploaded, ...mediaFiles]; if (isElectron()) { @@ -323,7 +320,7 @@ class UploadManager { ) { try { let decryptedFile: EnteFile; - addLogLine( + log.info( `post upload action -> fileUploadResult: ${fileUploadResult} uploadedFile present ${!!uploadedFile}`, ); await this.updateElectronRemainingFiles(fileWithCollection); @@ -368,7 +365,7 @@ class UploadManager { fileWithCollection.livePhotoAssets.image, }); } catch (e) { - logError(e, "Error in fileUploaded handlers"); + log.error("Error in fileUploaded handlers", e); } this.updateExistingFiles(decryptedFile); } @@ -379,7 +376,7 @@ class UploadManager { ); return fileUploadResult; } catch (e) { - logError(e, "failed to do post file upload action"); + log.error("failed to do post file upload action", e); return UPLOAD_RESULT.FAILED; } } @@ -399,7 +396,7 @@ class UploadManager { } public cancelRunningUpload() { - addLogLine("user cancelled running upload"); + log.info("user cancelled running upload"); UIService.setUploadStage(UPLOAD_STAGES.CANCELLING); uploadCancelService.requestUploadCancelation(); } diff --git a/web/apps/photos/src/services/upload/uploadService.ts b/web/apps/photos/src/services/upload/uploadService.ts index 0228bc541..95e4752a7 100644 --- a/web/apps/photos/src/services/upload/uploadService.ts +++ b/web/apps/photos/src/services/upload/uploadService.ts @@ -1,7 +1,7 @@ +import log from "@/next/log"; import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker"; import { B64EncryptionResult } from "@ente/shared/crypto/types"; import { CustomError, handleUploadError } from "@ente/shared/error"; -import { logError } from "@ente/shared/sentry"; import { Remote } from "comlink"; import { Collection } from "types/collection"; import { FilePublicMagicMetadataProps } from "types/file"; @@ -231,7 +231,7 @@ class UploadService { return backupedFile; } catch (e) { if (e.message !== CustomError.UPLOAD_CANCELLED) { - logError(e, "error uploading to bucket"); + log.error("error uploading to bucket", e); } throw e; } @@ -264,7 +264,7 @@ class UploadService { await this.fetchUploadURLs(); // checking for any subscription related errors } catch (e) { - logError(e, "prefetch uploadURL failed"); + log.error("prefetch uploadURL failed", e); handleUploadError(e); } } diff --git a/web/apps/photos/src/services/upload/videoMetadataService.ts b/web/apps/photos/src/services/upload/videoMetadataService.ts index e687c5199..947bd538c 100644 --- a/web/apps/photos/src/services/upload/videoMetadataService.ts +++ b/web/apps/photos/src/services/upload/videoMetadataService.ts @@ -1,6 +1,5 @@ import { getFileNameSize } from "@/next/file"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { NULL_EXTRACTED_METADATA } from "constants/upload"; import * as ffmpegService from "services/ffmpeg/ffmpegService"; import { ElectronFile } from "types/upload"; @@ -8,14 +7,14 @@ import { ElectronFile } from "types/upload"; export async function getVideoMetadata(file: File | ElectronFile) { let videoMetadata = NULL_EXTRACTED_METADATA; try { - addLogLine(`getVideoMetadata called for ${getFileNameSize(file)}`); + log.info(`getVideoMetadata called for ${getFileNameSize(file)}`); videoMetadata = await ffmpegService.extractVideoMetadata(file); - addLogLine( + log.info( `videoMetadata successfully extracted ${getFileNameSize(file)}`, ); } catch (e) { - logError(e, "failed to get video metadata"); - addLogLine( + log.error("failed to get video metadata", e); + log.info( `videoMetadata extracted failed ${getFileNameSize(file)} ,${ e.message } `, diff --git a/web/apps/photos/src/services/userService.ts b/web/apps/photos/src/services/userService.ts index 6fbbaa1bd..95b1b95c9 100644 --- a/web/apps/photos/src/services/userService.ts +++ b/web/apps/photos/src/services/userService.ts @@ -1,10 +1,10 @@ +import log from "@/next/log"; import { putAttributes } from "@ente/accounts/api/user"; import { logoutUser } from "@ente/accounts/services/user"; import { getRecoveryKey } from "@ente/shared/crypto/helpers"; import { ApiError } from "@ente/shared/error"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint, getFamilyPortalURL } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import localForage from "@ente/shared/storage/localForage"; import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; import { @@ -63,7 +63,7 @@ export const getFamiliesToken = async () => { ); return resp.data["familiesToken"]; } catch (e) { - logError(e, "failed to get family token"); + log.error("failed to get family token", e); throw e; } }; @@ -81,7 +81,7 @@ export const getAccountsToken = async () => { ); return resp.data["accountsToken"]; } catch (e) { - logError(e, "failed to get accounts token"); + log.error("failed to get accounts token", e); throw e; } }; @@ -99,7 +99,7 @@ export const getRoadmapRedirectURL = async () => { ); return resp.data["url"]; } catch (e) { - logError(e, "failed to get roadmap url"); + log.error("failed to get roadmap url", e); throw e; } }; @@ -128,15 +128,15 @@ export const isTokenValid = async (token: string) => { getData(LS_KEYS.ORIGINAL_KEY_ATTRIBUTES), ); } catch (e) { - logError(e, "put attribute failed"); + log.error("put attribute failed", e); } } } catch (e) { - logError(e, "hasSetKeys not set in session validity response"); + log.error("hasSetKeys not set in session validity response", e); } return true; } catch (e) { - logError(e, "session-validity api call failed"); + log.error("session-validity api call failed", e); if ( e instanceof ApiError && e.httpStatusCode === HttpStatusCode.Unauthorized @@ -172,7 +172,7 @@ export const getUserDetailsV2 = async (): Promise => { ); return resp.data; } catch (e) { - logError(e, "failed to get user details v2"); + log.error("failed to get user details v2", e); throw e; } }; @@ -185,7 +185,7 @@ export const getFamilyPortalRedirectURL = async () => { window.location.origin }/gallery`; } catch (e) { - logError(e, "unable to generate to family portal URL"); + log.error("unable to generate to family portal URL", e); throw e; } }; @@ -203,7 +203,7 @@ export const getAccountDeleteChallenge = async () => { ); return resp.data as DeleteChallengeResponse; } catch (e) { - logError(e, "failed to get account delete challenge"); + log.error("failed to get account delete challenge", e); throw e; } }; @@ -228,7 +228,7 @@ export const deleteAccount = async ( }, ); } catch (e) { - logError(e, "deleteAccount api call failed"); + log.error("deleteAccount api call failed", e); throw e; } }; @@ -262,7 +262,7 @@ export const getFaceSearchEnabledStatus = async () => { ); return resp.data.value === "true"; } catch (e) { - logError(e, "failed to get face search enabled status"); + log.error("failed to get face search enabled status", e); throw e; } }; @@ -282,7 +282,7 @@ export const updateFaceSearchEnabledStatus = async (newStatus: boolean) => { }, ); } catch (e) { - logError(e, "failed to update face search enabled status"); + log.error("failed to update face search enabled status", e); throw e; } }; @@ -292,7 +292,7 @@ export const syncMapEnabled = async () => { const status = await getMapEnabledStatus(); setLocalMapEnabled(status); } catch (e) { - logError(e, "failed to sync map enabled status"); + log.error("failed to sync map enabled status", e); throw e; } }; @@ -313,7 +313,7 @@ export const getMapEnabledStatus = async () => { ); return resp.data.value === "true"; } catch (e) { - logError(e, "failed to get map enabled status"); + log.error("failed to get map enabled status", e); throw e; } }; @@ -333,7 +333,7 @@ export const updateMapEnabledStatus = async (newStatus: boolean) => { }, ); } catch (e) { - logError(e, "failed to update map enabled status"); + log.error("failed to update map enabled status", e); throw e; } }; @@ -363,7 +363,7 @@ export async function getDisableCFUploadProxyFlag(): Promise { ).json() as GetFeatureFlagResponse; return featureFlags.disableCFUploadProxy; } catch (e) { - logError(e, "failed to get feature flags"); + log.error("failed to get feature flags", e); return false; } } diff --git a/web/apps/photos/src/services/wasm/ffmpeg.ts b/web/apps/photos/src/services/wasm/ffmpeg.ts index 154f5ac61..10c5a5c05 100644 --- a/web/apps/photos/src/services/wasm/ffmpeg.ts +++ b/web/apps/photos/src/services/wasm/ffmpeg.ts @@ -1,5 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { promiseWithTimeout } from "@ente/shared/utils"; import QueueProcessor from "@ente/shared/utils/queueProcessor"; import { generateTempName } from "@ente/shared/utils/temp"; @@ -51,7 +50,7 @@ export class WasmFFmpeg { try { return await response.promise; } catch (e) { - logError(e, "ffmpeg run failed"); + log.error("ffmpeg run failed", e); throw e; } } @@ -86,7 +85,7 @@ export class WasmFFmpeg { return cmdPart; } }); - addLogLine(`${cmd}`); + log.info(`${cmd}`); await this.ffmpeg.run(...cmd); return new File( [this.ffmpeg.FS("readFile", tempOutputFilePath)], @@ -96,12 +95,12 @@ export class WasmFFmpeg { try { this.ffmpeg.FS("unlink", tempInputFilePath); } catch (e) { - logError(e, "unlink input file failed"); + log.error("unlink input file failed", e); } try { this.ffmpeg.FS("unlink", tempOutputFilePath); } catch (e) { - logError(e, "unlink output file failed"); + log.error("unlink output file failed", e); } } } diff --git a/web/apps/photos/src/services/watchFolder/watchFolderEventHandlers.ts b/web/apps/photos/src/services/watchFolder/watchFolderEventHandlers.ts index 8c15559dd..ba4ad62ee 100644 --- a/web/apps/photos/src/services/watchFolder/watchFolderEventHandlers.ts +++ b/web/apps/photos/src/services/watchFolder/watchFolderEventHandlers.ts @@ -1,5 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { ElectronFile } from "types/upload"; import { EventQueueItem } from "types/watchFolder"; import watchFolderService from "./watchFolderService"; @@ -22,11 +21,11 @@ export async function diskFileAddedCallback(file: ElectronFile) { files: [file], }; watchFolderService.pushEvent(event); - addLogLine( + log.info( `added (upload) to event queue, collectionName:${event.collectionName} folderPath:${event.folderPath}, filesCount: ${event.files.length}`, ); } catch (e) { - logError(e, "error while calling diskFileAddedCallback"); + log.error("error while calling diskFileAddedCallback", e); } } @@ -48,11 +47,11 @@ export async function diskFileRemovedCallback(filePath: string) { paths: [filePath], }; watchFolderService.pushEvent(event); - addLogLine( + log.info( `added (trash) to event queue collectionName:${event.collectionName} folderPath:${event.folderPath} , pathsCount: ${event.paths.length}`, ); } catch (e) { - logError(e, "error while calling diskFileRemovedCallback"); + log.error("error while calling diskFileRemovedCallback", e); } } @@ -63,12 +62,12 @@ export async function diskFolderRemovedCallback(folderPath: string) { (mapping) => mapping.folderPath === folderPath, ); if (!mapping) { - addLogLine(`folder not found in mappings, ${folderPath}`); + log.info(`folder not found in mappings, ${folderPath}`); throw Error(`Watch mapping not found`); } watchFolderService.pushTrashedDir(folderPath); - addLogLine(`added trashedDir, ${folderPath}`); + log.info(`added trashedDir, ${folderPath}`); } catch (e) { - logError(e, "error while calling diskFolderRemovedCallback"); + log.error("error while calling diskFolderRemovedCallback", e); } } diff --git a/web/apps/photos/src/services/watchFolder/watchFolderService.ts b/web/apps/photos/src/services/watchFolder/watchFolderService.ts index b31a3bd87..791aed445 100644 --- a/web/apps/photos/src/services/watchFolder/watchFolderService.ts +++ b/web/apps/photos/src/services/watchFolder/watchFolderService.ts @@ -1,4 +1,4 @@ -import ElectronAPIs from "@/next/electron"; +import { ensureElectron } from "@/next/electron"; import log from "@/next/log"; import { UPLOAD_RESULT, UPLOAD_STRATEGY } from "constants/upload"; import debounce from "debounce"; @@ -83,7 +83,7 @@ class watchFolderService { for (const mapping of mappings) { const filesOnDisk: ElectronFile[] = - await ElectronAPIs.getDirFiles(mapping.folderPath); + await ensureElectron().getDirFiles(mapping.folderPath); this.uploadDiffOfFiles(mapping, filesOnDisk); this.trashDiffOfFiles(mapping, filesOnDisk); @@ -150,11 +150,11 @@ class watchFolderService { ): Promise { const notDeletedMappings = []; for (const mapping of mappings) { - const mappingExists = await ElectronAPIs.isFolder( + const mappingExists = await ensureElectron().isFolder( mapping.folderPath, ); if (!mappingExists) { - ElectronAPIs.removeWatchMapping(mapping.folderPath); + ensureElectron().removeWatchMapping(mapping.folderPath); } else { notDeletedMappings.push(mapping); } @@ -172,7 +172,7 @@ class watchFolderService { } private setupWatcherFunctions() { - ElectronAPIs.registerWatcherFunctions( + ensureElectron().registerWatcherFunctions( diskFileAddedCallback, diskFileRemovedCallback, diskFolderRemovedCallback, @@ -185,7 +185,7 @@ class watchFolderService { uploadStrategy: UPLOAD_STRATEGY, ) { try { - await ElectronAPIs.addWatchMapping( + await ensureElectron().addWatchMapping( rootFolderName, folderPath, uploadStrategy, @@ -198,7 +198,7 @@ class watchFolderService { async removeWatchMapping(folderPath: string) { try { - await ElectronAPIs.removeWatchMapping(folderPath); + await ensureElectron().removeWatchMapping(folderPath); } catch (e) { log.error("error while removing watch mapping", e); } @@ -206,7 +206,7 @@ class watchFolderService { async getWatchMappings(): Promise { try { - return (await ElectronAPIs.getWatchMappings()) ?? []; + return (await ensureElectron().getWatchMappings()) ?? []; } catch (e) { log.error("error while getting watch mappings", e); return []; @@ -378,7 +378,7 @@ class watchFolderService { ...this.currentlySyncedMapping.syncedFiles, ...syncedFiles, ]; - await ElectronAPIs.updateWatchMappingSyncedFiles( + await ensureElectron().updateWatchMappingSyncedFiles( this.currentlySyncedMapping.folderPath, this.currentlySyncedMapping.syncedFiles, ); @@ -388,7 +388,7 @@ class watchFolderService { ...this.currentlySyncedMapping.ignoredFiles, ...ignoredFiles, ]; - await ElectronAPIs.updateWatchMappingIgnoredFiles( + await ensureElectron().updateWatchMappingIgnoredFiles( this.currentlySyncedMapping.folderPath, this.currentlySyncedMapping.ignoredFiles, ); @@ -503,7 +503,7 @@ class watchFolderService { this.currentlySyncedMapping.syncedFiles.filter( (file) => !filePathsToRemove.has(file.path), ); - await ElectronAPIs.updateWatchMappingSyncedFiles( + await ensureElectron().updateWatchMappingSyncedFiles( this.currentlySyncedMapping.folderPath, this.currentlySyncedMapping.syncedFiles, ); @@ -595,7 +595,7 @@ class watchFolderService { async selectFolder(): Promise { try { - const folderPath = await ElectronAPIs.selectDirectory(); + const folderPath = await ensureElectron().selectDirectory(); return folderPath; } catch (e) { log.error("error while selecting folder", e); @@ -623,7 +623,7 @@ class watchFolderService { async isFolder(folderPath: string) { try { - const isFolder = await ElectronAPIs.isFolder(folderPath); + const isFolder = await ensureElectron().isFolder(folderPath); return isFolder; } catch (e) { log.error("error while checking if folder exists", e); diff --git a/web/apps/photos/src/utils/billing/index.ts b/web/apps/photos/src/utils/billing/index.ts index db5944bb3..3dfde5384 100644 --- a/web/apps/photos/src/utils/billing/index.ts +++ b/web/apps/photos/src/utils/billing/index.ts @@ -1,9 +1,8 @@ -import { t } from "i18next"; - +import log from "@/next/log"; import { SetDialogBoxAttributes } from "@ente/shared/components/DialogBox/types"; -import { logError } from "@ente/shared/sentry"; import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; import { REDIRECTS, getRedirectURL } from "constants/redirects"; +import { t } from "i18next"; import { NextRouter } from "next/router"; import billingService from "services/billingService"; import { Plan, Subscription } from "types/billing"; @@ -261,8 +260,8 @@ export async function manageFamilyMethod( setLoading(true); const familyPortalRedirectURL = getRedirectURL(REDIRECTS.FAMILIES); openLink(familyPortalRedirectURL, true); - } catch (error) { - logError(error, "failed to redirect to family portal"); + } catch (e) { + log.error("failed to redirect to family portal", e); setDialogMessage({ title: t("ERROR"), content: t("UNKNOWN_ERROR"), @@ -308,7 +307,7 @@ function handleFailureReason( setDialogMessage: SetDialogBoxAttributes, setLoading: SetLoading, ): void { - logError(Error(reason), "subscription purchase failed"); + log.error(`subscription purchase failed: ${reason}`); switch (reason) { case FAILURE_REASON.CANCELED: setDialogMessage({ diff --git a/web/apps/photos/src/utils/collection/index.ts b/web/apps/photos/src/utils/collection/index.ts index a2f066ac8..c18861515 100644 --- a/web/apps/photos/src/utils/collection/index.ts +++ b/web/apps/photos/src/utils/collection/index.ts @@ -1,8 +1,6 @@ -import ElectronAPIs from "@/next/electron"; +import log from "@/next/log"; import { CustomError } from "@ente/shared/error"; -import { addLogLine } from "@ente/shared/logging"; import { getAlbumsURL } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; import { getUnixTimeInMicroSecondsWithDelta } from "@ente/shared/time"; import { User } from "@ente/shared/user/types"; @@ -18,7 +16,6 @@ import { SYSTEM_COLLECTION_TYPES, } from "constants/collection"; import { t } from "i18next"; -import isElectron from "is-electron"; import { addToCollection, createAlbum, @@ -119,7 +116,7 @@ export async function downloadCollectionHelper( setFilesDownloadProgressAttributes, ); } catch (e) { - logError(e, "download collection failed "); + log.error("download collection failed ", e); } } @@ -140,7 +137,7 @@ export async function downloadDefaultHiddenCollectionHelper( setFilesDownloadProgressAttributes, ); } catch (e) { - logError(e, "download hidden files failed "); + log.error("download hidden files failed ", e); } } @@ -153,8 +150,9 @@ export async function downloadCollectionFiles( return; } let downloadDirPath: string; - if (isElectron()) { - const selectedDir = await ElectronAPIs.selectDirectory(); + const electron = globalThis.electron; + if (electron) { + const selectedDir = await electron.selectDirectory(); if (!selectedDir) { return; } @@ -272,7 +270,7 @@ export const changeCollectionVisibility = async ( ); } } catch (e) { - logError(e, "change collection visibility failed"); + log.error("change collection visibility failed", e); throw e; } }; @@ -298,7 +296,7 @@ export const changeCollectionSortOrder = async ( updatedPubMagicMetadata, ); } catch (e) { - logError(e, "change collection sort order failed"); + log.error("change collection sort order failed", e); } }; @@ -319,7 +317,7 @@ export const changeCollectionOrder = async ( await updateCollectionMagicMetadata(collection, updatedMagicMetadata); } catch (e) { - logError(e, "change collection order failed"); + log.error("change collection order failed", e); } }; @@ -339,7 +337,7 @@ export const changeCollectionSubType = async ( ); await updateCollectionMagicMetadata(collection, updatedMagicMetadata); } catch (e) { - logError(e, "change collection subType failed"); + log.error("change collection subType failed", e); throw e; } }; @@ -568,13 +566,13 @@ export const getOrCreateAlbum = async ( } for (const collection of existingCollections) { if (isValidReplacementAlbum(collection, user, albumName)) { - addLogLine( + log.info( `Found existing album ${albumName} with id ${collection.id}`, ); return collection; } } const album = await createAlbum(albumName); - addLogLine(`Created new album ${albumName} with id ${album.id}`); + log.info(`Created new album ${albumName} with id ${album.id}`); return album; }; diff --git a/web/apps/photos/src/utils/common/job.ts b/web/apps/photos/src/utils/common/job.ts index 7bc37afb4..f549966b6 100644 --- a/web/apps/photos/src/utils/common/job.ts +++ b/web/apps/photos/src/utils/common/job.ts @@ -1,4 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; +import log from "@/next/log"; import { JobConfig, JobResult, JobState } from "types/common/job"; export class SimpleJob { @@ -27,7 +27,7 @@ export class SimpleJob { if (this.state !== "Running") { this.scheduleNext(); } else { - addLogLine("Job already running, not scheduling"); + log.info("Job already running, not scheduling"); } } @@ -41,7 +41,7 @@ export class SimpleJob { this.intervalSec * 1000, ); this.state = "Scheduled"; - addLogLine("Scheduled next job after: ", this.intervalSec); + log.info("Scheduled next job after: ", this.intervalSec); } async run() { @@ -58,7 +58,7 @@ export class SimpleJob { } else { this.resetInterval(); } - addLogLine("Job completed"); + log.info("Job completed"); } catch (e) { console.error("Error while running Job: ", e); } finally { @@ -77,6 +77,6 @@ export class SimpleJob { clearTimeout(this.nextTimeoutId); this.nextTimeoutId = undefined; this.state = "NotScheduled"; - addLogLine("Cleared next job"); + log.info("Cleared next job"); } } diff --git a/web/apps/photos/src/utils/file/index.ts b/web/apps/photos/src/utils/file/index.ts index a0c13a48a..ad93dcb5a 100644 --- a/web/apps/photos/src/utils/file/index.ts +++ b/web/apps/photos/src/utils/file/index.ts @@ -1,6 +1,6 @@ -import ElectronAPIs from "@/next/electron"; import { convertBytesToHumanReadable } from "@/next/file"; import log from "@/next/log"; +import type { Electron } from "@/next/types/ipc"; import { workerBridge } from "@/next/worker/worker-bridge"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import { CustomError } from "@ente/shared/error"; @@ -489,8 +489,9 @@ const convertToJPEGInElectron = async ( try { const startTime = Date.now(); const inputFileData = new Uint8Array(await fileBlob.arrayBuffer()); - const convertedFileData = isElectron() - ? await ElectronAPIs.convertToJPEG(inputFileData, filename) + const electron = globalThis.electron; + const convertedFileData = electron + ? await electron.convertToJPEG(inputFileData, filename) : await workerBridge.convertToJPEG(inputFileData, filename); log.info( `originalFileSize:${convertBytesToHumanReadable( @@ -688,8 +689,10 @@ export async function downloadFilesWithProgress( canceller, }); - if (isElectron()) { + const electron = globalThis.electron; + if (electron) { await downloadFilesDesktop( + electron, files, { increaseSuccess, increaseFailed, isCancelled }, downloadDirPath, @@ -711,8 +714,9 @@ export async function downloadSelectedFiles( return; } let downloadDirPath: string; - if (isElectron()) { - downloadDirPath = await ElectronAPIs.selectDirectory(); + const electron = globalThis.electron; + if (electron) { + downloadDirPath = await electron.selectDirectory(); if (!downloadDirPath) { return; } @@ -729,8 +733,9 @@ export async function downloadSingleFile( setFilesDownloadProgressAttributes: SetFilesDownloadProgressAttributes, ) { let downloadDirPath: string; - if (isElectron()) { - downloadDirPath = await ElectronAPIs.selectDirectory(); + const electron = globalThis.electron; + if (electron) { + downloadDirPath = await electron.selectDirectory(); if (!downloadDirPath) { return; } @@ -764,7 +769,8 @@ export async function downloadFiles( } } -export async function downloadFilesDesktop( +async function downloadFilesDesktop( + electron: Electron, files: EnteFile[], progressBarUpdater: { increaseSuccess: () => void; @@ -779,7 +785,7 @@ export async function downloadFilesDesktop( if (progressBarUpdater?.isCancelled()) { return; } - await downloadFileDesktop(fileReader, file, downloadPath); + await downloadFileDesktop(electron, fileReader, file, downloadPath); progressBarUpdater?.increaseSuccess(); } catch (e) { log.error("download fail for file", e); @@ -788,7 +794,8 @@ export async function downloadFilesDesktop( } } -export async function downloadFileDesktop( +async function downloadFileDesktop( + electron: Electron, fileReader: FileReader, file: EnteFile, downloadPath: string, @@ -810,7 +817,7 @@ export async function downloadFileDesktop( livePhoto.imageNameTitle, ); const imageStream = generateStreamFromArrayBuffer(livePhoto.image); - await ElectronAPIs.saveStreamToDisk( + await electron.saveStreamToDisk( getFileExportPath(downloadPath, imageExportName), imageStream, ); @@ -820,12 +827,12 @@ export async function downloadFileDesktop( livePhoto.videoNameTitle, ); const videoStream = generateStreamFromArrayBuffer(livePhoto.video); - await ElectronAPIs.saveStreamToDisk( + await electron.saveStreamToDisk( getFileExportPath(downloadPath, videoExportName), videoStream, ); } catch (e) { - await ElectronAPIs.deleteFile( + await electron.deleteFile( getFileExportPath(downloadPath, imageExportName), ); throw e; @@ -835,7 +842,7 @@ export async function downloadFileDesktop( downloadPath, file.metadata.title, ); - await ElectronAPIs.saveStreamToDisk( + await electron.saveStreamToDisk( getFileExportPath(downloadPath, fileExportName), updatedFileStream, ); diff --git a/web/apps/photos/src/utils/image/index.ts b/web/apps/photos/src/utils/image/index.ts index 1062b828f..419545aed 100644 --- a/web/apps/photos/src/utils/image/index.ts +++ b/web/apps/photos/src/utils/image/index.ts @@ -80,7 +80,7 @@ export function cropWithRotation( } } - // addLogLine({ imageBitmap, box, outputSize }); + // log.info({ imageBitmap, box, outputSize }); const offscreen = new OffscreenCanvas(outputSize.width, outputSize.height); const offscreenCtx = offscreen.getContext("2d"); diff --git a/web/apps/photos/src/utils/machineLearning/faceAlign.ts b/web/apps/photos/src/utils/machineLearning/faceAlign.ts index 392b6b278..52b7f4692 100644 --- a/web/apps/photos/src/utils/machineLearning/faceAlign.ts +++ b/web/apps/photos/src/utils/machineLearning/faceAlign.ts @@ -61,7 +61,7 @@ export function getFaceAlignmentUsingSimilarityTransform( simTransform.rotation.get(0, 1), simTransform.rotation.get(0, 0), ); - // addLogLine({ affineMatrix, meanTranslation, centerMat, center, toMean: simTransform.toMean, fromMean: simTransform.fromMean, size }); + // log.info({ affineMatrix, meanTranslation, centerMat, center, toMean: simTransform.toMean, fromMean: simTransform.fromMean, size }); return { affineMatrix, @@ -169,7 +169,7 @@ export function ibExtractFaceImageUsingTransform( const scaledMatrix = new Matrix(alignment.affineMatrix) .mul(faceSize) .to2DArray(); - // addLogLine("scaledMatrix: ", scaledMatrix); + // log.info("scaledMatrix: ", scaledMatrix); return transform(image, scaledMatrix, faceSize, faceSize); } @@ -230,7 +230,7 @@ export function getRotatedFaceImage( padding: number = 1.5, ): tf.Tensor4D { const paddedBox = enlargeBox(faceDetection.box, padding); - // addLogLine("paddedBox", paddedBox); + // log.info("paddedBox", paddedBox); const landmarkPoints = faceDetection.landmarks; return tf.tidy(() => { @@ -245,15 +245,15 @@ export function getRotatedFaceImage( foreheadCenter, ); // landmarkPoints[BLAZEFACE_NOSE_INDEX] // angle = computeRotation(leftEye, rightEye); - // addLogLine('angle: ', angle); + // log.info('angle: ', angle); const faceCenter = getBoxCenter(faceDetection.box); - // addLogLine('faceCenter: ', faceCenter); + // log.info('faceCenter: ', faceCenter); const faceCenterNormalized: [number, number] = [ faceCenter.x / tf4dFloat32Image.shape[2], faceCenter.y / tf4dFloat32Image.shape[1], ]; - // addLogLine('faceCenterNormalized: ', faceCenterNormalized); + // log.info('faceCenterNormalized: ', faceCenterNormalized); let rotatedImage = tf4dFloat32Image; if (angle !== 0) { diff --git a/web/apps/photos/src/utils/machineLearning/faceCrop.ts b/web/apps/photos/src/utils/machineLearning/faceCrop.ts index e96f1d262..be0aa215d 100644 --- a/web/apps/photos/src/utils/machineLearning/faceCrop.ts +++ b/web/apps/photos/src/utils/machineLearning/faceCrop.ts @@ -1,4 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; +import log from "@/next/log"; import { CacheStorageService } from "@ente/shared/storage/cacheStorage"; import { CACHES } from "@ente/shared/storage/cacheStorage/constants"; import { getBlobFromCache } from "@ente/shared/storage/cacheStorage/helpers"; @@ -105,7 +105,7 @@ export async function removeOldFaceCrops( } export async function removeFaceCropUrls(faceCropUrls: Array) { - addLogLine("Removing face crop urls: ", JSON.stringify(faceCropUrls)); + log.info("Removing face crop urls: ", JSON.stringify(faceCropUrls)); const faceCropCache = await CacheStorageService.open(CACHES.FACE_CROPS); const urlRemovalPromises = faceCropUrls?.map((url) => faceCropCache.delete(url), @@ -132,7 +132,7 @@ export function extractFaceImageFromCrop( .shift(-imageBox.x, -imageBox.y) .rescale(scale) .round(); - // addLogLine({ box, imageBox, faceCropImage, scale, scaledBox, scaledImageBox, shiftedBox }); + // log.info({ box, imageBox, faceCropImage, scale, scaledBox, scaledImageBox, shiftedBox }); const faceSizeDimentions: Dimensions = { width: faceSize, diff --git a/web/apps/photos/src/utils/machineLearning/index.ts b/web/apps/photos/src/utils/machineLearning/index.ts index 57845937b..392b0fe9b 100644 --- a/web/apps/photos/src/utils/machineLearning/index.ts +++ b/web/apps/photos/src/utils/machineLearning/index.ts @@ -1,4 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; +import log from "@/next/log"; import { CACHES } from "@ente/shared/storage/cacheStorage/constants"; import { cached } from "@ente/shared/storage/cacheStorage/helpers"; import * as tf from "@tensorflow/tfjs-core"; @@ -130,7 +130,7 @@ export function extractFaces( ]; }); - // addLogLine('boxes: ', boxes[0]); + // log.info('boxes: ', boxes[0]); const faceImagesTensor = tf.image.cropAndResize( reshapedImage, @@ -356,14 +356,14 @@ export async function getOriginalImageBitmap( } else { fileBlob = await getOriginalConvertedFile(file, queue); } - addLogLine("[MLService] Got file: ", file.id.toString()); + log.info("[MLService] Got file: ", file.id.toString()); return getImageBlobBitmap(fileBlob); } export async function getThumbnailImageBitmap(file: EnteFile) { const thumb = await DownloadManager.getThumbnail(file); - addLogLine("[MLService] Got thumbnail: ", file.id.toString()); + log.info("[MLService] Got thumbnail: ", file.id.toString()); return getImageBlobBitmap(new Blob([thumb])); } @@ -380,7 +380,7 @@ export async function getLocalFileImageBitmap( export async function getPeopleList(file: EnteFile): Promise> { let startTime = Date.now(); const mlFileData: MlFileData = await mlIDbStorage.getFile(file.id); - addLogLine( + log.info( "getPeopleList:mlFilesStore:getItem", Date.now() - startTime, "ms", @@ -395,18 +395,18 @@ export async function getPeopleList(file: EnteFile): Promise> { if (!peopleIds || peopleIds.length < 1) { return []; } - // addLogLine("peopleIds: ", peopleIds); + // log.info("peopleIds: ", peopleIds); startTime = Date.now(); const peoplePromises = peopleIds.map( (p) => mlIDbStorage.getPerson(p) as Promise, ); const peopleList = await Promise.all(peoplePromises); - addLogLine( + log.info( "getPeopleList:mlPeopleStore:getItems", Date.now() - startTime, "ms", ); - // addLogLine("peopleList: ", peopleList); + // log.info("peopleList: ", peopleList); return peopleList; } @@ -514,7 +514,7 @@ export function getNearestPointIndex( (a, b) => Math.abs(a.distance) - Math.abs(b.distance), ); - // addLogLine('Nearest dist: ', nearest.distance, maxDistance); + // log.info('Nearest dist: ', nearest.distance, maxDistance); if (!maxDistance || nearest.distance <= maxDistance) { return nearest.index; } @@ -522,11 +522,11 @@ export function getNearestPointIndex( export function logQueueStats(queue: PQueue, name: string) { queue.on("active", () => - addLogLine( + log.info( `queuestats: ${name}: Active, Size: ${queue.size} Pending: ${queue.pending}`, ), ); - queue.on("idle", () => addLogLine(`queuestats: ${name}: Idle`)); + queue.on("idle", () => log.info(`queuestats: ${name}: Idle`)); queue.on("error", (error) => console.error(`queuestats: ${name}: Error, `, error), ); diff --git a/web/apps/photos/src/utils/photoFrame/index.ts b/web/apps/photos/src/utils/photoFrame/index.ts index 2ddc26252..faf0679e7 100644 --- a/web/apps/photos/src/utils/photoFrame/index.ts +++ b/web/apps/photos/src/utils/photoFrame/index.ts @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { FILE_TYPE } from "constants/file"; import { LivePhotoSourceURL, SourceURLs } from "services/download"; import { EnteFile } from "types/file"; @@ -94,10 +94,7 @@ export async function updateFileSrcProps( } else if (file.metadata.fileType === FILE_TYPE.IMAGE) { file.src = url as string; } else { - logError( - Error(`unknown file type - ${file.metadata.fileType}`), - "Unknown file type", - ); + log.error(`unknown file type - ${file.metadata.fileType}`); file.src = url as string; } } diff --git a/web/apps/photos/src/utils/storage/mlIDbStorage.ts b/web/apps/photos/src/utils/storage/mlIDbStorage.ts index 865b6cb8c..96b2cd905 100644 --- a/web/apps/photos/src/utils/storage/mlIDbStorage.ts +++ b/web/apps/photos/src/utils/storage/mlIDbStorage.ts @@ -1,6 +1,5 @@ import { haveWindow } from "@/next/env"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { DEFAULT_ML_SEARCH_CONFIG, DEFAULT_ML_SYNC_CONFIG, @@ -75,21 +74,18 @@ class MLIDbStorage { private openDB(): Promise> { return openDB(MLDATA_DB_NAME, 3, { terminated: async () => { - console.error("ML Indexed DB terminated"); - logError(new Error(), "ML Indexed DB terminated"); + log.error("ML Indexed DB terminated"); this._db = undefined; // TODO: remove if there is chance of this going into recursion in some case await this.db; }, blocked() { // TODO: make sure we dont allow multiple tabs of app - console.error("ML Indexed DB blocked"); - logError(new Error(), "ML Indexed DB blocked"); + log.error("ML Indexed DB blocked"); }, blocking() { // TODO: make sure we dont allow multiple tabs of app - console.error("ML Indexed DB blocking"); - logError(new Error(), "ML Indexed DB blocking"); + log.error("ML Indexed DB blocking"); }, async upgrade(db, oldVersion, newVersion, tx) { if (oldVersion < 1) { @@ -132,7 +128,7 @@ class MLIDbStorage { .objectStore("configs") .add(DEFAULT_ML_SEARCH_CONFIG, ML_SEARCH_CONFIG_NAME); } - addLogLine( + log.info( `Ml DB upgraded to version: ${newVersion} from version: ${oldVersion}`, ); }, @@ -142,7 +138,7 @@ class MLIDbStorage { public get db(): Promise> { if (!this._db) { this._db = this.openDB(); - addLogLine("Opening Ml DB"); + log.info("Opening Ml DB"); } return this._db; @@ -152,7 +148,7 @@ class MLIDbStorage { const db = await this.db; db.close(); await deleteDB(MLDATA_DB_NAME); - addLogLine("Cleared Ml DB"); + log.info("Cleared Ml DB"); this._db = undefined; await this.db; } @@ -281,7 +277,7 @@ class MLIDbStorage { mlFileData.faces && allFacesMap.set(mlFileData.fileId, mlFileData.faces), ); - addLogLine("getAllFacesMap", Date.now() - startTime, "ms"); + log.info("getAllFacesMap", Date.now() - startTime, "ms"); return allFacesMap; } @@ -300,7 +296,7 @@ class MLIDbStorage { cursor = await cursor.continue(); } await tx.done; - addLogLine("updateFaces", Date.now() - startTime, "ms"); + log.info("updateFaces", Date.now() - startTime, "ms"); } public async getAllObjectsMap() { @@ -313,7 +309,7 @@ class MLIDbStorage { mlFileData.objects && allObjectsMap.set(mlFileData.fileId, mlFileData.objects), ); - addLogLine("allObjectsMap", Date.now() - startTime, "ms"); + log.info("allObjectsMap", Date.now() - startTime, "ms"); return allObjectsMap; } diff --git a/web/apps/photos/src/utils/ui/index.tsx b/web/apps/photos/src/utils/ui/index.tsx index d193ba960..9090c6917 100644 --- a/web/apps/photos/src/utils/ui/index.tsx +++ b/web/apps/photos/src/utils/ui/index.tsx @@ -1,4 +1,3 @@ -import ElectronAPIs from "@/next/electron"; import { AppUpdateInfo } from "@/next/types/ipc"; import { logoutUser } from "@ente/accounts/services/user"; import { DialogBoxAttributes } from "@ente/shared/components/DialogBox/types"; @@ -60,14 +59,15 @@ export const getUpdateReadyToInstallMessage = ( title: t("UPDATE_AVAILABLE"), content: t("UPDATE_INSTALLABLE_MESSAGE"), proceed: { - action: () => ElectronAPIs.updateAndRestart(), + action: () => globalThis.electron?.updateAndRestart(), text: t("INSTALL_NOW"), variant: "accent", }, close: { text: t("INSTALL_ON_NEXT_LAUNCH"), variant: "secondary", - action: () => ElectronAPIs.muteUpdateNotification(updateInfo.version), + action: () => + globalThis.electron?.muteUpdateNotification(updateInfo.version), }, }); @@ -80,7 +80,7 @@ export const getUpdateAvailableForDownloadMessage = ( close: { text: t("IGNORE_THIS_VERSION"), variant: "secondary", - action: () => ElectronAPIs.skipAppUpdate(updateInfo.version), + action: () => globalThis.electron?.skipAppUpdate(updateInfo.version), }, proceed: { action: downloadApp, diff --git a/web/apps/photos/src/utils/user/family.ts b/web/apps/photos/src/utils/user/family.ts index 4ccc1bcf1..b0f90cbaf 100644 --- a/web/apps/photos/src/utils/user/family.ts +++ b/web/apps/photos/src/utils/user/family.ts @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; import { User } from "@ente/shared/user/types"; import { FamilyData, FamilyMember } from "types/user"; @@ -29,11 +29,8 @@ export function getFamilyPlanAdmin(familyData: FamilyData): FamilyMember { if (isPartOfFamily(familyData)) { return familyData.members.find((x) => x.isAdmin); } else { - logError( - Error( - "verify user is part of family plan before calling this method", - ), - "invalid getFamilyPlanAdmin call", + log.error( + "invalid getFamilyPlanAdmin call - verify user is part of family plan before calling this method", ); } } diff --git a/web/apps/photos/src/worker/ml.worker.ts b/web/apps/photos/src/worker/ml.worker.ts index 33c2e5583..ed46b7bd4 100644 --- a/web/apps/photos/src/worker/ml.worker.ts +++ b/web/apps/photos/src/worker/ml.worker.ts @@ -1,4 +1,4 @@ -import { addLogLine } from "@ente/shared/logging"; +import log from "@/next/log"; import { expose } from "comlink"; import mlService from "services/machineLearning/machineLearningService"; import { EnteFile } from "types/file"; @@ -6,7 +6,7 @@ import { MachineLearningWorker } from "types/machineLearning"; export class DedicatedMLWorker implements MachineLearningWorker { constructor() { - addLogLine("DedicatedMLWorker constructor called"); + log.info("DedicatedMLWorker constructor called"); } public async closeLocalSyncContext() { diff --git a/web/apps/photos/tests/zip-file-reading.test.ts b/web/apps/photos/tests/zip-file-reading.test.ts index 38be7ae75..6ac20bfee 100644 --- a/web/apps/photos/tests/zip-file-reading.test.ts +++ b/web/apps/photos/tests/zip-file-reading.test.ts @@ -1,7 +1,5 @@ -import ElectronAPIs from "@/next/electron"; import { getFileNameSize } from "@/next/file"; import { FILE_READER_CHUNK_SIZE, PICKED_UPLOAD_TYPE } from "constants/upload"; -import isElectron from "is-electron"; import { getElectronFileStream, getFileStream } from "services/readerService"; import { DataStream } from "types/upload"; import { getImportSuggestion } from "utils/upload"; @@ -12,7 +10,8 @@ import { getImportSuggestion } from "utils/upload"; // sizes starting from 1M to 20M. export const testZipFileReading = async () => { try { - if (!isElectron()) { + const electron = globalThis.electron; + if (!electron) { console.log("testZipFileReading Check is for desktop only"); return; } @@ -21,7 +20,7 @@ export const testZipFileReading = async () => { "upload test failed NEXT_PUBLIC_FILE_READING_TEST_ZIP_PATH missing", ); } - const files = await ElectronAPIs.getElectronFilesFromGoogleZip( + const files = await electron.getElectronFilesFromGoogleZip( process.env.NEXT_PUBLIC_FILE_READING_TEST_ZIP_PATH, ); if (!files?.length) { @@ -81,7 +80,8 @@ export const testZipFileReading = async () => { // at the root. export const testZipWithRootFileReadingTest = async () => { try { - if (!isElectron()) { + const electron = globalThis.electron; + if (!electron) { console.log("testZipFileReading Check is for desktop only"); return; } @@ -90,7 +90,7 @@ export const testZipWithRootFileReadingTest = async () => { "upload test failed NEXT_PUBLIC_ZIP_WITH_ROOT_FILE_PATH missing", ); } - const files = await ElectronAPIs.getElectronFilesFromGoogleZip( + const files = await electron.getElectronFilesFromGoogleZip( process.env.NEXT_PUBLIC_ZIP_WITH_ROOT_FILE_PATH, ); diff --git a/web/apps/photos/tsconfig.json b/web/apps/photos/tsconfig.json index e7105c071..cfe85e6d7 100644 --- a/web/apps/photos/tsconfig.json +++ b/web/apps/photos/tsconfig.json @@ -21,7 +21,8 @@ "**/*.ts", "**/*.tsx", "**/*.js", - "../../packages/shared/themes/mui-theme.d.ts" + "../../packages/shared/themes/mui-theme.d.ts", + "../../packages/next/global-electron.d.ts" ], "exclude": ["node_modules", "out", ".next", "thirdparty"] } diff --git a/web/packages/accounts/api/srp.ts b/web/packages/accounts/api/srp.ts index 8a737a0d6..89dd8ab7d 100644 --- a/web/packages/accounts/api/srp.ts +++ b/web/packages/accounts/api/srp.ts @@ -1,3 +1,4 @@ +import log from "@/next/log"; import HTTPService from "@ente/shared/network/HTTPService"; import { getEndpoint } from "@ente/shared/network/api"; @@ -14,7 +15,6 @@ import { UpdateSRPAndKeysResponse, } from "@ente/accounts/types/srp"; import { ApiError, CustomError } from "@ente/shared/error"; -import { logError } from "@ente/shared/sentry"; import { HttpStatusCode } from "axios"; const ENDPOINT = getEndpoint(); @@ -28,7 +28,7 @@ export const getSRPAttributes = async ( }); return (resp.data as GetSRPAttributesResponse).attributes; } catch (e) { - logError(e, "failed to get SRP attributes"); + log.error("failed to get SRP attributes", e); return null; } }; @@ -49,7 +49,7 @@ export const startSRPSetup = async ( return resp.data as SetupSRPResponse; } catch (e) { - logError(e, "failed to post SRP attributes"); + log.error("failed to post SRP attributes", e); throw e; } }; @@ -69,7 +69,7 @@ export const completeSRPSetup = async ( ); return resp.data as CompleteSRPSetupResponse; } catch (e) { - logError(e, "failed to complete SRP setup"); + log.error("failed to complete SRP setup", e); throw e; } }; @@ -85,7 +85,7 @@ export const createSRPSession = async (srpUserID: string, srpA: string) => { ); return resp.data as CreateSRPSessionResponse; } catch (e) { - logError(e, "createSRPSession failed"); + log.error("createSRPSession failed", e); throw e; } }; @@ -107,7 +107,7 @@ export const verifySRPSession = async ( ); return resp.data as SRPVerificationResponse; } catch (e) { - logError(e, "verifySRPSession failed"); + log.error("verifySRPSession failed", e); if ( e instanceof ApiError && e.httpStatusCode === HttpStatusCode.Unauthorized @@ -134,7 +134,7 @@ export const updateSRPAndKeys = async ( ); return resp.data as UpdateSRPAndKeysResponse; } catch (e) { - logError(e, "updateSRPAndKeys failed"); + log.error("updateSRPAndKeys failed", e); throw e; } }; diff --git a/web/packages/accounts/api/user.ts b/web/packages/accounts/api/user.ts index 0aa534306..865a0c217 100644 --- a/web/packages/accounts/api/user.ts +++ b/web/packages/accounts/api/user.ts @@ -1,6 +1,4 @@ -import HTTPService from "@ente/shared/network/HTTPService"; -import { getEndpoint } from "@ente/shared/network/api"; - +import log from "@/next/log"; import { RecoveryKey, TwoFactorRecoveryResponse, @@ -11,7 +9,8 @@ import { import { APPS, OTT_CLIENTS } from "@ente/shared/apps/constants"; import { B64EncryptionResult } from "@ente/shared/crypto/types"; import { ApiError, CustomError } from "@ente/shared/error"; -import { logError } from "@ente/shared/sentry"; +import HTTPService from "@ente/shared/network/HTTPService"; +import { getEndpoint } from "@ente/shared/network/api"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { KeyAttributes } from "@ente/shared/user/types"; import { HttpStatusCode } from "axios"; @@ -63,7 +62,7 @@ export const _logout = async () => { ) { return; } - logError(e, "/users/logout failed"); + log.error("/users/logout failed", e); throw e; } }; diff --git a/web/packages/accounts/components/SignUp.tsx b/web/packages/accounts/components/SignUp.tsx index b2984f108..b0ea1ac9f 100644 --- a/web/packages/accounts/components/SignUp.tsx +++ b/web/packages/accounts/components/SignUp.tsx @@ -1,25 +1,21 @@ +import log from "@/next/log"; import { sendOtt } from "@ente/accounts/api/user"; -import { isWeakPassword } from "@ente/accounts/utils"; -import { generateKeyAndSRPAttributes } from "@ente/accounts/utils/srp"; -import SubmitButton from "@ente/shared/components/SubmitButton"; -import { - generateAndSaveIntermediateKeyAttributes, - saveKeyInSessionStore, -} from "@ente/shared/crypto/helpers"; -import { LS_KEYS, setData } from "@ente/shared/storage/localStorage"; -import { Formik, FormikHelpers } from "formik"; -import React, { useState } from "react"; -import * as Yup from "yup"; - import { PasswordStrengthHint } from "@ente/accounts/components/PasswordStrength"; import { PAGES } from "@ente/accounts/constants/pages"; +import { isWeakPassword } from "@ente/accounts/utils"; +import { generateKeyAndSRPAttributes } from "@ente/accounts/utils/srp"; import { APPS } from "@ente/shared/apps/constants"; import { VerticallyCentered } from "@ente/shared/components//Container"; import FormPaperFooter from "@ente/shared/components/Form/FormPaper/Footer"; import FormPaperTitle from "@ente/shared/components/Form/FormPaper/Title"; import ShowHidePassword from "@ente/shared/components/Form/ShowHidePassword"; import LinkButton from "@ente/shared/components/LinkButton"; -import { logError } from "@ente/shared/sentry"; +import SubmitButton from "@ente/shared/components/SubmitButton"; +import { + generateAndSaveIntermediateKeyAttributes, + saveKeyInSessionStore, +} from "@ente/shared/crypto/helpers"; +import { LS_KEYS, setData } from "@ente/shared/storage/localStorage"; import { setJustSignedUp, setLocalReferralSource, @@ -38,9 +34,12 @@ import { Tooltip, Typography, } from "@mui/material"; +import { Formik, FormikHelpers } from "formik"; import { t } from "i18next"; import { NextRouter } from "next/router"; +import React, { useState } from "react"; import { Trans } from "react-i18next"; +import * as Yup from "yup"; interface FormValues { email: string; @@ -110,8 +109,8 @@ export default function SignUp({ router, appName, login }: SignUpProps) { setFieldError("confirm", t("PASSWORD_GENERATION_FAILED")); throw e; } - } catch (err) { - logError(err, "signup failed"); + } catch (e) { + log.error("signup failed", e); } setLoading(false); }; diff --git a/web/packages/accounts/pages/credentials.tsx b/web/packages/accounts/pages/credentials.tsx index 7980eb7a5..bf5943238 100644 --- a/web/packages/accounts/pages/credentials.tsx +++ b/web/packages/accounts/pages/credentials.tsx @@ -1,4 +1,3 @@ -import ElectronAPIs from "@/next/electron"; import log from "@/next/log"; import { APP_HOMES } from "@ente/shared/apps/constants"; import { PageProps } from "@ente/shared/apps/types"; @@ -21,7 +20,6 @@ import { import { B64EncryptionResult } from "@ente/shared/crypto/types"; import { CustomError } from "@ente/shared/error"; import { getAccountsURL } from "@ente/shared/network/api"; -import { logError } from "@ente/shared/sentry"; import InMemoryStore, { MS_KEYS } from "@ente/shared/storage/InMemoryStore"; import { LS_KEYS, @@ -42,7 +40,6 @@ import { } from "@ente/shared/storage/sessionStorage"; import { KeyAttributes, User } from "@ente/shared/user/types"; import { t } from "i18next"; -import isElectron from "is-electron"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; import { getSRPAttributes } from "../api/srp"; @@ -70,11 +67,12 @@ export default function Credentials({ appContext, appName }: PageProps) { } setUser(user); let key = getKey(SESSION_KEYS.ENCRYPTION_KEY); - if (!key && isElectron()) { + const electron = globalThis.electron; + if (!key && electron) { try { - key = await ElectronAPIs.getEncryptionKey(); + key = await electron.getEncryptionKey(); } catch (e) { - logError(e, "getEncryptionKey failed"); + log.error("getEncryptionKey failed", e); } if (key) { await saveKeyInSessionStore( @@ -198,7 +196,7 @@ export default function Credentials({ appContext, appName }: PageProps) { } } catch (e) { if (e.message !== CustomError.TWO_FACTOR_ENABLED) { - logError(e, "getKeyAttributes failed"); + log.error("getKeyAttributes failed", e); } throw e; } @@ -238,13 +236,13 @@ export default function Credentials({ appContext, appName }: PageProps) { await configureSRP(srpSetupAttributes); } } catch (e) { - logError(e, "migrate to srp failed"); + log.error("migrate to srp failed", e); } const redirectURL = InMemoryStore.get(MS_KEYS.REDIRECT_URL); InMemoryStore.delete(MS_KEYS.REDIRECT_URL); router.push(redirectURL ?? APP_HOMES.get(appName)); } catch (e) { - logError(e, "useMasterPassword failed"); + log.error("useMasterPassword failed", e); } }; diff --git a/web/packages/accounts/pages/generate.tsx b/web/packages/accounts/pages/generate.tsx index ad68308e4..fb92edb14 100644 --- a/web/packages/accounts/pages/generate.tsx +++ b/web/packages/accounts/pages/generate.tsx @@ -1,6 +1,4 @@ -import { t } from "i18next"; -import { useEffect, useState } from "react"; - +import log from "@/next/log"; import { putAttributes } from "@ente/accounts/api/user"; import { configureSRP } from "@ente/accounts/services/srp"; import { logoutUser } from "@ente/accounts/services/user"; @@ -11,6 +9,8 @@ import { } from "@ente/shared/crypto/helpers"; import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; import { SESSION_KEYS, getKey } from "@ente/shared/storage/sessionStorage"; +import { t } from "i18next"; +import { useEffect, useState } from "react"; import SetPasswordForm from "@ente/accounts/components/SetPasswordForm"; import { PAGES } from "@ente/accounts/constants/pages"; @@ -23,7 +23,6 @@ import FormPaperFooter from "@ente/shared/components/Form/FormPaper/Footer"; import FormTitle from "@ente/shared/components/Form/FormPaper/Title"; import LinkButton from "@ente/shared/components/LinkButton"; import RecoveryKey from "@ente/shared/components/RecoveryKey"; -import { logError } from "@ente/shared/sentry"; import { justSignedUp, setJustSignedUp, @@ -83,7 +82,7 @@ export default function Generate({ appContext, appName }: PageProps) { setJustSignedUp(true); setRecoveryModalView(true); } catch (e) { - logError(e, "failed to generate password"); + log.error("failed to generate password", e); setFieldError("passphrase", t("PASSWORD_GENERATION_FAILED")); } }; diff --git a/web/packages/accounts/pages/recover.tsx b/web/packages/accounts/pages/recover.tsx index fc9cf0812..20b806ac4 100644 --- a/web/packages/accounts/pages/recover.tsx +++ b/web/packages/accounts/pages/recover.tsx @@ -1,6 +1,4 @@ -import { t } from "i18next"; -import { useEffect, useState } from "react"; - +import log from "@/next/log"; import { sendOtt } from "@ente/accounts/api/user"; import { PAGES } from "@ente/accounts/constants/pages"; import { APP_HOMES } from "@ente/shared/apps/constants"; @@ -18,12 +16,13 @@ import { decryptAndStoreToken, saveKeyInSessionStore, } from "@ente/shared/crypto/helpers"; -import { logError } from "@ente/shared/sentry"; import InMemoryStore, { MS_KEYS } from "@ente/shared/storage/InMemoryStore"; import { LS_KEYS, getData, setData } from "@ente/shared/storage/localStorage"; import { SESSION_KEYS, getKey } from "@ente/shared/storage/sessionStorage"; import { KeyAttributes, User } from "@ente/shared/user/types"; +import { t } from "i18next"; import { useRouter } from "next/router"; +import { useEffect, useState } from "react"; const bip39 = require("bip39"); // mobile client library only supports english. @@ -88,7 +87,7 @@ export default function Recover({ appContext, appName }: PageProps) { setData(LS_KEYS.SHOW_BACK_BUTTON, { value: false }); router.push(PAGES.CHANGE_PASSWORD); } catch (e) { - logError(e, "password recovery failed"); + log.error("password recovery failed", e); setFieldError(t("INCORRECT_RECOVERY_KEY")); } }; diff --git a/web/packages/accounts/pages/two-factor/recover.tsx b/web/packages/accounts/pages/two-factor/recover.tsx index 7a589b9ab..150bd47de 100644 --- a/web/packages/accounts/pages/two-factor/recover.tsx +++ b/web/packages/accounts/pages/two-factor/recover.tsx @@ -1,29 +1,28 @@ -import { VerticallyCentered } from "@ente/shared/components/Container"; -import SingleInputForm, { - SingleInputFormProps, -} from "@ente/shared/components/SingleInputForm"; -import { logError } from "@ente/shared/sentry"; -import { LS_KEYS, getData, setData } from "@ente/shared/storage/localStorage"; -import { useEffect, useState } from "react"; - +import log from "@/next/log"; import { recoverTwoFactor, removeTwoFactor } from "@ente/accounts/api/user"; import { PAGES } from "@ente/accounts/constants/pages"; import { TwoFactorType } from "@ente/accounts/constants/twofactor"; import { logoutUser } from "@ente/accounts/services/user"; import { PageProps } from "@ente/shared/apps/types"; +import { VerticallyCentered } from "@ente/shared/components/Container"; import { DialogBoxAttributesV2 } from "@ente/shared/components/DialogBoxV2/types"; import FormPaper from "@ente/shared/components/Form/FormPaper"; import FormPaperFooter from "@ente/shared/components/Form/FormPaper/Footer"; import FormPaperTitle from "@ente/shared/components/Form/FormPaper/Title"; import LinkButton from "@ente/shared/components/LinkButton"; +import SingleInputForm, { + SingleInputFormProps, +} from "@ente/shared/components/SingleInputForm"; import { SUPPORT_EMAIL } from "@ente/shared/constants/urls"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import { B64EncryptionResult } from "@ente/shared/crypto/types"; import { ApiError } from "@ente/shared/error"; +import { LS_KEYS, getData, setData } from "@ente/shared/storage/localStorage"; import { Link } from "@mui/material"; import { HttpStatusCode } from "axios"; import { t } from "i18next"; import { useRouter } from "next/router"; +import { useEffect, useState } from "react"; import { Trans } from "react-i18next"; const bip39 = require("bip39"); @@ -80,7 +79,7 @@ export default function Recover({ ) { logoutUser(); } else { - logError(e, "two factor recovery page setup failed"); + log.error("two factor recovery page setup failed", e); setDoesHaveEncryptedRecoveryKey(false); showContactSupportDialog({ text: t("GO_BACK"), @@ -132,7 +131,7 @@ export default function Recover({ setData(LS_KEYS.KEY_ATTRIBUTES, keyAttributes); router.push(PAGES.CREDENTIALS); } catch (e) { - logError(e, "two factor recovery failed"); + log.error("two factor recovery failed", e); setFieldError(t("INCORRECT_RECOVERY_KEY")); } }; diff --git a/web/packages/accounts/pages/two-factor/setup.tsx b/web/packages/accounts/pages/two-factor/setup.tsx index bf22ea1c9..265b15fd6 100644 --- a/web/packages/accounts/pages/two-factor/setup.tsx +++ b/web/packages/accounts/pages/two-factor/setup.tsx @@ -1,3 +1,4 @@ +import log from "@/next/log"; import { enableTwoFactor, setupTwoFactor } from "@ente/accounts/api/user"; import VerifyTwoFactor, { VerifyTwoFactorCallback, @@ -9,7 +10,6 @@ import { PageProps } from "@ente/shared/apps/types"; import { VerticallyCentered } from "@ente/shared/components/Container"; import LinkButton from "@ente/shared/components/LinkButton"; import { encryptWithRecoveryKey } from "@ente/shared/crypto/helpers"; -import { logError } from "@ente/shared/sentry"; import { LS_KEYS, getData, setData } from "@ente/shared/storage/localStorage"; import { Box, CardContent, Typography } from "@mui/material"; import Card from "@mui/material/Card"; @@ -37,7 +37,7 @@ export default function SetupTwoFactor({ appName }: PageProps) { const twoFactorSecret = await setupTwoFactor(); setTwoFactorSecret(twoFactorSecret); } catch (e) { - logError(e, "failed to get two factor setup code"); + log.error("failed to get two factor setup code", e); } }; main(); diff --git a/web/packages/accounts/services/passkey.ts b/web/packages/accounts/services/passkey.ts index 89a9ae61a..e75c667d7 100644 --- a/web/packages/accounts/services/passkey.ts +++ b/web/packages/accounts/services/passkey.ts @@ -1,6 +1,6 @@ +import log from "@/next/log"; import { CustomError } from "@ente/shared/error"; import HTTPService from "@ente/shared/network/HTTPService"; -import { logError } from "@ente/shared/sentry"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; export const isPasskeyRecoveryEnabled = async () => { @@ -21,7 +21,7 @@ export const isPasskeyRecoveryEnabled = async () => { return resp.data["isPasskeyRecoveryEnabled"] as boolean; } catch (e) { - logError(e, "failed to get passkey recovery status"); + log.error("failed to get passkey recovery status", e); throw e; } }; @@ -50,7 +50,7 @@ export const configurePasskeyRecovery = async ( throw Error(CustomError.REQUEST_FAILED); } } catch (e) { - logError(e, "failed to configure passkey recovery"); + log.error("failed to configure passkey recovery", e); throw e; } }; diff --git a/web/packages/accounts/services/srp.ts b/web/packages/accounts/services/srp.ts index e8f825a9d..48c0f6ad8 100644 --- a/web/packages/accounts/services/srp.ts +++ b/web/packages/accounts/services/srp.ts @@ -2,7 +2,6 @@ import log from "@/next/log"; import { UserVerificationResponse } from "@ente/accounts/types/user"; import ComlinkCryptoWorker from "@ente/shared/crypto"; import { generateLoginSubKey } from "@ente/shared/crypto/helpers"; -import { logError } from "@ente/shared/sentry"; import InMemoryStore, { MS_KEYS } from "@ente/shared/storage/InMemoryStore"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { SRP, SrpClient } from "fast-srp-hap"; @@ -131,7 +130,7 @@ export const loginViaSRP = async ( log.debug(() => `srp server verify successful`); return rest; } catch (e) { - logError(e, "srp verify failed"); + log.error("srp verify failed", e); throw e; } }; diff --git a/web/packages/accounts/services/user.ts b/web/packages/accounts/services/user.ts index 6a2da8521..43d2f0883 100644 --- a/web/packages/accounts/services/user.ts +++ b/web/packages/accounts/services/user.ts @@ -1,12 +1,10 @@ -import ElectronAPIs from "@/next/electron"; +import log from "@/next/log"; import { Events, eventBus } from "@ente/shared/events"; -import { logError } from "@ente/shared/sentry"; import InMemoryStore from "@ente/shared/storage/InMemoryStore"; import { deleteAllCache } from "@ente/shared/storage/cacheStorage/helpers"; import { clearFiles } from "@ente/shared/storage/localForage/helpers"; import { clearData } from "@ente/shared/storage/localStorage"; import { clearKeys } from "@ente/shared/storage/sessionStorage"; -import isElectron from "is-electron"; import router from "next/router"; import { _logout } from "../api/user"; import { PAGES } from "../constants/pages"; @@ -22,42 +20,40 @@ export const logoutUser = async () => { InMemoryStore.clear(); } catch (e) { // ignore - logError(e, "clear InMemoryStore failed"); + log.error("clear InMemoryStore failed", e); } try { clearKeys(); } catch (e) { - logError(e, "clearKeys failed"); + log.error("clearKeys failed", e); } try { clearData(); } catch (e) { - logError(e, "clearData failed"); + log.error("clearData failed", e); } try { await deleteAllCache(); } catch (e) { - logError(e, "deleteAllCache failed"); + log.error("deleteAllCache failed", e); } try { await clearFiles(); } catch (e) { - logError(e, "clearFiles failed"); + log.error("clearFiles failed", e); } - if (isElectron()) { - try { - ElectronAPIs.clearElectronStore(); - } catch (e) { - logError(e, "clearElectronStore failed"); - } + try { + globalThis.electron?.clearElectronStore(); + } catch (e) { + log.error("clearElectronStore failed", e); } try { eventBus.emit(Events.LOGOUT); } catch (e) { - logError(e, "Error in logout handlers"); + log.error("Error in logout handlers", e); } router.push(PAGES.ROOT); } catch (e) { - logError(e, "logoutUser failed"); + log.error("logoutUser failed", e); } }; diff --git a/web/packages/next/electron.ts b/web/packages/next/electron.ts index 9f02bf799..d7af86c47 100644 --- a/web/packages/next/electron.ts +++ b/web/packages/next/electron.ts @@ -1,10 +1,25 @@ -import type { ElectronAPIsType } from "./types/ipc"; +import type { Electron } from "./types/ipc"; -// TODO (MR): -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const ElectronAPIs = (globalThis as unknown as any)[ - // eslint-disable-next-line @typescript-eslint/dot-notation, @typescript-eslint/no-unsafe-member-access - "ElectronAPIs" -] as ElectronAPIsType; - -export default ElectronAPIs; +/** + * A wrapper over a non-null assertion of `globalThis.electron`. + * + * This is useful where we have previously verified that the code path in which + * we're running only executes when we're in electron (usually by directly + * checking that `globalThis.electron` is defined somewhere up the chain). + * + * Generally, this should not be required - the check and the use should be + * colocated, or the unwrapped non-null value saved somewhere. But sometimes + * doing so requires code refactoring, so as an escape hatch we provide this + * convenience function. + * + * It will throw if `globalThis.electron` is undefined. + * + * @see `global-electron.d.ts`. + */ +export const ensureElectron = (): Electron => { + const et = globalThis.electron; + if (et) return et; + throw new Error( + "Attempting to assert globalThis.electron in a non-electron context", + ); +}; diff --git a/web/packages/next/global-electron.d.ts b/web/packages/next/global-electron.d.ts new file mode 100644 index 000000000..05a6838e1 --- /dev/null +++ b/web/packages/next/global-electron.d.ts @@ -0,0 +1,22 @@ +import type { Electron } from "./types/ipc"; + +/** + * Extend the global object's (`globalThis`) interface to state that it can + * potentially hold a property called `electron`. It will be injected by our + * preload.js script when we're running in the context of our desktop app. + */ +declare global { + /** + * Extra, desktop specific, APIs provided by our Node.js layer. + * + * This property will defined only when we're running inside our desktop + * (Electron) app. It will expose a bunch of functions (see + * {@link Electron}) that allow us to communicate with the Node.js layer of + * our desktop app. + */ + // This needs to be a var for it to be recognized as a property of + // globalThis, so we unfortunately need to hush eslint for the next line. + // + // eslint-disable-next-line no-var + var electron: Electron | undefined; +} diff --git a/web/packages/next/i18n.ts b/web/packages/next/i18n.ts index 11a0e532e..913ecf746 100644 --- a/web/packages/next/i18n.ts +++ b/web/packages/next/i18n.ts @@ -1,5 +1,5 @@ import { isDevBuild } from "@/next/env"; -import { logError } from "@/utils/logging"; +import log from "@/next/log"; import { includes } from "@/utils/type-guards"; import { getUserLocales } from "get-user-locale"; import i18n from "i18next"; @@ -154,7 +154,7 @@ const savedLocaleStringMigratingIfNeeded = (): SupportedLocale | undefined => { } catch (e) { // Not a valid JSON, or not in the format we expected it. This shouldn't // have happened, we're the only one setting it. - logError("Failed to parse locale obtained from local storage", e); + log.error("Failed to parse locale obtained from local storage", e); // Also remove the old key, it is not parseable by us anymore. localStorage.removeItem("locale"); return undefined; @@ -241,7 +241,7 @@ export const getLocaleInUse = (): SupportedLocale => { return locale; } else { // This shouldn't have happened. Log an error to attract attention. - logError( + log.error( `Expected the i18next locale to be one of the supported values, but instead found ${locale}`, ); return defaultLocale; diff --git a/web/packages/next/log-web.ts b/web/packages/next/log-web.ts index bd4b63666..093a2065c 100644 --- a/web/packages/next/log-web.ts +++ b/web/packages/next/log-web.ts @@ -1,5 +1,5 @@ import { isDevBuild } from "@/next/env"; -import { addLogLine } from "@ente/shared/logging"; +import log from "@/next/log"; /** * Log a standard startup banner. @@ -15,7 +15,7 @@ export const logStartupBanner = (appId: string, userId?: number) => { const sha = process.env.GIT_SHA; const buildId = isDevBuild ? "dev " : sha ? `git ${sha} ` : ""; - addLogLine(`Starting ente-${appIdL}-web ${buildId}uid ${userId ?? 0}`); + log.info(`Starting ente-${appIdL}-web ${buildId}uid ${userId ?? 0}`); }; interface LogEntry { diff --git a/web/packages/next/log.ts b/web/packages/next/log.ts index 9d5818443..3dadbd288 100644 --- a/web/packages/next/log.ts +++ b/web/packages/next/log.ts @@ -1,6 +1,4 @@ import { inWorker } from "@/next/env"; -import isElectron from "is-electron"; -import ElectronAPIs from "./electron"; import { isDevBuild } from "./env"; import { logToDisk as webLogToDisk } from "./log-web"; import { workerBridge } from "./worker/worker-bridge"; @@ -12,7 +10,8 @@ import { workerBridge } from "./worker/worker-bridge"; * in the log that is saved on disk. */ export const logToDisk = (message: string) => { - if (isElectron()) ElectronAPIs.logToDisk(message); + const electron = globalThis.electron; + if (electron) electron.logToDisk(message); else if (inWorker()) workerLogToDisk(message); else webLogToDisk(message); }; diff --git a/web/packages/next/tsconfig.json b/web/packages/next/tsconfig.json index 10fe5229c..9c7ee3ef6 100644 --- a/web/packages/next/tsconfig.json +++ b/web/packages/next/tsconfig.json @@ -5,5 +5,5 @@ "lib": ["ESnext", "DOM", "DOM.Iterable", "WebWorker"] }, /* Typecheck all files with the given extensions (here or in subfolders) */ - "include": ["**/*.ts", "**/*.tsx"] + "include": ["**/*.ts", "**/*.tsx", "**/*.d.ts", "global-electron.d.ts"] } diff --git a/web/packages/next/types/ipc.ts b/web/packages/next/types/ipc.ts index 46c4a4293..d13c775f4 100644 --- a/web/packages/next/types/ipc.ts +++ b/web/packages/next/types/ipc.ts @@ -27,17 +27,19 @@ export enum PICKED_UPLOAD_TYPE { } /** - * Extra APIs provided by the Node.js layer when our code is running in Electron + * Extra APIs provided by our Node.js layer when our code is running inside our + * desktop (Electron) app. * * This list is manually kept in sync with `desktop/src/preload.ts`. In case of * a mismatch, the types may lie. See also: [Note: types.ts <-> preload.ts <-> * ipc.ts] * * These extra objects and functions will only be available when our code is - * running as the renderer process in Electron. So something in the code path - * should check for `isElectron() == true` before invoking these. + * running as the renderer process in Electron. These can be accessed by using + * the `electron` property of the window (See @{link globalElectron} for a + * systematic way of getting at that). */ -export interface ElectronAPIsType { +export interface Electron { // - General /** Return the version of the desktop app. */ diff --git a/web/packages/next/worker/comlink-worker.ts b/web/packages/next/worker/comlink-worker.ts index af384bf59..033c79fa8 100644 --- a/web/packages/next/worker/comlink-worker.ts +++ b/web/packages/next/worker/comlink-worker.ts @@ -1,4 +1,4 @@ -import ElectronAPIs from "@/next/electron"; +import { ensureElectron } from "@/next/electron"; import log, { logToDisk } from "@/next/log"; import { expose, wrap, type Remote } from "comlink"; @@ -45,7 +45,7 @@ export class ComlinkWorker InstanceType> { const workerBridge = { logToDisk, convertToJPEG: (inputFileData: Uint8Array, filename: string) => - ElectronAPIs.convertToJPEG(inputFileData, filename), + ensureElectron().convertToJPEG(inputFileData, filename), }; export type WorkerBridge = typeof workerBridge; diff --git a/web/packages/shared/components/Directory/changeOption.tsx b/web/packages/shared/components/Directory/changeOption.tsx deleted file mode 100644 index f846e9ba9..000000000 --- a/web/packages/shared/components/Directory/changeOption.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import OverflowMenu from "@ente/shared/components/OverflowMenu/menu"; -import { OverflowMenuOption } from "@ente/shared/components/OverflowMenu/option"; -import FolderIcon from "@mui/icons-material/Folder"; -import MoreHoriz from "@mui/icons-material/MoreHoriz"; -import { t } from "i18next"; - -export default function ChangeDirectoryOption({ - changeExportDirectory: changeDirectory, -}) { - return ( - } - > - } - > - {t("CHANGE_FOLDER")} - - - ); -} diff --git a/web/packages/shared/components/Directory/index.tsx b/web/packages/shared/components/Directory/index.tsx deleted file mode 100644 index 154db456e..000000000 --- a/web/packages/shared/components/Directory/index.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import ElectronAPIs from "@/next/electron"; -import LinkButton from "@ente/shared/components/LinkButton"; -import { logError } from "@ente/shared/sentry"; -import { Tooltip } from "@mui/material"; -import { styled } from "@mui/material/styles"; - -const DirectoryPathContainer = styled(LinkButton)( - ({ width }) => ` - width: ${width}px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - /* Beginning of string */ - direction: rtl; - text-align: left; -`, -); - -export const DirectoryPath = ({ width, path }) => { - const handleClick = async () => { - try { - await ElectronAPIs.openDirectory(path); - } catch (e) { - logError(e, "openDirectory failed"); - } - }; - return ( - - - {path} - - - ); -}; diff --git a/web/packages/shared/components/Menu/EnteMenuItem.tsx b/web/packages/shared/components/Menu/EnteMenuItem.tsx index a3b6cb7b8..087971d02 100644 --- a/web/packages/shared/components/Menu/EnteMenuItem.tsx +++ b/web/packages/shared/components/Menu/EnteMenuItem.tsx @@ -12,18 +12,11 @@ import { import React from "react"; import { CaptionedText } from "../CaptionedText"; import PublicShareSwitch from "../Collections/CollectionShare/publicShare/switch"; -import ChangeDirectoryOption from "../Directory/changeOption"; interface Iprops { onClick: () => void; color?: ButtonProps["color"]; - variant?: - | "primary" - | "captioned" - | "toggle" - | "secondary" - | "mini" - | "path"; + variant?: "primary" | "captioned" | "toggle" | "secondary" | "mini"; fontWeight?: TypographyProps["fontWeight"]; startIcon?: React.ReactNode; endIcon?: React.ReactNode; @@ -49,14 +42,14 @@ export function EnteMenuItem({ disabled = false, }: Iprops) { const handleButtonClick = () => { - if (variant === "path" || variant === "toggle") { + if (variant === "toggle") { return; } onClick(); }; const handleIconClick = () => { - if (variant !== "path" && variant !== "toggle") { + if (variant !== "toggle") { return; } onClick(); @@ -116,11 +109,6 @@ export function EnteMenuItem({ onClick={handleIconClick} /> )} - {variant === "path" && ( - - )} diff --git a/web/packages/shared/components/VerifyMasterPasswordForm.tsx b/web/packages/shared/components/VerifyMasterPasswordForm.tsx index 5865d949f..155ab5526 100644 --- a/web/packages/shared/components/VerifyMasterPasswordForm.tsx +++ b/web/packages/shared/components/VerifyMasterPasswordForm.tsx @@ -1,14 +1,12 @@ -import { logError } from "@ente/shared/sentry"; -import SingleInputForm, { - SingleInputFormProps, -} from "../components/SingleInputForm"; - -import { CustomError } from "../error"; - +import log from "@/next/log"; import { SRPAttributes } from "@ente/accounts/types/srp"; import { ButtonProps, Input } from "@mui/material"; import { t } from "i18next"; +import SingleInputForm, { + SingleInputFormProps, +} from "../components/SingleInputForm"; import ComlinkCryptoWorker from "../crypto"; +import { CustomError } from "../error"; import { KeyAttributes, User } from "../user/types"; export interface VerifyMasterPasswordFormProps { @@ -59,7 +57,7 @@ export default function VerifyMasterPasswordForm({ ); } } catch (e) { - logError(e, "failed to derive key"); + log.error("failed to derive key", e); throw Error(CustomError.WEAK_DEVICE); } if (!keyAttributes && typeof getKeyAttributes === "function") { @@ -76,7 +74,7 @@ export default function VerifyMasterPasswordForm({ ); callback(key, kek, keyAttributes, passphrase); } catch (e) { - logError(e, "user entered a wrong password"); + log.error("user entered a wrong password", e); throw Error(CustomError.INCORRECT_PASSWORD); } } catch (e) { @@ -85,7 +83,7 @@ export default function VerifyMasterPasswordForm({ // two factor enabled, user has been redirected to two factor page return; } - logError(e, "failed to verify passphrase"); + log.error("failed to verify passphrase", e); switch (e.message) { case CustomError.WEAK_DEVICE: setFieldError(t("WEAK_DEVICE")); diff --git a/web/packages/shared/crypto/helpers.ts b/web/packages/shared/crypto/helpers.ts index 908c255d4..9250b4ab7 100644 --- a/web/packages/shared/crypto/helpers.ts +++ b/web/packages/shared/crypto/helpers.ts @@ -1,14 +1,11 @@ -import ElectronAPIs from "@/next/electron"; +import log from "@/next/log"; import { setRecoveryKey } from "@ente/accounts/api/user"; -import { logError } from "@ente/shared/sentry"; import { LS_KEYS, getData, setData } from "@ente/shared/storage/localStorage"; import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { SESSION_KEYS, setKey } from "@ente/shared/storage/sessionStorage"; import { getActualKey } from "@ente/shared/user"; import { KeyAttributes } from "@ente/shared/user/types"; -import isElectron from "is-electron"; import ComlinkCryptoWorker from "."; -import { addLogLine } from "../logging"; const LOGIN_SUB_KEY_LENGTH = 32; const LOGIN_SUB_KEY_ID = 1; @@ -104,13 +101,9 @@ export const saveKeyInSessionStore = async ( const sessionKeyAttributes = await cryptoWorker.generateKeyAndEncryptToB64(key); setKey(keyType, sessionKeyAttributes); - addLogLine("fromDesktop", fromDesktop); - if ( - isElectron() && - !fromDesktop && - keyType === SESSION_KEYS.ENCRYPTION_KEY - ) { - ElectronAPIs.setEncryptionKey(key); + const electron = globalThis.electron; + if (electron && !fromDesktop && keyType === SESSION_KEYS.ENCRYPTION_KEY) { + electron.setEncryptionKey(key); } }; @@ -146,7 +139,7 @@ export const getRecoveryKey = async () => { return recoveryKey; } catch (e) { console.log(e); - logError(e, "getRecoveryKey failed"); + log.error("getRecoveryKey failed", e); throw e; } }; diff --git a/web/packages/shared/logging/index.ts b/web/packages/shared/logging/index.ts deleted file mode 100644 index b4d1373cf..000000000 --- a/web/packages/shared/logging/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import log from "@/next/log"; - -export function addLogLine( - msg: string | number | boolean, - ...optionalParams: (string | number | boolean)[] -) { - const completeLog = [msg, ...optionalParams].join(" "); - log.info(completeLog); -} diff --git a/web/packages/shared/network/HTTPService.ts b/web/packages/shared/network/HTTPService.ts index ce60537ee..350f7f01d 100644 --- a/web/packages/shared/network/HTTPService.ts +++ b/web/packages/shared/network/HTTPService.ts @@ -1,7 +1,5 @@ -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import axios, { AxiosRequestConfig, AxiosResponse } from "axios"; - import { ApiError, CustomError, isApiErrorResponse } from "../error"; interface IHTTPHeaders { @@ -28,14 +26,17 @@ class HTTPService { // that falls out of the range of 2xx if (isApiErrorResponse(response.data)) { const responseData = response.data; - logError(error, "HTTP Service Error", { - url: config.url, - method: config.method, - xRequestId: response.headers["x-request-id"], - httpStatus: response.status, - errMessage: responseData.message, - errCode: responseData.code, - }); + log.error( + `HTTP Service Error - ${JSON.stringify({ + url: config.url, + method: config.method, + xRequestId: response.headers["x-request-id"], + httpStatus: response.status, + errMessage: responseData.message, + errCode: responseData.code, + })}`, + error, + ); apiError = new ApiError( responseData.message, responseData.code, @@ -56,30 +57,30 @@ class HTTPService { ); } } - logError(apiError, "HTTP Service Error", { - url: config.url, - method: config.method, - cfRay: response.headers["cf-ray"], - xRequestId: response.headers["x-request-id"], - httpStatus: response.status, - }); + log.error( + `HTTP Service Error - ${JSON.stringify({ + url: config.url, + method: config.method, + cfRay: response.headers["cf-ray"], + xRequestId: response.headers["x-request-id"], + httpStatus: response.status, + })}`, + apiError, + ); throw apiError; } else if (error.request) { // The request was made but no response was received // `error.request` is an instance of XMLHttpRequest in the browser and an instance of // http.ClientRequest in node.js - addLogLine( - "request failed- no response", - `url: ${config.url}`, - `method: ${config.method}`, + log.info( + `request failed - no response (${config.method} ${config.url}`, ); return Promise.reject(error); } else { - // Something happened in setting up the request that triggered an Error - addLogLine( - "request failed- axios error", - `url: ${config.url}`, - `method: ${config.method}`, + // Something happened in setting up the request that + // triggered an Error + log.info( + `request failed - axios error (${config.method} ${config.url}`, ); return Promise.reject(error); } diff --git a/web/packages/shared/network/cast.ts b/web/packages/shared/network/cast.ts index 82ba61af2..b240eab32 100644 --- a/web/packages/shared/network/cast.ts +++ b/web/packages/shared/network/cast.ts @@ -1,5 +1,5 @@ +import log from "@/next/log"; import { ApiError } from "../error"; -import { logError } from "../sentry"; import { getToken } from "../storage/localStorage/helpers"; import HTTPService from "./HTTPService"; import { getEndpoint } from "./api"; @@ -14,7 +14,7 @@ class CastGateway { `${getEndpoint()}/cast/cast-data/${code}`, ); } catch (e) { - logError(e, "failed to getCastData"); + log.error("failed to getCastData", e); throw e; } return resp.data.encCastData; @@ -32,7 +32,7 @@ class CastGateway { }, ); } catch (e) { - logError(e, "removeAllTokens failed"); + log.error("removeAllTokens failed", e); // swallow error } } @@ -52,7 +52,7 @@ class CastGateway { if (e instanceof ApiError && e.httpStatusCode === 404) { return ""; } - logError(e, "failed to getPublicKey"); + log.error("failed to getPublicKey", e); throw e; } return resp.data.publicKey; diff --git a/web/packages/shared/sentry/index.ts b/web/packages/shared/sentry/index.ts deleted file mode 100644 index 2dae035b7..000000000 --- a/web/packages/shared/sentry/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ApiError } from "@ente/shared/error"; -import { addLogLine } from "@ente/shared/logging"; - -/** Deprecated: Use `logError` from `@/utils/logging` */ -export const logError = async ( - error: any, - msg: string, - info?: Record, - skipAddLogLine = false, -) => { - if (skipAddLogLine) return; - - if (error instanceof ApiError) { - addLogLine(`error: ${error?.name} ${error?.message} - msg: ${msg} errorCode: ${JSON.stringify(error?.errCode)} - httpStatusCode: ${JSON.stringify(error?.httpStatusCode)} ${ - info ? `info: ${JSON.stringify(info)}` : "" - } - ${error?.stack}`); - } else { - addLogLine( - `error: ${error?.name} ${error?.message} - msg: ${msg} ${info ? `info: ${JSON.stringify(info)}` : ""} - ${error?.stack}`, - ); - } -}; diff --git a/web/packages/shared/storage/cacheStorage/helpers.ts b/web/packages/shared/storage/cacheStorage/helpers.ts index b95929106..b306d5683 100644 --- a/web/packages/shared/storage/cacheStorage/helpers.ts +++ b/web/packages/shared/storage/cacheStorage/helpers.ts @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { CacheStorageService } from "."; import { CACHES } from "./constants"; import { LimitedCache } from "./types"; @@ -50,6 +50,6 @@ export async function deleteAllCache() { await CacheStorageService.delete(CACHES.FACE_CROPS); await CacheStorageService.delete(CACHES.FILES); } catch (e) { - logError(e, "deleteAllCache failed"); // log and ignore + log.error("deleteAllCache failed", e); // log and ignore } } diff --git a/web/packages/shared/storage/cacheStorage/index.ts b/web/packages/shared/storage/cacheStorage/index.ts index 9271ae7f5..a70bf0927 100644 --- a/web/packages/shared/storage/cacheStorage/index.ts +++ b/web/packages/shared/storage/cacheStorage/index.ts @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; import { CacheStorageFactory } from "./factory"; const SecurityError = "SecurityError"; @@ -15,7 +15,7 @@ async function openCache(cacheName: string, cacheLimit?: number) { // no-op } else { // log and ignore, we don't want to break the caller flow, when cache is not available - logError(e, "openCache failed"); + log.error("openCache failed", e); } } } @@ -28,7 +28,7 @@ async function deleteCache(cacheName: string) { // no-op } else { // log and ignore, we don't want to break the caller flow, when cache is not available - logError(e, "deleteCache failed"); + log.error("deleteCache failed", e); } } } diff --git a/web/packages/shared/storage/localStorage/index.ts b/web/packages/shared/storage/localStorage/index.ts index b84f40e7c..70b9687cd 100644 --- a/web/packages/shared/storage/localStorage/index.ts +++ b/web/packages/shared/storage/localStorage/index.ts @@ -1,4 +1,4 @@ -import { logError } from "@ente/shared/sentry"; +import log from "@/next/log"; export enum LS_KEYS { USER = "user", @@ -57,7 +57,7 @@ export const getData = (key: LS_KEYS) => { const data = localStorage.getItem(key); return data && JSON.parse(data); } catch (e) { - logError(e, "Failed to Parse JSON for key " + key); + log.error(`Failed to Parse JSON for key ${key}`, e); } }; diff --git a/web/packages/utils/logging.ts b/web/packages/utils/logging.ts deleted file mode 100644 index cd9c4b53b..000000000 --- a/web/packages/utils/logging.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Log an error - * - * The {@link message} property describes what went wrong. Generally (but not - * always) in such situations we also have an "error" object that has specific - * details about the issue - that gets passed as the second parameter. - * - * Note that the "error" {@link e} is not typed. This is because in JavaScript - * any arbitrary value can be thrown. So this function allows us to pass it an - * arbitrary value as the error, and will internally figure out how best to deal - * with it. - * - * Where and how this error gets logged is dependent on where this code is - * running. The default implementation logs a string to the console, but in - * practice the layers above us will use the hooks provided in this file to - * route and show this error elsewhere. - * - * TODO (MR): Currently this is a placeholder function to funnel error logs - * through. This needs to do what the existing logError in @ente/shared does, - * but it cannot have a direct Electron dependency here. For now, we just - * log on the console. - */ -export const logError = (message: string, e?: unknown) => { - if (e === undefined || e === null) { - console.error(message); - return; - } - - let es: string; - if (e instanceof Error) { - // In practice, we expect ourselves to be called with Error objects, so - // this is the happy path so to say. - es = `${e.name}: ${e.message}\n${e.stack}`; - } else { - // For the rest rare cases, use the default string serialization of e. - es = String(e); - } - - // TODO(MR): Use addLogLine - console.error(`${message}: ${es}`); -};