Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
dongjunjie committed Jan 27, 2022
0 parents commit 5b11970
Show file tree
Hide file tree
Showing 11 changed files with 539 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": []
}
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# remote-log-go

remote-log sdk go 版本。将日志内容按照统一格式通过 http 发送到日志采集层,支持缓存和压缩上传。
59 changes: 59 additions & 0 deletions console_transport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package remote_log_go

import (
"fmt"
"os"
)

type ConsoleTransport struct {
allowLevel []Level // 允许使用此方式的日志级别
}

/**
* @description: 创建ConsoleTransport类
* @param {...Level} allowLevel
* @return {*}
*/
func NewConsoleTransport(allowLevel ...Level) *ConsoleTransport {
return &ConsoleTransport{
allowLevel: allowLevel,
}
}

/**
* @description: 是否允许此方式记录日志
* @param {Level} level
* @return {*}
*/
func (c *ConsoleTransport) ShouldLog(level Level) bool {
for _, v := range c.allowLevel {
if v == level {
return true
}
}

return false
}

/**
* @description: 记录日志
* @param {*LogInfo} log
* @return {*}
*/
func (c *ConsoleTransport) Log(log *LogInfo) {
logStr := formatConsole(log)
if log.Level == string(Error) {
fmt.Fprintln(os.Stderr, logStr)
} else {
fmt.Println(logStr)
}
}

/**
* @description: 日志格式化
* @param {*logger.LogInfo} log
* @return {*}
*/
func formatConsole(log *LogInfo) string {
return fmt.Sprintf("%v %v %v %v %v", log.LogTime, log.Level, log.ServiceName, log.AppName, log.Message)
}
11 changes: 11 additions & 0 deletions consts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package remote_log_go

type Level string

const (
Debug Level = "debug"
Info Level = "info"
Warn Level = "warn"
Error Level = "error"
Access Level = "access"
)
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/doubility/remote-log-go

go 1.16
235 changes: 235 additions & 0 deletions http_transport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
package remote_log_go

import (
"bufio"
"bytes"
"compress/zlib"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"time"
"unsafe"
)

type HttpTransport struct {
allowLevel []Level // 允许使用此方式的日志级别
maxBufferLength int64 // 最大缓存字符串长度
maxBufferSize int64 // 最大日志条数
bufferLog []unsafe.Pointer // 缓存日志
bufferLength int64 // 缓存日志长度
bufferChan chan string
t *time.Ticker
}

/**
* @description: 创建HttpTransport类
* @param {...string} allowLevel
* @return {*}
*/
func NewHttpTransport(allowLevel ...Level) *HttpTransport {
h := &HttpTransport{
allowLevel: allowLevel,
maxBufferLength: 50000,
maxBufferSize: 100,
bufferLog: make([]unsafe.Pointer, 0, 200),
bufferLength: 0,
bufferChan: make(chan string, 10000),
t: time.NewTicker(time.Millisecond * 1000),
}
// 定时执行任务、接受chan中的日志
go h.createInterval()

return h
}

func (h *HttpTransport) createInterval() {
for {
select {
case <-h.t.C:
h.flush()
case logStr := <-h.bufferChan:
h.bufferLength += int64(len(logStr))
h.bufferLog = append(h.bufferLog, unsafe.Pointer(&logStr))
if len(h.bufferLog) >= int(h.maxBufferSize) || h.bufferLength >= h.maxBufferLength {
h.flush()
}
}
}
}

/**
* @description: 设置自动上传间隔
* @param {int64} ms
* @return {*}
*/
func (h *HttpTransport) SetFlushInterval(ms int64) {
h.t.Reset(time.Millisecond * time.Duration(ms))
}

/**
* @description: 设置最大缓存字符串长度
* @param {int64} length
* @return {*}
*/
func (h *HttpTransport) SetMaxBufferLength(length int64) {
h.maxBufferLength = length
}

