123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- package main
- import (
- "encoding/json"
- "fmt"
- "os"
- "strings"
- "time"
- "github.com/fluent/fluent-logger-golang/fluent"
- )
- type Output interface {
- Post(time *time.Time, tag string, data map[string]interface{})
- Close()
- }
- type Fluentd struct {
- Host string
- Port int
- Tag string
- clog chan map[string]interface{}
- fluent *fluent.Fluent
- }
- func NewOutputFluentd(host string, port int, tag string, bufferSize int) Output {
- fluent, err := fluent.New(fluent.Config{FluentHost: host, FluentPort: port})
- if err != nil {
- panic(err)
- }
- clog := make(chan map[string]interface{}, bufferSize)
- go func() {
- for message := range clog {
- err := fluent.Post(tag, message)
- if err != nil {
- fmt.Printf("ERROR %s: %v+\n", err, message)
- }
- }
- }()
- return &Fluentd{
- Host: host,
- Port: port,
- Tag: tag,
- clog: clog,
- fluent: fluent,
- }
- }
- func (out *Fluentd) Post(time *time.Time, mtype string, message map[string]interface{}) {
- message["@timestamp"] = time.Format("2006-01-02T15:04:05.000Z07:00")
- message["type"] = mtype
- out.clog <- message
- }
- func (out *Fluentd) Close() {
- out.fluent.Close()
- }
- type OutputFile struct {
- Path string
- FileFormat string
- UID int
- GID int
- flog *os.File
- tnext *time.Time
- }
- func NewOutputFile(Path string, FileFormat string, UID int, GID int) Output {
- return &OutputFile{
- Path: Path,
- FileFormat: FileFormat,
- UID: UID,
- GID: GID,
- }
- }
- func (out *OutputFile) Post(ctime *time.Time, mtype string, message map[string]interface{}) {
- tz := time.Now()
- if out.tnext == nil || tz.After(*out.tnext) {
- flogFlag := os.O_APPEND | os.O_CREATE | os.O_WRONLY
- tnext := tz.Truncate(time.Hour).Add(time.Hour)
- fn := fmt.Sprintf("%s-%s.log", out.Path, tz.Format(out.FileFormat))
- flog, err := os.OpenFile(fn, flogFlag, 0644)
- if err != nil {
- panic(err)
- }
- flog.Chown(out.UID, out.GID)
- out.flog = flog
- out.tnext = &tnext
- }
- fmt.Fprintf(out.flog, "{\"@timestamp\":\"%s\"", ctime.Format("2006-01-02T15:04:05.000Z07:00"))
- message["type"] = mtype
- for k, v := range message {
- vstr, _ := json.Marshal(v)
- fmt.Fprintf(out.flog, ",\"%s\":%s", k, vstr)
- }
- fmt.Fprintln(out.flog, "}")
- }
- func (out *OutputFile) Close() {
- if out.flog != nil {
- out.flog.Close()
- }
- }
- type OutputStdOut struct {
- }
- func NewOutputStdOut() Output {
- return &OutputStdOut{}
- }
- func (out *OutputStdOut) Post(ctime *time.Time, mtype string, message map[string]interface{}) {
- fmt.Printf("%s ", ctime.Format("2006-01-02T15:04:05.000Z07:00"))
- message["type"] = mtype
- for k, v := range message {
- vstr, _ := json.Marshal(v)
- fmt.Printf(" %s:%s", k, vstr)
- }
- }
- func (out *OutputStdOut) Close() {
- }
- type DummyOutputData struct {
- Time time.Time
- Tag string
- Message map[string]interface{}
- }
- type DummyOutput struct {
- data []*DummyOutputData
- }
- func (out *DummyOutput) Post(ctime *time.Time, mtype string, message map[string]interface{}) {
- // fmt.Printf("LOG [%s]\n", message)
- message["type"] = mtype
- out.data = append(out.data, &DummyOutputData{Time: *ctime, Tag: mtype, Message: message})
- }
- func (out *DummyOutput) Close() {
- }
- func (out *DummyOutput) String() string {
- res := []string{}
- for _, v := range out.data {
- str, _ := json.MarshalIndent(v.Message, "", " ")
- res = append(res, string(str))
- }
- return strings.Join(res, "\n")
- }
- func (out *DummyOutput) Field(index int, field string) string {
- if index < len(out.data) {
- f := out.data[index].Message[field]
- if f != nil {
- if v, ok := f.(string); ok {
- return v
- }
- str, _ := json.MarshalIndent(f, "", " ")
- return string(str)
- }
- }
- return ""
- }
|