mirror of
https://github.com/samuelncui/yatm.git
synced 2025-12-23 06:15:22 +00:00
feat: frontend use router
This commit is contained in:
@@ -96,15 +96,14 @@ func main() {
|
||||
fs := http.FileServer(http.Dir("./frontend/assets"))
|
||||
mux.Handle("/assets/", http.StripPrefix("/assets/", fs))
|
||||
|
||||
indexBuf, err := ioutil.ReadFile("./frontend/index.html")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
indexBuf = bytes.ReplaceAll(indexBuf, []byte("%%API_BASE%%"), []byte(fmt.Sprintf("%s/services", conf.Domain)))
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
indexBuf, err := ioutil.ReadFile("./frontend/index.html")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.Write(indexBuf)
|
||||
w.Write(bytes.ReplaceAll(indexBuf, []byte("%%API_BASE%%"), []byte(fmt.Sprintf("%s/services", conf.Domain))))
|
||||
})
|
||||
|
||||
srv := &http.Server{
|
||||
|
||||
@@ -84,7 +84,7 @@ func (a *jobArchiveExecutor) handle(ctx context.Context, param *entity.JobArchiv
|
||||
}
|
||||
|
||||
tools.Working()
|
||||
go tools.Wrap(ctx, func() {
|
||||
go tools.WrapWithLogger(ctx, a.logger, func() {
|
||||
defer tools.Done()
|
||||
if err := a.makeTape(tools.ShutdownContext, p.Device, p.Barcode, p.Name); err != nil {
|
||||
a.logger.WithContext(ctx).WithError(err).Errorf("make type has error, barcode= '%s' name= '%s'", p.Barcode, p.Name)
|
||||
@@ -246,7 +246,7 @@ func (a *jobArchiveExecutor) makeTape(ctx context.Context, device, barcode, name
|
||||
a.logger.WithContext(ctx).WithError(err).Warnf("open report file fail, barcode= '%s'", barcode)
|
||||
} else {
|
||||
defer reportFile.Close()
|
||||
tools.Wrap(ctx, func() {
|
||||
tools.WrapWithLogger(ctx, a.logger, func() {
|
||||
reportFile.Write([]byte(report.ToJSONString(false)))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -26,12 +26,16 @@
|
||||
"fast-text-encoding": "^1.0.6",
|
||||
"filesize": "^10.0.5",
|
||||
"format-duration": "^2.0.0",
|
||||
"localforage": "^1.10.0",
|
||||
"match-sorter": "^6.3.1",
|
||||
"moment": "^2.29.4",
|
||||
"react": "^18.2.0",
|
||||
"react-dnd": "^11.1.3",
|
||||
"react-dnd-html5-backend": "^11.1.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-is": "^18.2.0"
|
||||
"react-is": "^18.2.0",
|
||||
"react-router-dom": "^6.4.5",
|
||||
"sort-by": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@protobuf-ts/plugin": "^2.8.2",
|
||||
|
||||
74
frontend/pnpm-lock.yaml
generated
74
frontend/pnpm-lock.yaml
generated
@@ -23,6 +23,8 @@ specifiers:
|
||||
filesize: ^10.0.5
|
||||
format-duration: ^2.0.0
|
||||
less: ^4.1.3
|
||||
localforage: ^1.10.0
|
||||
match-sorter: ^6.3.1
|
||||
moment: ^2.29.4
|
||||
prettier: 2.7.1
|
||||
react: ^18.2.0
|
||||
@@ -30,6 +32,8 @@ specifiers:
|
||||
react-dnd-html5-backend: ^11.1.3
|
||||
react-dom: ^18.2.0
|
||||
react-is: ^18.2.0
|
||||
react-router-dom: ^6.4.5
|
||||
sort-by: ^1.2.0
|
||||
tsdef: ^0.0.14
|
||||
typescript: ^4.6.4
|
||||
vite: ^3.1.0
|
||||
@@ -51,12 +55,16 @@ dependencies:
|
||||
fast-text-encoding: 1.0.6
|
||||
filesize: 10.0.5
|
||||
format-duration: 2.0.0
|
||||
localforage: 1.10.0
|
||||
match-sorter: 6.3.1
|
||||
moment: 2.29.4
|
||||
react: 18.2.0
|
||||
react-dnd: 11.1.3_biqbaboplfbrettd7655fr4n2y
|
||||
react-dnd-html5-backend: 11.1.3
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
react-is: 18.2.0
|
||||
react-router-dom: 6.4.5_biqbaboplfbrettd7655fr4n2y
|
||||
sort-by: 1.2.0
|
||||
|
||||
devDependencies:
|
||||
'@protobuf-ts/plugin': 2.8.2
|
||||
@@ -1025,6 +1033,11 @@ packages:
|
||||
reselect: 4.1.6
|
||||
dev: false
|
||||
|
||||
/@remix-run/router/1.0.5:
|
||||
resolution: {integrity: sha512-my0Mycd+jruq/1lQuO5LBB6WTlL/e8DTCYWp44DfMTDcXz8DcTlgF0ISaLsGewt+ctHN+yA8xMq3q/N7uWJPug==}
|
||||
engines: {node: '>=14'}
|
||||
dev: false
|
||||
|
||||
/@types/classnames/2.3.1:
|
||||
resolution: {integrity: sha512-zeOWb0JGBoVmlQoznvqXbE0tEC/HONsnoUNH19Hc96NFsTAwTXbTqb8FMYkru1F/iqp7a18Ws3nWJvtA1sHD1A==}
|
||||
deprecated: This is a stub types definition. classnames provides its own type definitions, so you do not need this installed.
|
||||
@@ -1739,6 +1752,10 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/immediate/3.0.6:
|
||||
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
|
||||
dev: false
|
||||
|
||||
/immer/9.0.15:
|
||||
resolution: {integrity: sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==}
|
||||
dev: false
|
||||
@@ -1935,10 +1952,22 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/lie/3.1.1:
|
||||
resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==}
|
||||
dependencies:
|
||||
immediate: 3.0.6
|
||||
dev: false
|
||||
|
||||
/lines-and-columns/1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
dev: false
|
||||
|
||||
/localforage/1.10.0:
|
||||
resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==}
|
||||
dependencies:
|
||||
lie: 3.1.1
|
||||
dev: false
|
||||
|
||||
/lodash/4.17.21:
|
||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||
dev: false
|
||||
@@ -1967,6 +1996,13 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/match-sorter/6.3.1:
|
||||
resolution: {integrity: sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.6
|
||||
remove-accents: 0.4.2
|
||||
dev: false
|
||||
|
||||
/memoize-one/5.2.1:
|
||||
resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==}
|
||||
dev: false
|
||||
@@ -2029,6 +2065,11 @@ packages:
|
||||
engines: {node: '>= 10.12.0'}
|
||||
dev: false
|
||||
|
||||
/object-path/0.6.0:
|
||||
resolution: {integrity: sha512-fxrwsCFi3/p+LeLOAwo/wyRMODZxdGBtUlWRzsEpsUVrisZbEfZ21arxLGfaWfcnqb8oHPNihIb4XPE8CQPN5A==}
|
||||
engines: {node: '>=0.8.0'}
|
||||
dev: false
|
||||
|
||||
/parent-module/1.0.1:
|
||||
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -2225,6 +2266,29 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/react-router-dom/6.4.5_biqbaboplfbrettd7655fr4n2y:
|
||||
resolution: {integrity: sha512-a7HsgikBR0wNfroBHcZUCd9+mLRqZS8R5U1Z1mzLWxFXEkUT3vR1XXmSIVoVpxVX8Bar0nQYYYc9Yipq8dWwAA==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
react: '>=16.8'
|
||||
react-dom: '>=16.8'
|
||||
dependencies:
|
||||
'@remix-run/router': 1.0.5
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
react-router: 6.4.5_react@18.2.0
|
||||
dev: false
|
||||
|
||||
/react-router/6.4.5_react@18.2.0:
|
||||
resolution: {integrity: sha512-1RQJ8bM70YEumHIlNUYc6mFfUDoWa5EgPDenK/fq0bxD8DYpQUi/S6Zoft+9DBrh2xmtg92N5HMAJgGWDhKJ5Q==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
react: '>=16.8'
|
||||
dependencies:
|
||||
'@remix-run/router': 1.0.5
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/react-transition-group/4.4.5_biqbaboplfbrettd7655fr4n2y:
|
||||
resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
|
||||
peerDependencies:
|
||||
@@ -2294,6 +2358,10 @@ packages:
|
||||
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
|
||||
dev: false
|
||||
|
||||
/remove-accents/0.4.2:
|
||||
resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==}
|
||||
dev: false
|
||||
|
||||
/reselect/4.1.6:
|
||||
resolution: {integrity: sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ==}
|
||||
dev: false
|
||||
@@ -2360,6 +2428,12 @@ packages:
|
||||
nanoid: 2.1.11
|
||||
dev: false
|
||||
|
||||
/sort-by/1.2.0:
|
||||
resolution: {integrity: sha512-aRyW65r3xMnf4nxJRluCg0H/woJpksU1dQxRtXYzau30sNBOmf5HACpDd9MZDhKh7ALQ5FgSOfMPwZEtUmMqcg==}
|
||||
dependencies:
|
||||
object-path: 0.6.0
|
||||
dev: false
|
||||
|
||||
/source-map-js/1.0.2:
|
||||
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { useState, useCallback } from "react";
|
||||
import { ChangeEvent } from "react";
|
||||
import { Fragment, useCallback, ChangeEvent } from "react";
|
||||
import { Routes, Route, Link, useNavigate, Navigate, useLocation } from "react-router-dom";
|
||||
|
||||
import Tabs from "@mui/material/Tabs";
|
||||
import Tab from "@mui/material/Tab";
|
||||
@@ -13,62 +12,58 @@ import { JobsBrowser, JobsType } from "./jobs";
|
||||
import "./app.less";
|
||||
import { sleep } from "./api";
|
||||
import { Nullable } from "tsdef";
|
||||
import { Job } from "./entity";
|
||||
import { useEffect } from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
// import reactLogo from './assets/react.svg'
|
||||
// <img src={reactLogo} className="logo react" alt="React logo" />
|
||||
|
||||
const theme = createTheme({});
|
||||
|
||||
const typeToElement = (type: string) => {
|
||||
switch (type) {
|
||||
case FileBrowserType:
|
||||
return <FileBrowser />;
|
||||
case BackupType:
|
||||
return <BackupBrowser />;
|
||||
case JobsType:
|
||||
return <JobsBrowser />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
const Delay = ({ inner }: { inner: JSX.Element }) => {
|
||||
const [ok, setOK] = useState(false);
|
||||
useEffect(() => {
|
||||
setOK(false);
|
||||
(async () => {
|
||||
await sleep(0);
|
||||
setOK(true);
|
||||
})();
|
||||
return () => {
|
||||
setOK(false);
|
||||
};
|
||||
}, [inner]);
|
||||
|
||||
return ok ? inner : null;
|
||||
};
|
||||
|
||||
const App = () => {
|
||||
const [tabValue, setTabValue] = useState(FileBrowserType);
|
||||
const [inner, setInner] = useState<Nullable<JSX.Element>>(null);
|
||||
|
||||
const setType = useCallback(
|
||||
(newValue: string) => {
|
||||
(async () => {
|
||||
setTabValue(newValue);
|
||||
setInner(null);
|
||||
await sleep(0);
|
||||
setInner(typeToElement(newValue));
|
||||
})();
|
||||
},
|
||||
[setTabValue, setInner]
|
||||
);
|
||||
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const handleTabChange = useCallback(
|
||||
(_: ChangeEvent<{}>, newValue: string) => {
|
||||
setType(newValue);
|
||||
navigate("/" + newValue);
|
||||
},
|
||||
[setTabValue]
|
||||
[navigate]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setType(FileBrowserType);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div id="app">
|
||||
<ThemeProvider theme={theme}>
|
||||
<Tabs className="tabs" value={tabValue} onChange={handleTabChange} indicatorColor="secondary">
|
||||
<Tabs className="tabs" value={location.pathname.slice(1)} onChange={handleTabChange} indicatorColor="secondary">
|
||||
<Tab label="File" value={FileBrowserType} />
|
||||
<Tab label="Source" value={BackupType} />
|
||||
<Tab label="Jobs" value={JobsType} />
|
||||
</Tabs>
|
||||
<Routes>
|
||||
<Route path="/*">
|
||||
<Route path={FileBrowserType} element={<Delay inner={<FileBrowser />} />} />
|
||||
<Route path={BackupType} element={<Delay inner={<BackupBrowser />} />} />
|
||||
<Route path={JobsType} element={<Delay inner={<JobsBrowser />} />} />
|
||||
<Route path="*" element={<Navigate to={"/" + FileBrowserType} replace />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</ThemeProvider>
|
||||
{inner}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useState, useRef, useEffect, useMemo, useCallback } from "react";
|
||||
|
||||
import Grid from "@mui/material/Grid";
|
||||
import Box from "@mui/material/Box";
|
||||
import { FullFileBrowser, FileBrowserHandle, FileArray } from "chonky";
|
||||
import { FullFileBrowser, FileBrowserProps, FileBrowserHandle, FileArray } from "chonky";
|
||||
import { ChonkyActions, ChonkyFileActionData } from "chonky";
|
||||
|
||||
import "./app.less";
|
||||
@@ -32,7 +32,7 @@ const useDualSide = () => {
|
||||
return { instances, refreshAll };
|
||||
};
|
||||
|
||||
const useFileBrowser = (refreshAll: () => Promise<void>, openDetailModel: (detail: FileGetReply) => void) => {
|
||||
const useFileBrowser = (storageKey: string, refreshAll: () => Promise<void>, openDetailModel: (detail: FileGetReply) => void) => {
|
||||
const [files, setFiles] = useState<FileArray>(Array(1).fill(null));
|
||||
const [folderChain, setFolderChan] = useState<FileArray>([Root]);
|
||||
const currentID = useMemo(() => {
|
||||
@@ -48,15 +48,28 @@ const useFileBrowser = (refreshAll: () => Promise<void>, openDetailModel: (detai
|
||||
return last.id;
|
||||
}, [folderChain]);
|
||||
|
||||
const openFolder = useCallback((id: string) => {
|
||||
(async () => {
|
||||
const [file, folderChain] = await Promise.all([cli.fileGet({ id: BigInt(id) }).response, cli.fileListParents({ id: BigInt(id) }).response]);
|
||||
const openFolder = useCallback(async (id: string) => {
|
||||
const [file, folderChain] = await Promise.all([cli.fileGet({ id: BigInt(id) }).response, cli.fileListParents({ id: BigInt(id) }).response]);
|
||||
|
||||
setFiles(convertFiles(file.children));
|
||||
setFolderChan([Root, ...convertFiles(folderChain.parents)]);
|
||||
setFiles(convertFiles(file.children));
|
||||
setFolderChan([Root, ...convertFiles(folderChain.parents)]);
|
||||
localStorage.setItem(storageKey, id);
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const storagedID = localStorage.getItem(storageKey);
|
||||
if (storagedID) {
|
||||
try {
|
||||
await openFolder(storagedID);
|
||||
return;
|
||||
} catch (e) {
|
||||
console.log("open storaged id fail, err= ", e);
|
||||
}
|
||||
}
|
||||
|
||||
openFolder(Root.id);
|
||||
})();
|
||||
}, []);
|
||||
useEffect(() => openFolder(Root.id), []);
|
||||
|
||||
const onFileAction = useCallback(
|
||||
(data: ChonkyFileActionData) => {
|
||||
@@ -157,8 +170,8 @@ export const FileBrowser = () => {
|
||||
const { instances, refreshAll } = useDualSide();
|
||||
const { detail, openDetailModel, closeDetailModel } = useDetailModal();
|
||||
|
||||
const leftProps = useFileBrowser(refreshAll, openDetailModel);
|
||||
const rightProps = useFileBrowser(refreshAll, openDetailModel);
|
||||
const leftProps = useFileBrowser("file_browser:left:current_id", refreshAll, openDetailModel);
|
||||
const rightProps = useFileBrowser("file_browser:right:current_id", refreshAll, openDetailModel);
|
||||
|
||||
useEffect(() => {
|
||||
Object.values(instances).map((inst) => inst.current?.requestFileAction(ChonkyActions.ToggleHiddenFiles, {}));
|
||||
@@ -167,6 +180,7 @@ export const FileBrowser = () => {
|
||||
}, 10000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
useEffect(() => {});
|
||||
|
||||
return (
|
||||
<Box className="browser-box">
|
||||
|
||||
@@ -348,10 +348,18 @@ const ViewLogDialog = ({ jobID }: { jobID: bigint }) => {
|
||||
|
||||
const LogConsole = ({ jobId }: { jobId: bigint }) => {
|
||||
const [log, setLog] = useState<string>("");
|
||||
const bottom = useRef(null);
|
||||
const refreshLog = useCallback(async () => {
|
||||
const reply = await cli.jobGetLog({ jobId, offset: BigInt(log.length) }).response;
|
||||
setLog(log + new TextDecoder().decode(reply.logs));
|
||||
}, [log, setLog]);
|
||||
|
||||
if (log.length === 0 && reply.logs.length > 0 && bottom && bottom.current) {
|
||||
await sleep(10);
|
||||
(bottom.current as HTMLElement).scrollIntoView(true);
|
||||
await sleep(10);
|
||||
(bottom.current as HTMLElement).parentElement?.scrollBy(0, 100);
|
||||
}
|
||||
}, [log, setLog, bottom]);
|
||||
useEffect(() => {
|
||||
let closed = false;
|
||||
(async () => {
|
||||
@@ -366,7 +374,12 @@ const LogConsole = ({ jobId }: { jobId: bigint }) => {
|
||||
};
|
||||
}, [refreshLog]);
|
||||
|
||||
return <pre>{log || "loading..."}</pre>;
|
||||
return (
|
||||
<Fragment>
|
||||
<pre>{log || "loading..."}</pre>
|
||||
<div ref={bottom} />
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const ArchiveViewFilesDialog = ({ sources }: { sources: SourceState[] }) => {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import App from "./app";
|
||||
import "./index.css";
|
||||
|
||||
import "./init";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
||||
<App />
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
);
|
||||
|
||||
@@ -4,7 +4,6 @@ import react from "@vitejs/plugin-react";
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ command, mode }) => {
|
||||
const env = loadEnv(mode, process.cwd(), "");
|
||||
console.log(env);
|
||||
|
||||
return {
|
||||
plugins: [react()],
|
||||
|
||||
@@ -9,6 +9,10 @@ import (
|
||||
)
|
||||
|
||||
func Wrap(ctx context.Context, f func()) {
|
||||
WrapWithLogger(ctx, logrus.StandardLogger(), f)
|
||||
}
|
||||
|
||||
func WrapWithLogger(ctx context.Context, logger *logrus.Logger, f func()) {
|
||||
defer func() {
|
||||
e := recover()
|
||||
if e == nil {
|
||||
@@ -23,7 +27,7 @@ func Wrap(ctx context.Context, f func()) {
|
||||
err = fmt.Errorf("%v", err)
|
||||
}
|
||||
|
||||
logrus.WithContext(ctx).WithError(err).Errorf("panic: %s", debug.Stack())
|
||||
logger.WithContext(ctx).WithError(err).Errorf("panic: %s", debug.Stack())
|
||||
}()
|
||||
|
||||
f()
|
||||
|
||||
Reference in New Issue
Block a user