// Copyright (C) 2014-2018 Goodrain Co., Ltd. // RAINBOND, Application Management Platform // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. For any non-GPL usage of Rainbond, // one or multiple Commercial Licenses authorized by Goodrain Co., Ltd. // must be obtained first. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see . package db import ( "archive/zip" "bufio" "bytes" "crypto/sha256" "fmt" "io" "os" "os/exec" "path" "strconv" "time" "github.com/goodrain/rainbond/util" "github.com/sirupsen/logrus" ) type filePlugin struct { homePath string } func (m *filePlugin) getStdFilePath(serviceID string) (string, error) { apath := path.Join(m.homePath, GetServiceAliasID(serviceID)) _, err := os.Stat(apath) if err != nil { if os.IsNotExist(err) { err := os.MkdirAll(apath, 0755) if err != nil { return "", err } } else { return "", err } } return apath, nil } func (m *filePlugin) SaveMessage(events []*EventLogMessage) error { if len(events) == 0 { return nil } key := events[0].EventID var logfile *os.File filePathDir, err := m.getStdFilePath(key) if err != nil { return err } logFile, err := os.Stat(path.Join(filePathDir, "stdout.log")) if err != nil { if os.IsNotExist(err) { logfile, err = os.Create(path.Join(filePathDir, "stdout.log")) if err != nil { return err } defer logfile.Close() } else { return err } } else { if logFile.ModTime().Day() != time.Now().Day() { err := MvLogFile(fmt.Sprintf("%s/%d-%d-%d.log.gz", filePathDir, logFile.ModTime().Year(), logFile.ModTime().Month(), logFile.ModTime().Day()), path.Join(filePathDir, "stdout.log")) if err != nil { return err } } } if logfile == nil { logfile, err = os.OpenFile(path.Join(filePathDir, "stdout.log"), os.O_WRONLY|os.O_APPEND, 0666) if err != nil { return err } defer logfile.Close() } else { defer logfile.Close() } var contant [][]byte for _, e := range events { contant = append(contant, e.Content) } body := bytes.Join(contant, []byte("\n")) body = append(body, []byte("\n")...) _, err = logfile.Write(body) return err } func (m *filePlugin) GetMessages(serviceID, level string, length int) (interface{}, error) { if length <= 0 { return nil, nil } filePathDir, err := m.getStdFilePath(serviceID) if err != nil { return nil, err } filePath := path.Join(filePathDir, "stdout.log") if ok, err := util.FileExists(filePath); !ok { if err != nil { logrus.Errorf("check file exist error %s", err.Error()) } return nil, nil } f, err := exec.Command("tail", "-n", fmt.Sprintf("%d", length), filePath).Output() if err != nil { return nil, err } reader := bufio.NewReader(bytes.NewBuffer(f)) var lines []string for { line, _, err := reader.ReadLine() if err != nil { break } if len(line) == 0 { continue } lines = append(lines, string(line)) } return lines, nil } func (m *filePlugin) Close() error { return nil } //GetServiceAliasID python: //new_word = str(ord(string[10])) + string + str(ord(string[3])) + 'log' + str(ord(string[2]) / 7) //new_id = hashlib.sha224(new_word).hexdigest()[0:16] // func GetServiceAliasID(ServiceID string) string { if len(ServiceID) > 11 { newWord := strconv.Itoa(int(ServiceID[10])) + ServiceID + strconv.Itoa(int(ServiceID[3])) + "log" + strconv.Itoa(int(ServiceID[2])/7) ha := sha256.New224() ha.Write([]byte(newWord)) return fmt.Sprintf("%x", ha.Sum(nil))[0:16] } return ServiceID } //MvLogFile 更改文件名称,压缩 func MvLogFile(newName string, filePath string) error { info, err := os.Stat(filePath) if err != nil { return err } reader, err := os.OpenFile(filePath, os.O_RDONLY, 0666) if err != nil { return err } // 将压缩文档内容写入文件 f, err := os.OpenFile(newName, os.O_CREATE|os.O_WRONLY, 0666) if err != nil { return err } defer f.Close() zw := zip.NewWriter(f) defer zw.Close() header, err := zip.FileInfoHeader(info) if err != nil { return err } writer, err := zw.CreateHeader(header) if err != nil { return err } _, err = io.Copy(writer, reader) if err != nil { return err } err = os.Remove(filePath) if err != nil { return err } new, err := os.Create(filePath) if err != nil { return err } defer new.Close() return nil }