/**
* @description: 设置最大缓存条数
* @param {int64} size
* @return {*}
*/
func (h *HttpTransport) SetMaxBufferSize(size int64) {
h.maxBufferSize = size
h.bufferLog = make([]unsafe.Pointer, 0, size*2)
}

/**
* @description: 是否允许此方式记录日志
* @param {Level} level
* @return {*}
*/
func (h *HttpTransport) ShouldLog(level Level) bool {
for _, v := range h.allowLevel {
if v == level {
return true
}
}

return false
}

/**
* @description: 记录日志
* @param {*LogInfo} log
* @return {*}
*/
func (h *HttpTransport) Log(log *LogInfo) {
logStr := formatHttp(log)
h.bufferChan <- logStr
}

/**
* @description: 处理日志
* @param {*}
* @return {*}
*/
func (h *HttpTransport) flush() {
if len(h.bufferLog) > 0 {
arrStrBufferLog := []string{}
for _, v := range h.bufferLog {
arrStrBufferLog = append(arrStrBufferLog, *(*string)(v))
}
// 长度大于1000时压缩上传
// 压缩失败时,原字符串上传
if h.bufferLength > 1000 {
bytesData, err := json.Marshal(arrStrBufferLog)
if err != nil {
sendLog(1, arrStrBufferLog, "")
}
strLog, err := doZlibCompress(bytesData)
if err != nil {
sendLog(1, arrStrBufferLog, "")
} else {
sendLog(2, []string{}, strLog)
}

} else {
sendLog(1, arrStrBufferLog, "")
}

h.bufferLog = h.bufferLog[:0]
h.bufferLength = 0
}
}

/**
* @description: 请求接口 上传日志
* @param {int32} _type
* @param {[]string} data1
* @param {string} data2
* @return {*}
*/
func sendLog(_type int32, data1 []string, data2 string) {
defer func() {
if err := recover(); err != nil {
data := make(map[string]interface{})
data["type"] = _type
data["data1"] = data1
data["data2"] = data2
bytesData, _ := json.Marshal(data)

httpErrorLog(string(bytesData))

fmt.Println(err)
}
}()

data := make(map[string]interface{})
data["type"] = _type
data["data1"] = data1
data["data2"] = data2
bytesData, _ := json.Marshal(data)

res, err := http.Post(RemoteLogApiUrl+"/api/collectLog?pwd=b3981ef7-694b-11ec-a673-00163e1357b3", "application/json", bytes.NewBuffer(bytesData))
if err != nil {
panic(err)
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}

var response Response
err = json.Unmarshal(body, &response)
if err != nil {
panic(err)
}

if response.Code != 200 {
panic(errors.New(response.Message))
}
}

// 记录上传失败的日志
func httpErrorLog(log string) {
file, _ := os.OpenFile(fmt.Sprintf("%v/error_log_%v.log", ErrorLogPath, time.Now().Format("2006-01-02")), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
defer file.Close()
write := bufio.NewWriter(file)
write.WriteString(log + "\n")
write.Flush()
}

/**
* @description: 日志格式化
* @param {*LogInfo} log
* @return {*}
*/
func formatHttp(log *LogInfo) string {
return fmt.Sprintf("%v|**|%v|**|%v|**|%v|**|%v", log.LogTime, log.Level, log.ServiceName, log.AppName, log.Message)
}

/**
* @description: 压缩字符串
* @param {[]byte} src
* @return {*}
*/
func doZlibCompress(src []byte) (string, error) {
var in bytes.Buffer
w := zlib.NewWriter(&in)
n, err := w.Write(src)
if err != nil || n == 0 {
return "", err
}
err = w.Close()
if err != nil {
return "", err
}

return base64.StdEncoding.EncodeToString(in.Bytes()), nil
}
9 changes: 9 additions & 0 deletions log_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package remote_log_go

type LogInfo struct {
ServiceName string
AppName string
Level string
LogTime string
Message string
}
Loading

0 comments on commit 5b11970

Please sign in to comment.