github.com/astaxie/beego@v1.12.3/logs/alils/alils.go (about)

     1  package alils
     2  
     3  import (
     4  	"encoding/json"
     5  	"strings"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/astaxie/beego/logs"
    10  	"github.com/gogo/protobuf/proto"
    11  )
    12  
    13  const (
    14  	// CacheSize set the flush size
    15  	CacheSize int = 64
    16  	// Delimiter define the topic delimiter
    17  	Delimiter string = "##"
    18  )
    19  
    20  // Config is the Config for Ali Log
    21  type Config struct {
    22  	Project   string   `json:"project"`
    23  	Endpoint  string   `json:"endpoint"`
    24  	KeyID     string   `json:"key_id"`
    25  	KeySecret string   `json:"key_secret"`
    26  	LogStore  string   `json:"log_store"`
    27  	Topics    []string `json:"topics"`
    28  	Source    string   `json:"source"`
    29  	Level     int      `json:"level"`
    30  	FlushWhen int      `json:"flush_when"`
    31  }
    32  
    33  // aliLSWriter implements LoggerInterface.
    34  // it writes messages in keep-live tcp connection.
    35  type aliLSWriter struct {
    36  	store    *LogStore
    37  	group    []*LogGroup
    38  	withMap  bool
    39  	groupMap map[string]*LogGroup
    40  	lock     *sync.Mutex
    41  	Config
    42  }
    43  
    44  // NewAliLS create a new Logger
    45  func NewAliLS() logs.Logger {
    46  	alils := new(aliLSWriter)
    47  	alils.Level = logs.LevelTrace
    48  	return alils
    49  }
    50  
    51  // Init parse config and init struct
    52  func (c *aliLSWriter) Init(jsonConfig string) (err error) {
    53  
    54  	json.Unmarshal([]byte(jsonConfig), c)
    55  
    56  	if c.FlushWhen > CacheSize {
    57  		c.FlushWhen = CacheSize
    58  	}
    59  
    60  	prj := &LogProject{
    61  		Name:            c.Project,
    62  		Endpoint:        c.Endpoint,
    63  		AccessKeyID:     c.KeyID,
    64  		AccessKeySecret: c.KeySecret,
    65  	}
    66  
    67  	c.store, err = prj.GetLogStore(c.LogStore)
    68  	if err != nil {
    69  		return err
    70  	}
    71  
    72  	// Create default Log Group
    73  	c.group = append(c.group, &LogGroup{
    74  		Topic:  proto.String(""),
    75  		Source: proto.String(c.Source),
    76  		Logs:   make([]*Log, 0, c.FlushWhen),
    77  	})
    78  
    79  	// Create other Log Group
    80  	c.groupMap = make(map[string]*LogGroup)
    81  	for _, topic := range c.Topics {
    82  
    83  		lg := &LogGroup{
    84  			Topic:  proto.String(topic),
    85  			Source: proto.String(c.Source),
    86  			Logs:   make([]*Log, 0, c.FlushWhen),
    87  		}
    88  
    89  		c.group = append(c.group, lg)
    90  		c.groupMap[topic] = lg
    91  	}
    92  
    93  	if len(c.group) == 1 {
    94  		c.withMap = false
    95  	} else {
    96  		c.withMap = true
    97  	}
    98  
    99  	c.lock = &sync.Mutex{}
   100  
   101  	return nil
   102  }
   103  
   104  // WriteMsg write message in connection.
   105  // if connection is down, try to re-connect.
   106  func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int) (err error) {
   107  
   108  	if level > c.Level {
   109  		return nil
   110  	}
   111  
   112  	var topic string
   113  	var content string
   114  	var lg *LogGroup
   115  	if c.withMap {
   116  
   117  		// Topic,LogGroup
   118  		strs := strings.SplitN(msg, Delimiter, 2)
   119  		if len(strs) == 2 {
   120  			pos := strings.LastIndex(strs[0], " ")
   121  			topic = strs[0][pos+1 : len(strs[0])]
   122  			content = strs[0][0:pos] + strs[1]
   123  			lg = c.groupMap[topic]
   124  		}
   125  
   126  		// send to empty Topic
   127  		if lg == nil {
   128  			content = msg
   129  			lg = c.group[0]
   130  		}
   131  	} else {
   132  		content = msg
   133  		lg = c.group[0]
   134  	}
   135  
   136  	c1 := &LogContent{
   137  		Key:   proto.String("msg"),
   138  		Value: proto.String(content),
   139  	}
   140  
   141  	l := &Log{
   142  		Time: proto.Uint32(uint32(when.Unix())),
   143  		Contents: []*LogContent{
   144  			c1,
   145  		},
   146  	}
   147  
   148  	c.lock.Lock()
   149  	lg.Logs = append(lg.Logs, l)
   150  	c.lock.Unlock()
   151  
   152  	if len(lg.Logs) >= c.FlushWhen {
   153  		c.flush(lg)
   154  	}
   155  
   156  	return nil
   157  }
   158  
   159  // Flush implementing method. empty.
   160  func (c *aliLSWriter) Flush() {
   161  
   162  	// flush all group
   163  	for _, lg := range c.group {
   164  		c.flush(lg)
   165  	}
   166  }
   167  
   168  // Destroy destroy connection writer and close tcp listener.
   169  func (c *aliLSWriter) Destroy() {
   170  }
   171  
   172  func (c *aliLSWriter) flush(lg *LogGroup) {
   173  
   174  	c.lock.Lock()
   175  	defer c.lock.Unlock()
   176  	err := c.store.PutLogs(lg)
   177  	if err != nil {
   178  		return
   179  	}
   180  
   181  	lg.Logs = make([]*Log, 0, c.FlushWhen)
   182  }
   183  
   184  func init() {
   185  	logs.Register(logs.AdapterAliLS, NewAliLS)
   186  }