로그 저장 로직 단순화

This commit is contained in:
2023-11-13 16:43:56 +09:00
parent 61d2fbf709
commit 394466e216
5 changed files with 89 additions and 132 deletions

View File

@ -71,41 +71,13 @@ type HoustonClient interface {
Start() Start()
} }
type bufferStack struct {
pool [5][]byte
cursor int32
}
func (bs *bufferStack) pop() []byte {
pos := atomic.LoadInt32(&bs.cursor)
for !atomic.CompareAndSwapInt32(&bs.cursor, pos, pos+1) {
pos = atomic.LoadInt32(&bs.cursor)
}
defer func() {
bs.pool[pos] = nil
}()
curbuf := bs.pool[pos]
if curbuf == nil {
curbuf = make([]byte, 1024)
}
return curbuf
}
func (bs *bufferStack) push(x []byte) {
pos := atomic.AddInt32(&bs.cursor, -1)
bs.pool[pos] = x
}
type procmeta struct { type procmeta struct {
cmd *exec.Cmd cmd *exec.Cmd
name string name string
version string args []string
state protos.ProcessState version string
stdin io.WriteCloser state protos.ProcessState
logUploadChan chan *shared.UploadRequest stdin io.WriteCloser
buffers bufferStack
} }
type houstonClient struct { type houstonClient struct {
@ -197,7 +169,7 @@ func (hc *houstonClient) makeOperationQueryRequest() *protos.OperationQueryReque
for _, child := range hc.childProcs { for _, child := range hc.childProcs {
procs = append(procs, &protos.ProcessDescription{ procs = append(procs, &protos.ProcessDescription{
Name: child.name, Name: child.name,
Args: child.cmd.Args, Args: child.args,
Version: child.version, Version: child.version,
State: child.state, State: child.state,
Pid: int32(child.cmd.Process.Pid), Pid: int32(child.cmd.Process.Pid),
@ -327,7 +299,7 @@ func NewClient(standalone bool) (HoustonClient, error) {
hc.startChildProcess(&shared.StartProcessRequest{ hc.startChildProcess(&shared.StartProcessRequest{
Version: proc.version, Version: proc.version,
Name: proc.name, Name: proc.name,
Args: proc.cmd.Args, Args: proc.args,
}, op) }, op)
} }
}(proc) }(proc)

View File

@ -4,6 +4,7 @@ package client
import ( import (
"archive/zip" "archive/zip"
"bufio"
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
@ -14,7 +15,6 @@ import (
"os/exec" "os/exec"
"path" "path"
"path/filepath" "path/filepath"
"runtime/debug"
"strings" "strings"
"syscall" "syscall"
"time" "time"
@ -183,18 +183,29 @@ func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) *
stdin, _ := cmd.StdinPipe() stdin, _ := cmd.StdinPipe()
return &procmeta{ return &procmeta{
cmd: cmd, cmd: cmd,
name: req.Name, name: req.Name,
version: req.Version, args: req.Args,
state: protos.ProcessState_Stopped, version: req.Version,
stdin: stdin, state: protos.ProcessState_Stopped,
logUploadChan: make(chan *shared.UploadRequest), stdin: stdin,
buffers: bufferStack{cursor: 0},
} }
} }
return nil return nil
} }
func makeLogFile(meta *procmeta, idx int) string {
now := time.Now().UTC()
ext := path.Ext(meta.args[0])
nameonly := path.Base(meta.args[0])
if len(ext) > 0 {
nameonly = nameonly[:len(nameonly)-len(ext)]
}
ts := now.Format("2006-01-02T15-04-05")
stdPrefix := path.Join(meta.cmd.Dir, "logs", fmt.Sprintf("%s_%s", nameonly, ts))
return fmt.Sprintf("%s_%d.log", stdPrefix, idx)
}
func (hc *houstonClient) launch(meta *procmeta) error { func (hc *houstonClient) launch(meta *procmeta) error {
stdout, err := meta.cmd.StdoutPipe() stdout, err := meta.cmd.StdoutPipe()
if err != nil { if err != nil {
@ -210,104 +221,61 @@ func (hc *houstonClient) launch(meta *procmeta) error {
return err return err
} }
relayChan := make(chan struct { stdReader := func(r io.ReadCloser) {
size int
buf []byte
})
go func() {
defer func() { defer func() {
r := recover() reco := recover()
if r != nil { if reco != nil {
logger.Println(r) logger.Println(reco)
debug.PrintStack()
} }
close(relayChan)
hc.exitChan <- meta.cmd
}() }()
now := time.Now().UTC() defer r.Close()
ext := path.Ext(meta.cmd.Args[0])
nameonly := path.Base(meta.cmd.Args[0]) reader := bufio.NewReader(r)
if len(ext) > 0 { thisFileSize := 0
nameonly = nameonly[:len(nameonly)-len(ext)] logFileIndex := 0
logFileName := makeLogFile(meta, logFileIndex)
targetFile, err := os.Create(logFileName)
if err != nil {
logger.Println("failed to create log file :", logFileName)
return
} }
ts := now.Format("2006-01-02T15-04-05")
stdPrefix := path.Join(meta.cmd.Dir, "logs", fmt.Sprintf("%s_%s", nameonly, ts))
logfile, _ := os.Create(stdPrefix + "_0.log")
defer logfile.Close()
logfileIdx := 0
for {
thisFileSize := 0
switchToNextFile := func() string {
logfileIdx++
nextFile := fmt.Sprintf("%s_%d.log", stdPrefix, logfileIdx)
if nextLogfile, err := os.Create(nextFile); err == nil {
logfile.Close()
logfile = nextLogfile
}
thisFileSize = 0
return nextFile
}
uploadStartFile := ""
select {
case req := <-meta.logUploadChan:
nextFile := switchToNextFile()
startFile := uploadStartFile
uploadStartFile = nextFile
go func(startFile, nextFile string) {
zipFile, srcFiles, err := zipLogFiles(hc.config.StorageRoot, req, startFile, nextFile)
if err == nil && len(zipFile) > 0 && len(srcFiles) > 0 {
if err = hc.uploadZipLogFile(zipFile, meta.name, meta.version); err == nil {
for _, oldf := range srcFiles {
os.Remove(oldf)
}
} else {
logger.Println("uploadZipLogFile failed :", err)
}
} else if err != nil {
logger.Println("zipLogFiles failed :", err)
}
}(startFile, nextFile)
case bt := <-relayChan:
if bt.buf == nil {
return
}
logfile.Write(bt.buf[:bt.size])
logfile.Sync()
meta.buffers.push(bt.buf)
thisFileSize += bt.size
if thisFileSize > 10*1024*1024 {
switchToNextFile()
}
}
}
}()
stdReader := func(r io.Reader) {
defer func() { defer func() {
recover() if targetFile != nil {
stdout.Close() targetFile.Close()
}
}() }()
for { for {
buff := meta.buffers.pop() buff, err := reader.ReadBytes('\n')
size, err := r.Read(buff)
if err != nil { if err != nil {
relayChan <- struct {
size int
buf []byte
}{buf: nil}
break break
} }
if size > 0 {
relayChan <- struct { for written := 0; written < len(buff); {
size int n, err := targetFile.Write(buff)
buf []byte if err != nil {
}{size: size, buf: buff} logger.Println("write log file failed :", logFileName, err)
break
} else {
written += n
thisFileSize += n
}
}
if thisFileSize > 10*1024*1024 {
logFileIndex++
logFileName := makeLogFile(meta, logFileIndex)
nextTargetFile, err := os.Create(logFileName)
if err != nil {
logger.Println("failed to create log file :", logFileName)
} else {
targetFile.Close()
targetFile = nextTargetFile
thisFileSize = 0
}
} }
} }
} }
@ -349,7 +317,7 @@ func (hc *houstonClient) startChildProcess(req *shared.StartProcessRequest, op p
vers := hc.deploys[req.Name] vers := hc.deploys[req.Name]
for _, ver := range vers { for _, ver := range vers {
if ver.Version == req.Version { if ver.Version == req.Version {
ver.Args = meta.cmd.Args ver.Args = meta.args
} }
} }
@ -476,7 +444,23 @@ func (hc *houstonClient) uploadFiles(req *shared.UploadRequest) error {
for _, child := range hc.childProcs { for _, child := range hc.childProcs {
if child.version == req.Version && child.name == req.Name { if child.version == req.Version && child.name == req.Name {
logger.Println("uploadFiles found :", child.version, child.name) logger.Println("uploadFiles found :", child.version, child.name)
child.logUploadChan <- req
go func() {
zipFile, srcFiles, err := zipLogFiles(hc.config.StorageRoot, req, "", "")
if err == nil && len(zipFile) > 0 && len(srcFiles) > 0 {
if err = hc.uploadZipLogFile(zipFile, child.name, child.version); err == nil {
// 마지막거 빼고 삭제
for i := 0; i < len(srcFiles)-1; i++ {
os.Remove(srcFiles[i])
}
} else {
logger.Println("uploadZipLogFile failed :", err)
}
} else if err != nil {
logger.Println("zipLogFiles failed :", err)
}
}()
return nil return nil
} }
} }

View File

@ -31,7 +31,6 @@ func main() {
hc, err := client.NewClient(true) hc, err := client.NewClient(true)
if err != nil { if err != nil {
panic(err) panic(err)
return
} }
var ( var (

View File

@ -1,3 +1,5 @@
//go:build !client
package server package server
import ( import (