mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-01-12 00:06:29 +08:00
perf: Optimize supervisor log reading (#11545)
Refs https://github.com/1Panel-dev/1Panel/issues/11515
This commit is contained in:
@@ -658,6 +658,9 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
|
||||
configPath = pathSet.Value
|
||||
}
|
||||
logFilePath, _ = ini_conf.GetIniValue(configPath, "supervisord", "logfile")
|
||||
case constant.Supervisor:
|
||||
logDir := path.Join(global.Dir.DataDir, "tools", "supervisord", "log")
|
||||
logFilePath = path.Join(logDir, req.Name)
|
||||
}
|
||||
|
||||
file, err := os.Open(logFilePath)
|
||||
|
||||
@@ -1,25 +1,12 @@
|
||||
<template>
|
||||
<DrawerPro
|
||||
v-model="open"
|
||||
:header="title"
|
||||
:header="$t('website.source')"
|
||||
@close="handleClose"
|
||||
:size="globalStore.isFullScreen ? 'full' : 'large'"
|
||||
:fullScreen="true"
|
||||
>
|
||||
<template #content>
|
||||
<div v-if="req.file != 'config'">
|
||||
<el-tabs v-model="req.file" type="card" @tab-click="handleChange">
|
||||
<el-tab-pane :label="$t('logs.runLog')" name="out.log"></el-tab-pane>
|
||||
<el-tab-pane :label="$t('logs.errLog')" name="err.log"></el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-checkbox border v-model="tailLog" class="float-left" @change="changeTail">
|
||||
{{ $t('commons.button.watch') }}
|
||||
</el-checkbox>
|
||||
<el-button class="ml-5" @click="cleanLog" icon="Delete">
|
||||
{{ $t('commons.button.clean') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<br />
|
||||
<div v-loading="loading">
|
||||
<CodemirrorPro class="mt-5" v-model="content" :heightDiff="400"></CodemirrorPro>
|
||||
</div>
|
||||
@@ -28,19 +15,17 @@
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
|
||||
<el-button type="primary" :disabled="loading" @click="submit()" v-if="req.file === 'config'">
|
||||
<el-button type="primary" :disabled="loading" @click="submit()">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</DrawerPro>
|
||||
<OpDialog ref="opRef" @search="getContent" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onUnmounted, reactive, ref } from 'vue';
|
||||
import { operateSupervisorProcessFile } from '@/api/modules/host-tool';
|
||||
import i18n from '@/lang';
|
||||
import { TabsPaneContext } from 'element-plus';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { GlobalStore } from '@/store';
|
||||
const globalStore = GlobalStore();
|
||||
@@ -55,10 +40,6 @@ const req = reactive({
|
||||
operate: '',
|
||||
content: '',
|
||||
});
|
||||
const title = ref('');
|
||||
const opRef = ref();
|
||||
|
||||
let timer: NodeJS.Timer | null = null;
|
||||
|
||||
const em = defineEmits(['search']);
|
||||
|
||||
@@ -73,21 +54,6 @@ const getContent = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const handleChange = (tab: TabsPaneContext) => {
|
||||
req.file = tab.props.name.toString();
|
||||
getContent();
|
||||
};
|
||||
|
||||
const changeTail = () => {
|
||||
if (tailLog.value) {
|
||||
timer = setInterval(() => {
|
||||
getContent();
|
||||
}, 1000 * 5);
|
||||
} else {
|
||||
onCloseLog();
|
||||
}
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
content.value = '';
|
||||
open.value = false;
|
||||
@@ -117,26 +83,12 @@ const acceptParams = (name: string, file: string, operate: string) => {
|
||||
req.file = file;
|
||||
req.operate = operate;
|
||||
|
||||
title.value = file == 'config' ? i18n.global.t('website.source') : i18n.global.t('commons.button.log');
|
||||
getContent();
|
||||
open.value = true;
|
||||
};
|
||||
|
||||
const cleanLog = async () => {
|
||||
let log = req.file === 'out.log' ? i18n.global.t('logs.runLog') : i18n.global.t('logs.errLog');
|
||||
opRef.value.acceptParams({
|
||||
title: i18n.global.t('commons.button.clean'),
|
||||
names: [req.name],
|
||||
msg: i18n.global.t('commons.msg.operatorHelper', [log, i18n.global.t('commons.button.clean')]),
|
||||
api: operateSupervisorProcessFile,
|
||||
params: { name: req.name, operate: 'clear', file: req.file },
|
||||
});
|
||||
};
|
||||
|
||||
const onCloseLog = async () => {
|
||||
tailLog.value = false;
|
||||
clearInterval(Number(timer));
|
||||
timer = null;
|
||||
};
|
||||
|
||||
onUnmounted(() => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<el-card v-if="showStopped" class="mask-prompt">
|
||||
<span>{{ $t('tool.supervisor.notStartWarn') }}</span>
|
||||
</el-card>
|
||||
<LayoutContent :title="$t('tool.supervisor.list', 2)" v-loading="loading">
|
||||
<LayoutContent :title="$t(' tool.supervisor.list', 2)" v-loading="loading">
|
||||
<template #prompt v-if="!globalStore.isFxplay">
|
||||
<el-alert type="info" :closable="false">
|
||||
<template #title>
|
||||
@@ -157,11 +157,14 @@
|
||||
</LayoutContent>
|
||||
<Create ref="createRef" @close="search"></Create>
|
||||
<File ref="fileRef" @search="search"></File>
|
||||
<Log ref="logRef" @close="search" />
|
||||
<ProcessDetail ref="processDetailRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Log from './log/index.vue';
|
||||
|
||||
import SuperVisorStatus from './status/index.vue';
|
||||
import { ref } from 'vue';
|
||||
import ConfigSuperVisor from './config/index.vue';
|
||||
@@ -181,6 +184,7 @@ const loading = ref(false);
|
||||
const setSuperVisor = ref(false);
|
||||
const createRef = ref();
|
||||
const fileRef = ref();
|
||||
const logRef = ref();
|
||||
const processDetailRef = ref();
|
||||
const data = ref();
|
||||
const maskShow = ref(true);
|
||||
@@ -324,6 +328,10 @@ const getFile = (name: string, file: string) => {
|
||||
fileRef.value.acceptParams(name, file, 'get');
|
||||
};
|
||||
|
||||
const openLog = (name: string) => {
|
||||
logRef.value.acceptParams(name);
|
||||
};
|
||||
|
||||
const edit = (row: HostTool.SupersivorProcess) => {
|
||||
createRef.value.acceptParams('update', row);
|
||||
};
|
||||
@@ -344,7 +352,7 @@ const buttons = [
|
||||
{
|
||||
label: i18n.global.t('commons.button.log'),
|
||||
click: function (row: HostTool.SupersivorProcess) {
|
||||
getFile(row.name, 'out.log');
|
||||
openLog(row.name);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
118
frontend/src/views/toolbox/supervisor/log/index.vue
Normal file
118
frontend/src/views/toolbox/supervisor/log/index.vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<DrawerPro
|
||||
v-model="open"
|
||||
:header="$t('commons.button.log') + ' - ' + supervisorName"
|
||||
@close="handleClose"
|
||||
:size="globalStore.isFullScreen ? 'full' : 'large'"
|
||||
:fullScreen="true"
|
||||
>
|
||||
<template #content>
|
||||
<el-tabs v-model="tab" type="card" @tab-click="handleChange">
|
||||
<el-tab-pane :label="$t('logs.runLog')" name="out.log"></el-tab-pane>
|
||||
<el-tab-pane :label="$t('logs.errLog')" name="err.log"></el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<LogFile
|
||||
:key="logKey"
|
||||
ref="logRef"
|
||||
v-if="openLog"
|
||||
:config="logConfig"
|
||||
v-model:loading="loading"
|
||||
v-model:has-content="hasContent"
|
||||
:height-diff="300"
|
||||
>
|
||||
<template #button>
|
||||
<el-button @click="cleanLog" icon="Delete" :disabled="hasContent === false">
|
||||
{{ $t('commons.button.clean') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</LogFile>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</DrawerPro>
|
||||
<OpDialog ref="opRef" @search="refreshLog" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import LogFile from '@/components/log/file/index.vue';
|
||||
|
||||
import { onUnmounted, reactive, ref } from 'vue';
|
||||
import { GlobalStore } from '@/store';
|
||||
import { operateSupervisorProcessFile } from '@/api/modules/host-tool';
|
||||
import i18n from '@/lang';
|
||||
import { TabsPaneContext } from 'element-plus';
|
||||
const globalStore = GlobalStore();
|
||||
|
||||
const logConfig = reactive({
|
||||
type: 'supervisor',
|
||||
id: undefined,
|
||||
name: '',
|
||||
colorMode: 'nginx',
|
||||
});
|
||||
const loading = ref(false);
|
||||
const open = ref(false);
|
||||
const tab = ref('out.log');
|
||||
const openLog = ref();
|
||||
const supervisorName = ref('');
|
||||
const opRef = ref();
|
||||
const logKey = ref(0);
|
||||
const hasContent = ref(false);
|
||||
|
||||
const em = defineEmits(['close']);
|
||||
|
||||
const handleChange = (tab: TabsPaneContext) => {
|
||||
openLog.value = false;
|
||||
logConfig.name = supervisorName.value + '.' + tab.props.name.toString();
|
||||
logKey.value++;
|
||||
openLog.value = true;
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
open.value = false;
|
||||
};
|
||||
|
||||
const acceptParams = (name: string) => {
|
||||
tab.value = 'out.log';
|
||||
supervisorName.value = name;
|
||||
logConfig.name = name + '.' + tab.value;
|
||||
open.value = true;
|
||||
openLog.value = true;
|
||||
};
|
||||
|
||||
const onCloseLog = async () => {
|
||||
em('close');
|
||||
};
|
||||
|
||||
const refreshLog = () => {
|
||||
logKey.value++;
|
||||
};
|
||||
|
||||
const cleanLog = async () => {
|
||||
let log = tab.value === 'out.log' ? i18n.global.t('logs.runLog') : i18n.global.t('logs.errLog');
|
||||
opRef.value.acceptParams({
|
||||
title: i18n.global.t('commons.button.clean'),
|
||||
names: [supervisorName.value],
|
||||
msg: i18n.global.t('commons.msg.operatorHelper', [log, i18n.global.t('commons.button.clean')]),
|
||||
api: operateSupervisorProcessFile,
|
||||
params: { name: supervisorName.value, operate: 'clear', file: tab.value },
|
||||
});
|
||||
};
|
||||
|
||||
onUnmounted(() => {
|
||||
onCloseLog();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.fullScreen {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user