로그 저장 로직 단순화
This commit is contained in:
@ -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
|
||||||
|
args []string
|
||||||
version string
|
version string
|
||||||
state protos.ProcessState
|
state protos.ProcessState
|
||||||
stdin io.WriteCloser
|
stdin io.WriteCloser
|
||||||
logUploadChan chan *shared.UploadRequest
|
|
||||||
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)
|
||||||
|
|||||||
@ -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"
|
||||||
@ -185,16 +185,27 @@ func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) *
|
|||||||
return &procmeta{
|
return &procmeta{
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
name: req.Name,
|
name: req.Name,
|
||||||
|
args: req.Args,
|
||||||
version: req.Version,
|
version: req.Version,
|
||||||
state: protos.ProcessState_Stopped,
|
state: protos.ProcessState_Stopped,
|
||||||
stdin: stdin,
|
stdin: stdin,
|
||||||
logUploadChan: make(chan *shared.UploadRequest),
|
|
||||||
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])
|
|
||||||
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))
|
|
||||||
logfile, _ := os.Create(stdPrefix + "_0.log")
|
|
||||||
defer logfile.Close()
|
|
||||||
|
|
||||||
logfileIdx := 0
|
reader := bufio.NewReader(r)
|
||||||
for {
|
|
||||||
thisFileSize := 0
|
thisFileSize := 0
|
||||||
switchToNextFile := func() string {
|
logFileIndex := 0
|
||||||
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 := ""
|
logFileName := makeLogFile(meta, logFileIndex)
|
||||||
select {
|
targetFile, err := os.Create(logFileName)
|
||||||
case req := <-meta.logUploadChan:
|
if err != nil {
|
||||||
nextFile := switchToNextFile()
|
logger.Println("failed to create log file :", logFileName)
|
||||||
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
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 (
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
//go:build !client
|
||||||
|
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
Reference in New Issue
Block a user