feat: Show container log timestamps (#11785)

This commit is contained in:
MoeShin
2026-02-04 17:42:37 +08:00
committed by GitHub
parent b0a053b397
commit 35ea1a1d6c
6 changed files with 39 additions and 5 deletions
+4 -1
View File
@@ -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 != "" {
+2
View File
@@ -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
}
+8 -2
View File
@@ -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...)
+6
View File
@@ -4594,6 +4594,12 @@ const docTemplate = `{
"in": "query",
"name": "tail",
"type": "string"
},
{
"description": "是否显示时间",
"in": "query",
"name": "timestamp",
"type": "string"
}
],
"responses": {
+6
View File
@@ -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}&timestamp=${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}&timestamp=${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 = {};