Skip to content

Commit d604b73

Browse files
committed
add support log to kafka
add support log to kafka
1 parent 05fdae1 commit d604b73

File tree

3 files changed

+196
-2
lines changed

3 files changed

+196
-2
lines changed

Diff for: go.mod

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ module github.com/qclaogui/lg
33
go 1.12
44

55
require (
6-
github.com/davecgh/go-spew v1.1.1 // indirect
6+
github.com/Shopify/sarama v1.23.1
77
github.com/pkg/errors v0.8.1 // indirect
8-
github.com/stretchr/testify v1.3.0 // indirect
98
go.uber.org/atomic v1.4.0 // indirect
109
go.uber.org/multierr v1.1.0 // indirect
1110
go.uber.org/zap v1.10.0

Diff for: go.sum

+35
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,52 @@
1+
github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798 h1:2T/jmrHeTezcCM58lvEQXs0UpQJCo5SoGAcg+mbSTIg=
2+
github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
3+
github.com/Shopify/sarama v1.23.1 h1:XxJBCZEoWJtoWjf/xRbmGUpAmTZGnuuF0ON0EvxxBrs=
4+
github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs=
5+
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
6+
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
17
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
28
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
39
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
410
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
11+
github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU=
12+
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
13+
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
14+
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
15+
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
16+
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
17+
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
18+
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
19+
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
20+
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03 h1:FUwcHNlEqkqLjLBdCp5PRlCFijNjvcYANOZXzCfXwCM=
21+
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
22+
github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41 h1:GeinFsrjWz97fAxVUEd748aV0cYL+I6k44gFJTCVvpU=
23+
github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
524
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
625
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
26+
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
727
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
828
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
29+
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
30+
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
931
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
1032
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
1133
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
34+
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
35+
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
1236
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
1337
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
1438
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
1539
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
1640
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
1741
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
42+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
43+
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
44+
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
45+
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
46+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
47+
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
48+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
49+
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
50+
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
51+
gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
52+
gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=

Diff for: kafka.go

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package lg
2+
3+
import (
4+
"io"
5+
"os"
6+
"strings"
7+
8+
"go.uber.org/zap"
9+
"go.uber.org/zap/zapcore"
10+
11+
"github.com/Shopify/sarama"
12+
)
13+
14+
// kafkaConfig contains information
15+
type kafkaConfig struct {
16+
Hosts string
17+
Topic string
18+
}
19+
20+
// write2Kafka is used for sending logs to kafka.
21+
type write2Kafka struct {
22+
config *kafkaConfig
23+
syncProducer sarama.SyncProducer
24+
}
25+
26+
func (w *write2Kafka) Write(b []byte) (n int, err error) {
27+
if _, _, err = w.syncProducer.SendMessage(&sarama.ProducerMessage{
28+
Topic: w.config.Topic,
29+
Value: sarama.ByteEncoder(b),
30+
}); err != nil {
31+
return
32+
}
33+
n = len(b)
34+
return
35+
}
36+
37+
func newLog2Kafka(cfg *kafkaConfig) (*write2Kafka, error) {
38+
config := sarama.NewConfig()
39+
// SyncProducer
40+
config.Producer.RequiredAcks = sarama.WaitForLocal // Only wait for the leader to ack
41+
config.Producer.Compression = sarama.CompressionSnappy // Compress messages
42+
// Producer.Return.Successes must be true to be used in a SyncProducer
43+
config.Producer.Return.Successes = true
44+
45+
var brokerList []string
46+
for _, broker := range strings.Split(cfg.Hosts, ",") {
47+
if strings.Index(broker, ":") == -1 {
48+
broker += ":9092"
49+
}
50+
brokerList = append(brokerList, broker)
51+
}
52+
53+
var producer sarama.SyncProducer
54+
var err error
55+
if producer, err = sarama.NewSyncProducer(brokerList, config); err != nil {
56+
return nil, err
57+
}
58+
59+
return &write2Kafka{config: cfg, syncProducer: producer}, nil
60+
}
61+
62+
// Init initializes log by input parameters
63+
// lvl - global log level: Debug(-1), Info(0), Warn(1), Error(2), DPanic(3), Panic(4), Fatal(5)
64+
// timeFormat - custom time format for logger of empty string to use default
65+
func InitOnlyKafka(lvl int, project, kafkaTopic, brokers string) (err error) {
66+
onceInit.Do(func() {
67+
globalLevel := zapcore.Level(lvl)
68+
69+
KafkaPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
70+
return lvl >= globalLevel
71+
})
72+
var ws io.Writer
73+
if ws, err = newLog2Kafka(&kafkaConfig{Hosts: brokers, Topic: kafkaTopic}); err != nil {
74+
return
75+
}
76+
77+
// Configure console output.
78+
cfg := zap.NewProductionEncoderConfig()
79+
if len(TimeFormat) > 0 {
80+
cfg.TimeKey = "tsp"
81+
cfg.EncodeTime = customTimeEncoder
82+
}
83+
84+
// Optimize the Kafka output for machine consumption and the console output
85+
// for human operators.
86+
core := zapcore.NewTee(zapcore.NewCore(zapcore.NewJSONEncoder(cfg), zapcore.Lock(zapcore.AddSync(ws)), KafkaPriority))
87+
88+
// ErrorLevel 堆栈跟踪
89+
stackTrace := zap.AddStacktrace(zap.ErrorLevel)
90+
// 设置初始化字段
91+
fields := zap.Fields(zap.Object("info", &commonInfo{project, getHostName()}))
92+
93+
// From a zapcore.Core, it's easy to construct a Logger.
94+
APPLog = zap.New(core, fields, stackTrace)
95+
})
96+
return err
97+
}
98+
99+
// Init initializes log by input parameters
100+
// lvl - global log level: Debug(-1), Info(0), Warn(1), Error(2), DPanic(3), Panic(4), Fatal(5)
101+
// timeFormat - custom time format for logger of empty string to use default
102+
func InitWithKafka(lvl int, project, kafkaTopic, brokers string) (err error) {
103+
onceInit.Do(func() {
104+
// First, define our level-handling logic.
105+
globalLevel := zapcore.Level(lvl)
106+
// High-priority output should also go to standard error, and low-priority
107+
// output should also go to standard out.
108+
// It is usefull for Kubernetes deployment.
109+
// Kubernetes interprets os.Stdout log items as INFO and os.Stderr log items
110+
// as ERROR by default.
111+
highPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
112+
return lvl >= zapcore.ErrorLevel
113+
})
114+
lowPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
115+
return lvl >= globalLevel && lvl < zapcore.ErrorLevel
116+
})
117+
118+
KafkaPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
119+
return lvl >= globalLevel
120+
})
121+
// Assume that we have clients for two Kafka topics. The clients implement
122+
// zapcore.WriteSyncer and are safe for concurrent use. (If they only
123+
// implement io.Writer, we can use zapcore.AddSync to add a no-op Sync
124+
// method. If they're not safe for concurrent use, we can add a protecting
125+
// mutex with zapcore.Lock.)
126+
var ws io.Writer
127+
if ws, err = newLog2Kafka(&kafkaConfig{Hosts: brokers, Topic: kafkaTopic}); err != nil {
128+
return
129+
}
130+
131+
// Configure console output.
132+
cfg := zap.NewProductionEncoderConfig()
133+
if len(TimeFormat) > 0 {
134+
cfg.TimeKey = "tsp"
135+
cfg.EncodeTime = customTimeEncoder
136+
}
137+
138+
// Optimize the Kafka output for machine consumption and the console output
139+
// for human operators.
140+
kafkaEncoder := zapcore.NewJSONEncoder(cfg)
141+
consoleEncoder := zapcore.NewJSONEncoder(cfg)
142+
// Join the outputs, encoders, and level-handling functions into
143+
// zapcore.Cores, then tee the four cores together.
144+
core := zapcore.NewTee(
145+
zapcore.NewCore(kafkaEncoder, zapcore.Lock(zapcore.AddSync(ws)), KafkaPriority),
146+
// 同时写一份到标准输出
147+
zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stdout), lowPriority),
148+
zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stderr), highPriority),
149+
)
150+
151+
// ErrorLevel 堆栈跟踪
152+
stackTrace := zap.AddStacktrace(zap.ErrorLevel)
153+
// 设置初始化字段
154+
fields := zap.Fields(zap.Object("info", &commonInfo{project, getHostName()}))
155+
156+
// From a zapcore.Core, it's easy to construct a Logger.
157+
APPLog = zap.New(core, fields, stackTrace)
158+
})
159+
return err
160+
}

0 commit comments

Comments
 (0)