mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-09-22 08:00:53 +00:00
feat: Show container log timestamps (#11785)
This commit is contained in:
@@ -529,7 +529,7 @@ func (b *BaseApi) DownloadContainerLogs(c *gin.Context) {
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
err := containerService.DownloadContainerLogs(req.ContainerType, req.Container, req.Since, strconv.Itoa(int(req.Tail)), c)
|
||||
err := containerService.DownloadContainerLogs(req.ContainerType, req.Container, req.Since, strconv.Itoa(int(req.Tail)), req.Timestamp, c)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
}
|
||||
@@ -757,6 +757,7 @@ func (b *BaseApi) LoadComposeEnv(c *gin.Context) {
|
||||
// @Param since query string false "时间筛选"
|
||||
// @Param follow query string false "是否追踪"
|
||||
// @Param tail query string false "显示行号"
|
||||
// @Param timestamp query string false "是否显示时间"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
@@ -770,6 +771,7 @@ func (b *BaseApi) ContainerStreamLogs(c *gin.Context) {
|
||||
since := c.Query("since")
|
||||
follow := c.Query("follow") == "true"
|
||||
tail := c.Query("tail")
|
||||
timestamp := c.Query("timestamp") == "true"
|
||||
|
||||
container := c.Query("container")
|
||||
compose := c.Query("compose")
|
||||
@@ -779,6 +781,7 @@ func (b *BaseApi) ContainerStreamLogs(c *gin.Context) {
|
||||
Since: since,
|
||||
Follow: follow,
|
||||
Tail: tail,
|
||||
Timestamp: timestamp,
|
||||
Type: "container",
|
||||
}
|
||||
if compose != "" {
|
||||
|
||||
@@ -305,6 +305,7 @@ type ContainerLog struct {
|
||||
Container string `json:"container" validate:"required"`
|
||||
Since string `json:"since"`
|
||||
Tail uint `json:"tail"`
|
||||
Timestamp bool `json:"timestamp"`
|
||||
ContainerType string `json:"containerType"`
|
||||
}
|
||||
|
||||
@@ -314,5 +315,6 @@ type StreamLog struct {
|
||||
Since string
|
||||
Follow bool
|
||||
Tail string
|
||||
Timestamp bool
|
||||
Type string
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ type IContainerService interface {
|
||||
ContainerCommit(req dto.ContainerCommit) error
|
||||
ContainerLogClean(req dto.OperationWithName) error
|
||||
ContainerOperation(req dto.ContainerOperation) error
|
||||
DownloadContainerLogs(containerType, container, since, tail string, c *gin.Context) error
|
||||
DownloadContainerLogs(containerType, container, since, tail string, timestamp bool, c *gin.Context) error
|
||||
ContainerStats(id string) (*dto.ContainerStats, error)
|
||||
|
||||
Inspect(req dto.InspectReq) (string, error)
|
||||
@@ -956,6 +956,9 @@ func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<-
|
||||
if params.Follow {
|
||||
cmdArgs = append(cmdArgs, "-f")
|
||||
}
|
||||
if params.Timestamp {
|
||||
cmdArgs = append(cmdArgs, "-t")
|
||||
}
|
||||
if params.Tail != "0" {
|
||||
cmdArgs = append(cmdArgs, "--tail", params.Tail)
|
||||
}
|
||||
@@ -1052,7 +1055,7 @@ func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<-
|
||||
_ = dockerCmd.Wait()
|
||||
}
|
||||
|
||||
func (u *ContainerService) DownloadContainerLogs(containerType, container, since, tail string, c *gin.Context) error {
|
||||
func (u *ContainerService) DownloadContainerLogs(containerType, container, since, tail string, timestamp bool, c *gin.Context) error {
|
||||
if cmd.CheckIllegal(container, since, tail) {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
@@ -1080,6 +1083,9 @@ func (u *ContainerService) DownloadContainerLogs(containerType, container, since
|
||||
commandArg = append(commandArg, "--since")
|
||||
commandArg = append(commandArg, since)
|
||||
}
|
||||
if timestamp {
|
||||
commandArg = append(commandArg, "-t")
|
||||
}
|
||||
var dockerCmd *exec.Cmd
|
||||
if containerType == "compose" && dockerCommand == "docker-compose" {
|
||||
dockerCmd = exec.Command("docker-compose", commandArg...)
|
||||
|
||||
@@ -4594,6 +4594,12 @@ const docTemplate = `{
|
||||
"in": "query",
|
||||
"name": "tail",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "是否显示时间",
|
||||
"in": "query",
|
||||
"name": "timestamp",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
||||
@@ -4590,6 +4590,12 @@
|
||||
"in": "query",
|
||||
"name": "tail",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "是否显示时间",
|
||||
"in": "query",
|
||||
"name": "timestamp",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
{{ $t('commons.button.watch') }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
<div class="margin-button float-left">
|
||||
<el-checkbox border @change="searchLogs" v-model="logSearch.isShowTimestamp">
|
||||
{{ $t('commons.table.date') }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
<el-button class="margin-button" @click="onDownload" icon="Download">
|
||||
{{ $t('commons.button.download') }}
|
||||
</el-button>
|
||||
@@ -79,6 +84,10 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
defaultIsShowTimestamp: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const styleVars = computed(() => ({
|
||||
@@ -91,6 +100,7 @@ const logs = ref<string[]>([]);
|
||||
let eventSource: EventSource | null = null;
|
||||
const logSearch = reactive({
|
||||
isWatch: props.defaultFollow ? true : true,
|
||||
isShowTimestamp: props.defaultIsShowTimestamp,
|
||||
container: '',
|
||||
mode: 'all',
|
||||
tail: props.defaultFollow ? 0 : 100,
|
||||
@@ -152,9 +162,9 @@ const searchLogs = async () => {
|
||||
if (props.node && props.node !== '') {
|
||||
currentNode = props.node;
|
||||
}
|
||||
let url = `/api/v2/containers/search/log?container=${logSearch.container}&since=${logSearch.mode}&tail=${logSearch.tail}&follow=${logSearch.isWatch}&operateNode=${currentNode}`;
|
||||
let url = `/api/v2/containers/search/log?container=${logSearch.container}&since=${logSearch.mode}&tail=${logSearch.tail}&follow=${logSearch.isWatch}×tamp=${logSearch.isShowTimestamp}&operateNode=${currentNode}`;
|
||||
if (logSearch.compose !== '') {
|
||||
url = `/api/v2/containers/search/log?compose=${logSearch.compose}&since=${logSearch.mode}&tail=${logSearch.tail}&follow=${logSearch.isWatch}&operateNode=${currentNode}`;
|
||||
url = `/api/v2/containers/search/log?compose=${logSearch.compose}&since=${logSearch.mode}&tail=${logSearch.tail}&follow=${logSearch.isWatch}×tamp=${logSearch.isShowTimestamp}&operateNode=${currentNode}`;
|
||||
}
|
||||
eventSource = new EventSource(url);
|
||||
eventSource.onmessage = (event: MessageEvent) => {
|
||||
@@ -192,6 +202,7 @@ const onDownload = async () => {
|
||||
container: container,
|
||||
since: logSearch.mode,
|
||||
tail: logSearch.tail,
|
||||
timestamp: logSearch.isShowTimestamp,
|
||||
containerType: containerType,
|
||||
};
|
||||
let addItem = {};
|
||||
|
||||
Reference in New Issue
Block a user