2022-11-04 19:02:15 +08:00
|
|
|
<template>
|
|
|
|
<div>
|
2023-08-09 16:32:12 +08:00
|
|
|
<div style="display: flex; flex-wrap: wrap">
|
2023-08-17 16:10:09 +08:00
|
|
|
<el-select @change="searchLogs" v-model="logSearch.mode" style="width: 150px">
|
2023-06-14 14:16:13 +08:00
|
|
|
<template #prefix>{{ $t('container.fetch') }}</template>
|
2022-11-04 19:02:15 +08:00
|
|
|
<el-option v-for="item in timeOptions" :key="item.label" :value="item.value" :label="item.label" />
|
|
|
|
</el-select>
|
2023-08-09 16:32:12 +08:00
|
|
|
<el-input @change="searchLogs" class="margin-button" style="width: 100px" v-model.number="logSearch.tail">
|
2023-06-14 14:16:13 +08:00
|
|
|
<template #prefix>
|
|
|
|
<div style="margin-left: 2px">{{ $t('container.lines') }}</div>
|
|
|
|
</template>
|
|
|
|
</el-input>
|
2023-08-09 16:32:12 +08:00
|
|
|
<div class="margin-button">
|
2023-08-03 16:49:32 +08:00
|
|
|
<el-checkbox border @change="searchLogs" v-model="logSearch.isWatch">
|
|
|
|
{{ $t('commons.button.watch') }}
|
|
|
|
</el-checkbox>
|
2022-11-04 19:02:15 +08:00
|
|
|
</div>
|
2023-05-23 15:43:51 +08:00
|
|
|
<el-button class="margin-button" @click="onDownload" icon="Download">
|
2022-11-04 19:02:15 +08:00
|
|
|
{{ $t('file.download') }}
|
|
|
|
</el-button>
|
2023-05-23 15:43:51 +08:00
|
|
|
<el-button class="margin-button" @click="onClean" icon="Delete">
|
|
|
|
{{ $t('commons.button.clean') }}
|
|
|
|
</el-button>
|
2022-11-04 19:02:15 +08:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<codemirror
|
|
|
|
:autofocus="true"
|
2023-07-10 18:39:07 +08:00
|
|
|
:placeholder="$t('commons.msg.noneData')"
|
2022-11-04 19:02:15 +08:00
|
|
|
:indent-with-tab="true"
|
|
|
|
:tabSize="4"
|
2023-02-01 16:15:31 +08:00
|
|
|
style="margin-top: 10px; height: calc(100vh - 375px)"
|
2022-11-04 19:02:15 +08:00
|
|
|
:lineWrapping="true"
|
|
|
|
:matchBrackets="true"
|
|
|
|
theme="cobalt"
|
|
|
|
:styleActiveLine="true"
|
|
|
|
:extensions="extensions"
|
2022-12-23 15:38:13 +08:00
|
|
|
@ready="handleReady"
|
2022-11-04 19:02:15 +08:00
|
|
|
v-model="logInfo"
|
2023-02-20 18:05:07 +08:00
|
|
|
:disabled="true"
|
2022-11-04 19:02:15 +08:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2023-06-14 14:16:13 +08:00
|
|
|
import { cleanContainerLog } from '@/api/modules/container';
|
2022-11-04 19:02:15 +08:00
|
|
|
import i18n from '@/lang';
|
2023-07-10 21:27:07 +08:00
|
|
|
import { dateFormatForName, downloadWithContent } from '@/utils/util';
|
2023-06-14 14:16:13 +08:00
|
|
|
import { onBeforeUnmount, reactive, ref, shallowRef } from 'vue';
|
2022-11-04 19:02:15 +08:00
|
|
|
import { Codemirror } from 'vue-codemirror';
|
|
|
|
import { javascript } from '@codemirror/lang-javascript';
|
|
|
|
import { oneDark } from '@codemirror/theme-one-dark';
|
2023-06-14 14:16:13 +08:00
|
|
|
import { MsgError, MsgSuccess } from '@/utils/message';
|
2022-11-04 19:02:15 +08:00
|
|
|
|
|
|
|
const extensions = [javascript(), oneDark];
|
|
|
|
|
|
|
|
const logInfo = ref();
|
2022-12-23 15:38:13 +08:00
|
|
|
const view = shallowRef();
|
|
|
|
const handleReady = (payload) => {
|
|
|
|
view.value = payload.view;
|
|
|
|
};
|
2023-06-14 14:16:13 +08:00
|
|
|
const terminalSocket = ref<WebSocket>();
|
2022-12-23 15:38:13 +08:00
|
|
|
|
2022-11-04 19:02:15 +08:00
|
|
|
const logSearch = reactive({
|
|
|
|
isWatch: false,
|
|
|
|
container: '',
|
|
|
|
containerID: '',
|
|
|
|
mode: 'all',
|
2023-06-14 14:16:13 +08:00
|
|
|
tail: 100,
|
2022-11-04 19:02:15 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
const timeOptions = ref([
|
|
|
|
{ label: i18n.global.t('container.all'), value: 'all' },
|
|
|
|
{
|
|
|
|
label: i18n.global.t('container.lastDay'),
|
|
|
|
value: new Date(new Date().getTime() - 3600 * 1000 * 24 * 1).getTime() / 1000 + '',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: i18n.global.t('container.last4Hour'),
|
|
|
|
value: new Date(new Date().getTime() - 3600 * 1000 * 4).getTime() / 1000 + '',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: i18n.global.t('container.lastHour'),
|
|
|
|
value: new Date(new Date().getTime() - 3600 * 1000).getTime() / 1000 + '',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: i18n.global.t('container.last10Min'),
|
|
|
|
value: new Date(new Date().getTime() - 600 * 1000).getTime() / 1000 + '',
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
|
|
|
const searchLogs = async () => {
|
2023-07-12 14:33:19 +08:00
|
|
|
if (!Number(logSearch.tail) || Number(logSearch.tail) < 0) {
|
2023-06-14 14:16:13 +08:00
|
|
|
MsgError(i18n.global.t('container.linesHelper'));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
terminalSocket.value?.close();
|
|
|
|
logInfo.value = '';
|
|
|
|
const href = window.location.href;
|
|
|
|
const protocol = href.split('//')[0] === 'http:' ? 'ws' : 'wss';
|
|
|
|
const host = href.split('//')[1].split('/')[0];
|
|
|
|
terminalSocket.value = new WebSocket(
|
|
|
|
`${protocol}://${host}/api/v1/containers/search/log?container=${logSearch.containerID}&since=${logSearch.mode}&tail=${logSearch.tail}&follow=${logSearch.isWatch}`,
|
|
|
|
);
|
|
|
|
terminalSocket.value.onmessage = (event) => {
|
|
|
|
logInfo.value += event.data;
|
2022-12-23 15:38:13 +08:00
|
|
|
const state = view.value.state;
|
|
|
|
view.value.dispatch({
|
|
|
|
selection: { anchor: state.doc.length, head: state.doc.length },
|
|
|
|
scrollIntoView: true,
|
|
|
|
});
|
2023-06-14 14:16:13 +08:00
|
|
|
};
|
2022-11-04 19:02:15 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const onDownload = async () => {
|
2023-07-10 21:27:07 +08:00
|
|
|
downloadWithContent(logInfo.value, logSearch.container + '-' + dateFormatForName(new Date()) + '.log');
|
2022-11-04 19:02:15 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
interface DialogProps {
|
2022-12-02 18:52:43 +08:00
|
|
|
container: string;
|
2022-11-04 19:02:15 +08:00
|
|
|
containerID: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
const acceptParams = (props: DialogProps): void => {
|
|
|
|
logSearch.containerID = props.containerID;
|
2023-06-14 14:16:13 +08:00
|
|
|
logSearch.tail = 100;
|
2022-11-04 19:02:15 +08:00
|
|
|
logSearch.mode = 'all';
|
|
|
|
logSearch.isWatch = false;
|
2022-12-02 18:52:43 +08:00
|
|
|
logSearch.container = props.container;
|
2022-11-04 19:02:15 +08:00
|
|
|
searchLogs();
|
|
|
|
};
|
|
|
|
|
2023-05-23 15:43:51 +08:00
|
|
|
const onClean = async () => {
|
2023-08-21 17:00:12 +08:00
|
|
|
ElMessageBox.confirm(i18n.global.t('container.cleanLogHelper'), i18n.global.t('container.cleanLog'), {
|
2023-05-23 15:43:51 +08:00
|
|
|
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
|
|
|
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
|
|
|
type: 'info',
|
|
|
|
}).then(async () => {
|
|
|
|
await cleanContainerLog(logSearch.container);
|
|
|
|
searchLogs();
|
|
|
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2023-02-15 17:10:15 +08:00
|
|
|
onBeforeUnmount(() => {
|
2023-06-14 14:16:13 +08:00
|
|
|
terminalSocket.value?.close();
|
2023-02-15 17:10:15 +08:00
|
|
|
});
|
|
|
|
|
2022-11-04 19:02:15 +08:00
|
|
|
defineExpose({
|
|
|
|
acceptParams,
|
|
|
|
});
|
|
|
|
</script>
|
2023-05-23 15:43:51 +08:00
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
.margin-button {
|
|
|
|
margin-left: 20px;
|
|
|
|
}
|
|
|
|
</style>
|