mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-11-30 10:48:15 +08:00
248 lines
6.2 KiB
Go
248 lines
6.2 KiB
Go
|
|
// RAINBOND, Application Management Platform
|
|
// Copyright (C) 2014-2017 Goodrain Co., Ltd.
|
|
|
|
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
package handler
|
|
|
|
import (
|
|
"github.com/goodrain/rainbond/cmd/api/option"
|
|
api_model "github.com/goodrain/rainbond/pkg/api/model"
|
|
"bytes"
|
|
"compress/zlib"
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
|
|
"github.com/coreos/etcd/client"
|
|
"github.com/pquerna/ffjson/ffjson"
|
|
|
|
"github.com/goodrain/rainbond/pkg/db"
|
|
"os/exec"
|
|
)
|
|
|
|
//LogAction log action struct
|
|
type LogAction struct {
|
|
EtcdEndpoints []string
|
|
}
|
|
|
|
//CreateLogManager get log manager
|
|
func CreateLogManager(conf option.Config) (*LogAction, error) {
|
|
return &LogAction{
|
|
EtcdEndpoints: conf.EtcdEndpoint,
|
|
}, nil
|
|
}
|
|
|
|
//GetLogList get log list
|
|
func (l *LogAction) GetLogList(serviceAlias string) ([]string, error) {
|
|
downLoadDIR := "/grdata/downloads"
|
|
urlPath := fmt.Sprintf("/log/%s", serviceAlias)
|
|
logDIR := fmt.Sprintf("%s%s", downLoadDIR, urlPath)
|
|
_, err := os.Stat(logDIR)
|
|
if os.IsNotExist(err) {
|
|
return nil, err
|
|
}
|
|
fileList, err := ioutil.ReadDir(logDIR)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var logList []string
|
|
if len(fileList) == 0 {
|
|
return logList, nil
|
|
}
|
|
|
|
for _, file := range fileList {
|
|
filePath := fmt.Sprintf("/logs/%s/%s", serviceAlias, file.Name())
|
|
logrus.Debugf("filepath is %s", file.Name())
|
|
logList = append(logList, filePath)
|
|
}
|
|
return logList, nil
|
|
}
|
|
|
|
//GetLogFile GetLogFile
|
|
func (l *LogAction) GetLogFile(serviceAlias, fileName string) (string, string, error) {
|
|
downLoadDIR := "/grdata/downloads"
|
|
urlPath := fmt.Sprintf("/log/%s", serviceAlias)
|
|
fullPath := fmt.Sprintf("%s%s/%s", downLoadDIR, urlPath, fileName)
|
|
logPath := fmt.Sprintf("%s/log/%s", downLoadDIR, serviceAlias)
|
|
_, err := os.Stat(fullPath)
|
|
if os.IsNotExist(err) {
|
|
return "", "", err
|
|
}
|
|
return logPath, fullPath, err
|
|
}
|
|
|
|
//GetLogInstance get log web socket instance
|
|
func (l *LogAction) GetLogInstance(serviceID string) (string, error) {
|
|
//etcd V2
|
|
etcdclient, err := client.New(client.Config{
|
|
Endpoints: l.EtcdEndpoints,
|
|
})
|
|
value, err := client.NewKeysAPI(etcdclient).Get(context.Background(),
|
|
fmt.Sprintf("/event/dockerloginstacne/%s", serviceID),
|
|
nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return value.Node.Value, nil
|
|
/*
|
|
@ etcd V3 使用
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
etcdclientv3, err := clientv2.New(clientv3.Config{
|
|
Endpoints: l.EtcdEndpoints,
|
|
})
|
|
value, err := etcdclientv3.Get(ctx, fmt.Sprintf("/event/dockerloginstacne/%s", serviceID))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(value.Kvs) == 0 {
|
|
return "", errors.New("have no value")
|
|
}
|
|
return string(value.Kvs[0].Value), nil
|
|
*/
|
|
}
|
|
|
|
//GetLevelLog 获取指定操作的操作日志
|
|
func (l *LogAction) GetLevelLog(eventID string, level string) (*api_model.DataLog, error) {
|
|
messages, err := db.GetManager().EventLogDao().GetEventLogMessages(eventID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var d []api_model.MessageData
|
|
timeLayout := "2006-01-02T15:04:05+08:00"
|
|
loc, _ := time.LoadLocation("Local")
|
|
for _, v := range messages {
|
|
log, err := decompress(v.Message)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var mlogs []api_model.MsgStruct
|
|
if err := ffjson.Unmarshal(log, &mlogs); err != nil {
|
|
return nil, err
|
|
}
|
|
for _, msg := range mlogs {
|
|
if checkLevel(level, msg.Level) {
|
|
//兼容 {system worker worker已收到异步任务。 info 2017-09-29T10:02:44.703640}"
|
|
if strings.Contains(msg.Time, ".") {
|
|
//msg.Time = strings.Split(msg.Time, ".")[0]
|
|
timeLayout = "2006-01-02T15:04:05"
|
|
} else {
|
|
timeLayout = "2006-01-02T15:04:05+08:00"
|
|
}
|
|
utime, err := time.ParseInLocation(timeLayout, msg.Time, loc)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
md := api_model.MessageData{
|
|
Message: msg.Message,
|
|
Time: msg.Time,
|
|
Unixtime: utime.Unix(),
|
|
}
|
|
d = append(d, md)
|
|
}
|
|
}
|
|
}
|
|
//耗时
|
|
d = bubSort(d)
|
|
return &api_model.DataLog{
|
|
Status: "success",
|
|
Data: d,
|
|
}, nil
|
|
}
|
|
|
|
//GetLinesLogs GetLinesLogs
|
|
func (l *LogAction) GetLinesLogs(alias string, n int) ([]byte, error) {
|
|
downLoadDIR := "/grdata/downloads"
|
|
filePath := fmt.Sprintf("%s/log/%s/stdout.log", downLoadDIR, alias)
|
|
logrus.Debugf("file path is %s", filePath)
|
|
f, err := exec.Command("tail", "-n", fmt.Sprintf("%d", n), filePath).Output()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return f, nil
|
|
}
|
|
|
|
//Decompress zlib解码
|
|
func decompress(zb []byte) ([]byte, error) {
|
|
b := bytes.NewReader(zb)
|
|
var out bytes.Buffer
|
|
r, err := zlib.NewReader(b)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if _, err := io.Copy(&out, r); err != nil {
|
|
return nil, err
|
|
}
|
|
return out.Bytes(), nil
|
|
}
|
|
|
|
func checkLevel(level, info string) bool {
|
|
switch level {
|
|
case "error":
|
|
if info == "error" {
|
|
return true
|
|
}
|
|
return false
|
|
case "info":
|
|
if info == "info" || info == "error" {
|
|
return true
|
|
}
|
|
return false
|
|
case "debug":
|
|
if info == "info" || info == "error" || info == "debug" {
|
|
return true
|
|
}
|
|
return false
|
|
default:
|
|
if info == "info" || info == "error" {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
|
|
func uncompress(source []byte) (re []byte, err error) {
|
|
r, err := zlib.NewReader(bytes.NewReader(source))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var buffer bytes.Buffer
|
|
io.Copy(&buffer, r)
|
|
r.Close()
|
|
return buffer.Bytes(), nil
|
|
}
|
|
|
|
func bubSort(d []api_model.MessageData) []api_model.MessageData {
|
|
for i := 0; i < len(d); i++ {
|
|
for j := i + 1; j < len(d); j++ {
|
|
if d[i].Unixtime > d[j].Unixtime {
|
|
temp := d[i]
|
|
d[i] = d[j]
|
|
d[j] = temp
|
|
}
|
|
}
|
|
}
|
|
return d
|
|
}
|