upate plugin logic

This commit is contained in:
joy.zhou
2019-08-16 17:59:15 +08:00
parent e8ceea87b4
commit 93c02b0ea9
41 changed files with 429 additions and 890 deletions
+4 -3
View File
@@ -55,9 +55,10 @@ Common Options:
"certFile": "tls/server/cert.pem",
"keyFile": "tls/server/key.pem"
},
"acl":true,
"aclConf":"conf/acl.conf",
"plugins": ["authhttp","kafka"]
"plugins": {
"auth": "authhttp",
"bridge": "kafka"
}
}
~~~
+10 -8
View File
@@ -4,8 +4,6 @@ package broker
import (
"strings"
"github.com/fhmq/hmq/plugins/authhttp"
)
const (
@@ -14,16 +12,20 @@ const (
)
func (b *Broker) CheckTopicAuth(action, username, topic string) bool {
if b.pluginAuthHTTP {
if b.Auth != nil {
if strings.HasPrefix(topic, "$SYS/broker/connection/clients/") {
return true
}
if strings.HasPrefix(topic, "$queue/") {
topic = strings.TrimPrefix(topic, "$queue/")
if strings.HasPrefix(topic, "$share/") && action == SUB {
substr := groupCompile.FindStringSubmatch(topic)
if len(substr) != 3 {
return false
}
topic = substr[2]
}
return authhttp.CheckACL(username, action, topic)
return b.Auth.CheckACL(action, username, topic)
}
return true
@@ -31,11 +33,11 @@ func (b *Broker) CheckTopicAuth(action, username, topic string) bool {
}
func (b *Broker) CheckConnectAuth(clientID, username, password string) bool {
if b.pluginAuthHTTP {
if b.Auth != nil {
if clientID == "" || username == "" {
return false
}
return authhttp.CheckAuth(clientID, username, password)
return b.Auth.CheckConnect(clientID, username, password)
}
return true
+23 -29
View File
@@ -13,14 +13,16 @@ import (
"sync"
"time"
"github.com/tidwall/gjson"
"github.com/fhmq/hmq/plugins/auth"
"github.com/fhmq/hmq/plugins/bridge"
"github.com/fhmq/hmq/broker/lib/sessions"
"github.com/fhmq/hmq/broker/lib/topics"
pb "github.com/fhmq/hmq/grpc"
"github.com/fhmq/hmq/plugins"
"github.com/eclipse/paho.mqtt.golang/packets"
"github.com/fhmq/hmq/plugins/authhttp"
"github.com/fhmq/hmq/plugins/kafka"
"github.com/fhmq/hmq/pool"
"github.com/shirou/gopsutil/mem"
"go.uber.org/zap"
@@ -38,19 +40,19 @@ type Message struct {
}
type Broker struct {
id string
mu sync.Mutex
config *Config
tlsConfig *tls.Config
wpool *pool.WorkerPool
clients sync.Map
nodes map[string]interface{}
clusterPool chan *Message
topicsMgr *topics.Manager
sessionMgr *sessions.Manager
rpcClient map[string]pb.HMQServiceClient
pluginAuthHTTP bool
pluginKafka bool
id string
mu sync.Mutex
config *Config
tlsConfig *tls.Config
wpool *pool.WorkerPool
clients sync.Map
nodes map[string]gjson.Result
clusterPool chan *Message
topicsMgr *topics.Manager
sessionMgr *sessions.Manager
rpcClient map[string]pb.HMQServiceClient
Auth auth.Auth
BridgeMQ bridge.BridgeMQ
}
func newMessagePool() []chan *Message {
@@ -71,7 +73,7 @@ func NewBroker(config *Config) (*Broker, error) {
id: GenUniqueId(),
config: config,
wpool: pool.New(config.Worker),
nodes: make(map[string]interface{}),
nodes: make(map[string]gjson.Result),
clusterPool: make(chan *Message),
rpcClient: make(map[string]pb.HMQServiceClient),
}
@@ -98,16 +100,8 @@ func NewBroker(config *Config) (*Broker, error) {
b.tlsConfig = tlsconfig
}
for _, plugin := range b.config.Plugins {
switch plugin {
case authhttp.AuthHTTP:
authhttp.Init()
b.pluginAuthHTTP = true
case kafka.Kafka:
kafka.Init()
b.pluginKafka = true
}
}
b.Auth = auth.NewAuth(b.config.Plugin.Auth)
b.BridgeMQ = bridge.NewBridgeMQ(b.config.Plugin.Bridge)
return b, nil
}
@@ -316,10 +310,10 @@ func (b *Broker) handleConnection(typ int, conn net.Conn) {
}
if typ == CLIENT {
b.Publish(&plugins.Elements{
b.Publish(&bridge.Elements{
ClientID: string(msg.ClientIdentifier),
Username: string(msg.Username),
Action: plugins.Connect,
Action: bridge.Connect,
Timestamp: time.Now().Unix(),
})
}
+9 -9
View File
@@ -15,7 +15,7 @@ import (
"github.com/fhmq/hmq/broker/lib/sessions"
"github.com/fhmq/hmq/broker/lib/topics"
"github.com/fhmq/hmq/plugins"
"github.com/fhmq/hmq/plugins/bridge"
"github.com/eclipse/paho.mqtt.golang/packets"
"go.uber.org/zap"
@@ -217,10 +217,10 @@ func (c *client) processClientPublish(packet *packets.PublishPacket) {
}
//publish kafka
c.broker.Publish(&plugins.Elements{
c.broker.Publish(&bridge.Elements{
ClientID: c.info.clientID,
Username: c.info.username,
Action: plugins.Publish,
Action: bridge.Publish,
Timestamp: time.Now().Unix(),
Payload: string(packet.Payload),
Topic: topic,
@@ -278,10 +278,10 @@ func (c *client) processClientSubscribe(packet *packets.SubscribePacket) {
continue
}
b.Publish(&plugins.Elements{
b.Publish(&bridge.Elements{
ClientID: c.info.clientID,
Username: c.info.username,
Action: plugins.Subscribe,
Action: bridge.Subscribe,
Timestamp: time.Now().Unix(),
Topic: topic,
})
@@ -361,10 +361,10 @@ func (c *client) processClientUnSubscribe(packet *packets.UnsubscribePacket) {
{
//publish kafka
b.Publish(&plugins.Elements{
b.Publish(&bridge.Elements{
ClientID: c.info.clientID,
Username: c.info.username,
Action: plugins.Unsubscribe,
Action: bridge.Unsubscribe,
Timestamp: time.Now().Unix(),
Topic: topic,
})
@@ -412,10 +412,10 @@ func (c *client) Close() {
c.status = Disconnected
b := c.broker
b.Publish(&plugins.Elements{
b.Publish(&bridge.Elements{
ClientID: c.info.clientID,
Username: c.info.username,
Action: plugins.Disconnect,
Action: bridge.Disconnect,
Timestamp: time.Now().Unix(),
})
+20 -15
View File
@@ -18,21 +18,26 @@ import (
)
type Config struct {
Worker int `json:"workerNum"`
Host string `json:"host"`
Port string `json:"port"`
RpcPort string `json:"rpc"`
Router string `json:"router"`
TlsHost string `json:"tlsHost"`
TlsPort string `json:"tlsPort"`
WsPath string `json:"wsPath"`
WsPort string `json:"wsPort"`
WsTLS bool `json:"wsTLS"`
TlsInfo TLSInfo `json:"tlsInfo"`
Acl bool `json:"acl"`
AclConf string `json:"aclConf"`
Debug bool `json:"debug"`
Plugins []string `json:"plugins"`
Worker int `json:"workerNum"`
Host string `json:"host"`
Port string `json:"port"`
RpcPort string `json:"rpc"`
Router string `json:"router"`
TlsHost string `json:"tlsHost"`
TlsPort string `json:"tlsPort"`
WsPath string `json:"wsPath"`
WsPort string `json:"wsPort"`
WsTLS bool `json:"wsTLS"`
TlsInfo TLSInfo `json:"tlsInfo"`
Acl bool `json:"acl"`
AclConf string `json:"aclConf"`
Debug bool `json:"debug"`
Plugin Plugins `json:"plugins"`
}
type Plugins struct {
Auth string
Bridge string
}
type TLSInfo struct {
+7 -13
View File
@@ -6,7 +6,8 @@ import (
"fmt"
"time"
simplejson "github.com/bitly/go-simplejson"
"github.com/tidwall/gjson"
"github.com/eclipse/paho.mqtt.golang/packets"
"go.uber.org/zap"
)
@@ -80,15 +81,9 @@ func (c *client) ProcessInfo(packet *packets.PublishPacket) {
log.Info("recv remoteInfo: ", zap.String("payload", string(packet.Payload)))
js, err := simplejson.NewJson(packet.Payload)
if err != nil {
log.Warn("parse info message err", zap.Error(err))
return
}
routes, err := js.Get("data").Map()
if routes == nil {
log.Error("receive info message error, ", zap.Error(err))
routes := gjson.GetBytes(packet.Payload, "data").Map()
if len(routes) == 0 {
log.Error("receive nil info message ", zap.String("info", string(packet.Payload)))
return
}
@@ -100,9 +95,8 @@ func (c *client) ProcessInfo(packet *packets.PublishPacket) {
continue
}
url, ok := rurl.(string)
if ok {
//todo new rpc client
url := rurl.String()
if url != "" {
if _, exist := b.rpcClient[rid]; !exist {
b.initRPCClient(rid, url)
}
+8 -5
View File
@@ -1,12 +1,15 @@
package broker
import (
"github.com/fhmq/hmq/plugins"
"github.com/fhmq/hmq/plugins/kafka"
"github.com/fhmq/hmq/plugins/bridge"
"go.uber.org/zap"
)
func (b *Broker) Publish(e *plugins.Elements) {
if b.pluginKafka {
kafka.Publish(e)
func (b *Broker) Publish(e *bridge.Elements) {
if b.BridgeMQ != nil {
err := b.BridgeMQ.Publish(e)
if err != nil {
log.Error("send message to mq error.", zap.Error(err))
}
}
}
+3 -4
View File
@@ -69,7 +69,7 @@ func (b *Broker) ConnectToDiscovery() {
func (b *Broker) checkNodeExist(id, url string) bool {
if id == b.id {
return false
return false //skip self
}
for k, v := range b.nodes {
@@ -77,9 +77,8 @@ func (b *Broker) checkNodeExist(id, url string) bool {
return true
}
//skip
l, ok := v.(string)
if ok {
l := v.String()
if l != "" {
if url == l {
return true
}
+4 -4
View File
@@ -15,8 +15,8 @@
"certFile": "ssl/server/cert.pem",
"keyFile": "ssl/server/key.pem"
},
"plugins": [
"authhttp",
"kafka"
]
"plugins": {
"auth": "authhttp",
"bridge": "kafka"
}
}
+3 -4
View File
@@ -5,8 +5,6 @@ go 1.12
require (
github.com/Shopify/sarama v1.23.0
github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 // indirect
github.com/bitly/go-simplejson v0.5.0
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/gin-gonic/gin v1.4.0
github.com/go-ole/go-ole v1.2.4 // indirect
@@ -19,13 +17,14 @@ require (
github.com/shirou/gopsutil v2.18.12+incompatible
github.com/stretchr/testify v1.3.0
github.com/tidwall/gjson v1.3.0
go.uber.org/atomic v1.3.2 // indirect
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/multierr v1.1.0 // indirect
go.uber.org/zap v1.9.1
go.uber.org/zap v1.10.0
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80
golang.org/x/sys v0.0.0-20190730183949-1393eb018365 // indirect
golang.org/x/text v0.3.2 // indirect
google.golang.org/appengine v1.4.0 // indirect
google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610 // indirect
google.golang.org/grpc v1.22.1
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
+4 -8
View File
@@ -8,10 +8,6 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWso
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 h1:UUppSQnhf4Yc6xGxSkoQpPhb7RVzuv5Nb1mwJ5VId9s=
github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -89,12 +85,12 @@ github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
+14 -5
View File
@@ -5,19 +5,27 @@ package logger
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var (
// env can be setup at build time with Go Linker. Value could be prod or whatever else for dev env
instance *zap.Logger
logCfg zap.Config
instance *zap.Logger
logCfg zap.Config
encoderCfg = zap.NewProductionEncoderConfig()
)
func init() {
encoderCfg.TimeKey = "timestamp"
encoderCfg.EncodeTime = zapcore.ISO8601TimeEncoder
}
// NewDevLogger return a logger for dev builds
func NewDevLogger() (*zap.Logger, error) {
logCfg := zap.NewDevelopmentConfig()
// logCfg.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
logCfg.DisableStacktrace = true
logCfg := zap.NewProductionConfig()
logCfg.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
// logCfg.DisableStacktrace = true
logCfg.EncoderConfig = encoderCfg
return logCfg.Build()
}
@@ -26,6 +34,7 @@ func NewProdLogger() (*zap.Logger, error) {
logCfg := zap.NewProductionConfig()
logCfg.DisableStacktrace = true
logCfg.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
logCfg.EncoderConfig = encoderCfg
return logCfg.Build()
}
+23
View File
@@ -0,0 +1,23 @@
package auth
import (
"github.com/fhmq/hmq/plugins/auth/authhttp"
)
const (
AuthHTTP = "authhttp"
)
type Auth interface {
CheckACL(action, username, topic string) bool
CheckConnect(clientID, username, password string) bool
}
func NewAuth(name string) Auth {
switch name {
case AuthHTTP:
return authhttp.Init()
default:
return &mockAuth{}
}
}
@@ -14,17 +14,6 @@ import (
"go.uber.org/zap"
)
const (
//AuthHTTP plugin name
AuthHTTP = "authhttp"
)
var (
config Config
log = logger.Get().Named("http")
httpClient *http.Client
)
//Config device kafka config
type Config struct {
AuthURL string `json:"auth"`
@@ -32,9 +21,19 @@ type Config struct {
SuperURL string `json:"super"`
}
type authHTTP struct {
client *http.Client
}
var (
config Config
log = logger.Get().Named("authhttp")
httpClient *http.Client
)
//Init init kafak client
func Init() {
content, err := ioutil.ReadFile("./plugins/authhttp/http.json")
func Init() *authHTTP {
content, err := ioutil.ReadFile("./plugins/auth/authhttp/http.json")
if err != nil {
log.Fatal("Read config file error: ", zap.Error(err))
}
@@ -54,11 +53,11 @@ func Init() {
},
Timeout: time.Second * 100,
}
return &authHTTP{client: httpClient}
}
//CheckAuth check mqtt connect
func CheckAuth(clientID, username, password string) bool {
func (a *authHTTP) CheckConnect(clientID, username, password string) bool {
action := "connect"
{
aCache := checkCache(action, clientID, username, password, "")
@@ -82,7 +81,7 @@ func CheckAuth(clientID, username, password string) bool {
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
resp, err := httpClient.Do(req)
resp, err := a.client.Do(req)
if err != nil {
log.Error("request super: ", zap.Error(err))
return false
@@ -98,48 +97,48 @@ func CheckAuth(clientID, username, password string) bool {
return false
}
//CheckSuper check mqtt connect
func CheckSuper(clientID, username, password string) bool {
action := "connect"
{
aCache := checkCache(action, clientID, username, password, "")
if aCache != nil {
if aCache.password == password && aCache.username == username && aCache.action == action {
return true
}
}
}
// //CheckSuper check mqtt connect
// func CheckSuper(clientID, username, password string) bool {
// action := "connect"
// {
// aCache := checkCache(action, clientID, username, password, "")
// if aCache != nil {
// if aCache.password == password && aCache.username == username && aCache.action == action {
// return true
// }
// }
// }
data := url.Values{}
data.Add("username", username)
data.Add("clientid", clientID)
data.Add("password", password)
// data := url.Values{}
// data.Add("username", username)
// data.Add("clientid", clientID)
// data.Add("password", password)
req, err := http.NewRequest("POST", config.SuperURL, strings.NewReader(data.Encode()))
if err != nil {
log.Error("new request super: ", zap.Error(err))
return false
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
// req, err := http.NewRequest("POST", config.SuperURL, strings.NewReader(data.Encode()))
// if err != nil {
// log.Error("new request super: ", zap.Error(err))
// return false
// }
// req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
// req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
resp, err := httpClient.Do(req)
if err != nil {
log.Error("request super: ", zap.Error(err))
return false
}
// resp, err := httpClient.Do(req)
// if err != nil {
// log.Error("request super: ", zap.Error(err))
// return false
// }
defer resp.Body.Close()
io.Copy(ioutil.Discard, resp.Body)
// defer resp.Body.Close()
// io.Copy(ioutil.Discard, resp.Body)
if resp.StatusCode == http.StatusOK {
return true
}
return false
}
// if resp.StatusCode == http.StatusOK {
// return true
// }
// return false
// }
//CheckACL check mqtt connect
func CheckACL(username, access, topic string) bool {
func (a *authHTTP) CheckACL(username, access, topic string) bool {
action := access
{
aCache := checkCache(action, "", username, "", topic)
@@ -163,7 +162,7 @@ func CheckACL(username, access, topic string) bool {
data.Add("access", access)
req.URL.RawQuery = data.Encode()
// fmt.Println("req:", req)
resp, err := httpClient.Do(req)
resp, err := a.client.Do(req)
if err != nil {
log.Error("request acl: ", zap.Error(err))
return false
+11
View File
@@ -0,0 +1,11 @@
package auth
type mockAuth struct{}
func (m *mockAuth) CheckACL(action, username, topic string) bool {
return true
}
func (m *mockAuth) CheckConnect(clientID, username, password string) bool {
return true
}
@@ -1,4 +1,6 @@
package plugins
package bridge
import "github.com/fhmq/hmq/logger"
const (
//Connect mqtt connect
@@ -13,6 +15,10 @@ const (
Disconnect = "disconnect"
)
var (
log = logger.Get().Named("bridge")
)
//Elements kafka publish elements
type Elements struct {
ClientID string `json:"clientid"`
@@ -23,3 +29,21 @@ type Elements struct {
Size int32 `json:"size"`
Action string `json:"action"`
}
const (
//Kafka plugin name
Kafka = "kafka"
)
type BridgeMQ interface {
Publish(e *Elements) error
}
func NewBridgeMQ(name string) BridgeMQ {
switch name {
case Kafka:
return InitKafka()
default:
return &mockMQ{}
}
}
@@ -1,29 +1,16 @@
package kafka
package bridge
import (
"encoding/json"
"errors"
"io/ioutil"
"regexp"
"github.com/Shopify/sarama"
"github.com/fhmq/hmq/logger"
"github.com/fhmq/hmq/plugins"
"go.uber.org/zap"
)
const (
//Kafka plugin name
Kafka = "kafka"
)
var (
kafkaClient sarama.AsyncProducer
config Config
log = logger.Get().Named("kafka")
)
//Config device kafka config
type Config struct {
type kafakConfig struct {
Addr []string `json:"addr"`
ConnectTopic string `json:"onConnect"`
SubscribeTopic string `json:"onSubscribe"`
@@ -33,28 +20,34 @@ type Config struct {
RegexpMap map[string]string `json:"regexpMap"`
}
type kafka struct {
kafakConfig kafakConfig
kafkaClient sarama.AsyncProducer
}
//Init init kafak client
func Init() {
func InitKafka() *kafka {
log.Info("start connect kafka....")
content, err := ioutil.ReadFile("./plugins/kafka/kafka.json")
content, err := ioutil.ReadFile("./plugins/mq/kafka/kafka.json")
if err != nil {
log.Fatal("Read config file error: ", zap.Error(err))
}
// log.Info(string(content))
var config kafakConfig
err = json.Unmarshal(content, &config)
if err != nil {
log.Fatal("Unmarshal config file error: ", zap.Error(err))
}
connect()
c := &kafka{kafakConfig: config}
c.connect()
return c
}
//connect
func connect() {
var err error
func (k *kafka) connect() {
conf := sarama.NewConfig()
conf.Version = sarama.V1_1_1_0
kafkaClient, err = sarama.NewAsyncProducer(config.Addr, conf)
kafkaClient, err := sarama.NewAsyncProducer(k.kafakConfig.Addr, conf)
if err != nil {
log.Fatal("create kafka async producer failed: ", zap.Error(err))
}
@@ -64,18 +57,21 @@ func connect() {
log.Error("send msg to kafka failed: ", zap.Error(err))
}
}()
k.kafkaClient = kafkaClient
}
//Publish publish to kafka
func Publish(e *plugins.Elements) {
func (k *kafka) Publish(e *Elements) error {
config := k.kafakConfig
key := e.ClientID
var topics []string
switch e.Action {
case plugins.Connect:
case Connect:
if config.ConnectTopic != "" {
topics = append(topics, config.ConnectTopic)
}
case plugins.Publish:
case Publish:
if config.PublishTopic != "" {
topics = append(topics, config.PublishTopic)
}
@@ -86,38 +82,34 @@ func Publish(e *plugins.Elements) {
topics = append(topics, topic)
}
}
case plugins.Subscribe:
case Subscribe:
if config.SubscribeTopic != "" {
topics = append(topics, config.SubscribeTopic)
}
case plugins.Unsubscribe:
case Unsubscribe:
if config.UnsubscribeTopic != "" {
topics = append(topics, config.UnsubscribeTopic)
}
case plugins.Disconnect:
case Disconnect:
if config.DisconnectTopic != "" {
topics = append(topics, config.DisconnectTopic)
}
default:
log.Error("error action: ", zap.String("action", e.Action))
return
return errors.New("error action: " + e.Action)
}
err := publish(topics, key, e)
if err != nil {
log.Error("publish kafka error: ", zap.Error(err))
}
return k.publish(topics, key, e)
}
func publish(topics []string, key string, msg *plugins.Elements) error {
func (k *kafka) publish(topics []string, key string, msg *Elements) error {
payload, err := json.Marshal(msg)
if err != nil {
return err
}
for _, topic := range topics {
kafkaClient.Input() <- &sarama.ProducerMessage{
k.kafkaClient.Input() <- &sarama.ProducerMessage{
Topic: topic,
Key: sarama.ByteEncoder(key),
Value: sarama.ByteEncoder(payload),
+7
View File
@@ -0,0 +1,7 @@
package bridge
type mockMQ struct{}
func (m *mockMQ) Publish(e *Elements) error {
return nil
}
-10
View File
@@ -1,10 +0,0 @@
language: go
go:
- 1.0.3
- 1.1.2
- 1.2
- tip
install:
- go get github.com/bmizerany/assert
notifications:
email: false
-17
View File
@@ -1,17 +0,0 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-13
View File
@@ -1,13 +0,0 @@
### go-simplejson
a Go package to interact with arbitrary JSON
[![Build Status](https://secure.travis-ci.org/bitly/go-simplejson.png)](http://travis-ci.org/bitly/go-simplejson)
### Importing
import github.com/bitly/go-simplejson
### Documentation
Visit the docs on [gopkgdoc](http://godoc.org/github.com/bitly/go-simplejson)
-446
View File
@@ -1,446 +0,0 @@
package simplejson
import (
"encoding/json"
"errors"
"log"
)
// returns the current implementation version
func Version() string {
return "0.5.0"
}
type Json struct {
data interface{}
}
// NewJson returns a pointer to a new `Json` object
// after unmarshaling `body` bytes
func NewJson(body []byte) (*Json, error) {
j := new(Json)
err := j.UnmarshalJSON(body)
if err != nil {
return nil, err
}
return j, nil
}
// New returns a pointer to a new, empty `Json` object
func New() *Json {
return &Json{
data: make(map[string]interface{}),
}
}
// Interface returns the underlying data
func (j *Json) Interface() interface{} {
return j.data
}
// Encode returns its marshaled data as `[]byte`
func (j *Json) Encode() ([]byte, error) {
return j.MarshalJSON()
}
// EncodePretty returns its marshaled data as `[]byte` with indentation
func (j *Json) EncodePretty() ([]byte, error) {
return json.MarshalIndent(&j.data, "", " ")
}
// Implements the json.Marshaler interface.
func (j *Json) MarshalJSON() ([]byte, error) {
return json.Marshal(&j.data)
}
// Set modifies `Json` map by `key` and `value`
// Useful for changing single key/value in a `Json` object easily.
func (j *Json) Set(key string, val interface{}) {
m, err := j.Map()
if err != nil {
return
}
m[key] = val
}
// SetPath modifies `Json`, recursively checking/creating map keys for the supplied path,
// and then finally writing in the value
func (j *Json) SetPath(branch []string, val interface{}) {
if len(branch) == 0 {
j.data = val
return
}
// in order to insert our branch, we need map[string]interface{}
if _, ok := (j.data).(map[string]interface{}); !ok {
// have to replace with something suitable
j.data = make(map[string]interface{})
}
curr := j.data.(map[string]interface{})
for i := 0; i < len(branch)-1; i++ {
b := branch[i]
// key exists?
if _, ok := curr[b]; !ok {
n := make(map[string]interface{})
curr[b] = n
curr = n
continue
}
// make sure the value is the right sort of thing
if _, ok := curr[b].(map[string]interface{}); !ok {
// have to replace with something suitable
n := make(map[string]interface{})
curr[b] = n
}
curr = curr[b].(map[string]interface{})
}
// add remaining k/v
curr[branch[len(branch)-1]] = val
}
// Del modifies `Json` map by deleting `key` if it is present.
func (j *Json) Del(key string) {
m, err := j.Map()
if err != nil {
return
}
delete(m, key)
}
// Get returns a pointer to a new `Json` object
// for `key` in its `map` representation
//
// useful for chaining operations (to traverse a nested JSON):
// js.Get("top_level").Get("dict").Get("value").Int()
func (j *Json) Get(key string) *Json {
m, err := j.Map()
if err == nil {
if val, ok := m[key]; ok {
return &Json{val}
}
}
return &Json{nil}
}
// GetPath searches for the item as specified by the branch
// without the need to deep dive using Get()'s.
//
// js.GetPath("top_level", "dict")
func (j *Json) GetPath(branch ...string) *Json {
jin := j
for _, p := range branch {
jin = jin.Get(p)
}
return jin
}
// GetIndex returns a pointer to a new `Json` object
// for `index` in its `array` representation
//
// this is the analog to Get when accessing elements of
// a json array instead of a json object:
// js.Get("top_level").Get("array").GetIndex(1).Get("key").Int()
func (j *Json) GetIndex(index int) *Json {
a, err := j.Array()
if err == nil {
if len(a) > index {
return &Json{a[index]}
}
}
return &Json{nil}
}
// CheckGet returns a pointer to a new `Json` object and
// a `bool` identifying success or failure
//
// useful for chained operations when success is important:
// if data, ok := js.Get("top_level").CheckGet("inner"); ok {
// log.Println(data)
// }
func (j *Json) CheckGet(key string) (*Json, bool) {
m, err := j.Map()
if err == nil {
if val, ok := m[key]; ok {
return &Json{val}, true
}
}
return nil, false
}
// Map type asserts to `map`
func (j *Json) Map() (map[string]interface{}, error) {
if m, ok := (j.data).(map[string]interface{}); ok {
return m, nil
}
return nil, errors.New("type assertion to map[string]interface{} failed")
}
// Array type asserts to an `array`
func (j *Json) Array() ([]interface{}, error) {
if a, ok := (j.data).([]interface{}); ok {
return a, nil
}
return nil, errors.New("type assertion to []interface{} failed")
}
// Bool type asserts to `bool`
func (j *Json) Bool() (bool, error) {
if s, ok := (j.data).(bool); ok {
return s, nil
}
return false, errors.New("type assertion to bool failed")
}
// String type asserts to `string`
func (j *Json) String() (string, error) {
if s, ok := (j.data).(string); ok {
return s, nil
}
return "", errors.New("type assertion to string failed")
}
// Bytes type asserts to `[]byte`
func (j *Json) Bytes() ([]byte, error) {
if s, ok := (j.data).(string); ok {
return []byte(s), nil
}
return nil, errors.New("type assertion to []byte failed")
}
// StringArray type asserts to an `array` of `string`
func (j *Json) StringArray() ([]string, error) {
arr, err := j.Array()
if err != nil {
return nil, err
}
retArr := make([]string, 0, len(arr))
for _, a := range arr {
if a == nil {
retArr = append(retArr, "")
continue
}
s, ok := a.(string)
if !ok {
return nil, err
}
retArr = append(retArr, s)
}
return retArr, nil
}
// MustArray guarantees the return of a `[]interface{}` (with optional default)
//
// useful when you want to interate over array values in a succinct manner:
// for i, v := range js.Get("results").MustArray() {
// fmt.Println(i, v)
// }
func (j *Json) MustArray(args ...[]interface{}) []interface{} {
var def []interface{}
switch len(args) {
case 0:
case 1:
def = args[0]
default:
log.Panicf("MustArray() received too many arguments %d", len(args))
}
a, err := j.Array()
if err == nil {
return a
}
return def
}
// MustMap guarantees the return of a `map[string]interface{}` (with optional default)
//
// useful when you want to interate over map values in a succinct manner:
// for k, v := range js.Get("dictionary").MustMap() {
// fmt.Println(k, v)
// }
func (j *Json) MustMap(args ...map[string]interface{}) map[string]interface{} {
var def map[string]interface{}
switch len(args) {
case 0:
case 1:
def = args[0]
default:
log.Panicf("MustMap() received too many arguments %d", len(args))
}
a, err := j.Map()
if err == nil {
return a
}
return def
}
// MustString guarantees the return of a `string` (with optional default)
//
// useful when you explicitly want a `string` in a single value return context:
// myFunc(js.Get("param1").MustString(), js.Get("optional_param").MustString("my_default"))
func (j *Json) MustString(args ...string) string {
var def string
switch len(args) {
case 0:
case 1:
def = args[0]
default:
log.Panicf("MustString() received too many arguments %d", len(args))
}
s, err := j.String()
if err == nil {
return s
}
return def
}
// MustStringArray guarantees the return of a `[]string` (with optional default)
//
// useful when you want to interate over array values in a succinct manner:
// for i, s := range js.Get("results").MustStringArray() {
// fmt.Println(i, s)
// }
func (j *Json) MustStringArray(args ...[]string) []string {
var def []string
switch len(args) {
case 0:
case 1:
def = args[0]
default:
log.Panicf("MustStringArray() received too many arguments %d", len(args))
}
a, err := j.StringArray()
if err == nil {
return a
}
return def
}
// MustInt guarantees the return of an `int` (with optional default)
//
// useful when you explicitly want an `int` in a single value return context:
// myFunc(js.Get("param1").MustInt(), js.Get("optional_param").MustInt(5150))
func (j *Json) MustInt(args ...int) int {
var def int
switch len(args) {
case 0:
case 1:
def = args[0]
default:
log.Panicf("MustInt() received too many arguments %d", len(args))
}
i, err := j.Int()
if err == nil {
return i
}
return def
}
// MustFloat64 guarantees the return of a `float64` (with optional default)
//
// useful when you explicitly want a `float64` in a single value return context:
// myFunc(js.Get("param1").MustFloat64(), js.Get("optional_param").MustFloat64(5.150))
func (j *Json) MustFloat64(args ...float64) float64 {
var def float64
switch len(args) {
case 0:
case 1:
def = args[0]
default:
log.Panicf("MustFloat64() received too many arguments %d", len(args))
}
f, err := j.Float64()
if err == nil {
return f
}
return def
}
// MustBool guarantees the return of a `bool` (with optional default)
//
// useful when you explicitly want a `bool` in a single value return context:
// myFunc(js.Get("param1").MustBool(), js.Get("optional_param").MustBool(true))
func (j *Json) MustBool(args ...bool) bool {
var def bool
switch len(args) {
case 0:
case 1:
def = args[0]
default:
log.Panicf("MustBool() received too many arguments %d", len(args))
}
b, err := j.Bool()
if err == nil {
return b
}
return def
}
// MustInt64 guarantees the return of an `int64` (with optional default)
//
// useful when you explicitly want an `int64` in a single value return context:
// myFunc(js.Get("param1").MustInt64(), js.Get("optional_param").MustInt64(5150))
func (j *Json) MustInt64(args ...int64) int64 {
var def int64
switch len(args) {
case 0:
case 1:
def = args[0]
default:
log.Panicf("MustInt64() received too many arguments %d", len(args))
}
i, err := j.Int64()
if err == nil {
return i
}
return def
}
// MustUInt64 guarantees the return of an `uint64` (with optional default)
//
// useful when you explicitly want an `uint64` in a single value return context:
// myFunc(js.Get("param1").MustUint64(), js.Get("optional_param").MustUint64(5150))
func (j *Json) MustUint64(args ...uint64) uint64 {
var def uint64
switch len(args) {
case 0:
case 1:
def = args[0]
default:
log.Panicf("MustUint64() received too many arguments %d", len(args))
}
i, err := j.Uint64()
if err == nil {
return i
}
return def
}
-75
View File
@@ -1,75 +0,0 @@
// +build !go1.1
package simplejson
import (
"encoding/json"
"errors"
"io"
"reflect"
)
// NewFromReader returns a *Json by decoding from an io.Reader
func NewFromReader(r io.Reader) (*Json, error) {
j := new(Json)
dec := json.NewDecoder(r)
err := dec.Decode(&j.data)
return j, err
}
// Implements the json.Unmarshaler interface.
func (j *Json) UnmarshalJSON(p []byte) error {
return json.Unmarshal(p, &j.data)
}
// Float64 coerces into a float64
func (j *Json) Float64() (float64, error) {
switch j.data.(type) {
case float32, float64:
return reflect.ValueOf(j.data).Float(), nil
case int, int8, int16, int32, int64:
return float64(reflect.ValueOf(j.data).Int()), nil
case uint, uint8, uint16, uint32, uint64:
return float64(reflect.ValueOf(j.data).Uint()), nil
}
return 0, errors.New("invalid value type")
}
// Int coerces into an int
func (j *Json) Int() (int, error) {
switch j.data.(type) {
case float32, float64:
return int(reflect.ValueOf(j.data).Float()), nil
case int, int8, int16, int32, int64:
return int(reflect.ValueOf(j.data).Int()), nil
case uint, uint8, uint16, uint32, uint64:
return int(reflect.ValueOf(j.data).Uint()), nil
}
return 0, errors.New("invalid value type")
}
// Int64 coerces into an int64
func (j *Json) Int64() (int64, error) {
switch j.data.(type) {
case float32, float64:
return int64(reflect.ValueOf(j.data).Float()), nil
case int, int8, int16, int32, int64:
return reflect.ValueOf(j.data).Int(), nil
case uint, uint8, uint16, uint32, uint64:
return int64(reflect.ValueOf(j.data).Uint()), nil
}
return 0, errors.New("invalid value type")
}
// Uint64 coerces into an uint64
func (j *Json) Uint64() (uint64, error) {
switch j.data.(type) {
case float32, float64:
return uint64(reflect.ValueOf(j.data).Float()), nil
case int, int8, int16, int32, int64:
return uint64(reflect.ValueOf(j.data).Int()), nil
case uint, uint8, uint16, uint32, uint64:
return reflect.ValueOf(j.data).Uint(), nil
}
return 0, errors.New("invalid value type")
}
-89
View File
@@ -1,89 +0,0 @@
// +build go1.1
package simplejson
import (
"bytes"
"encoding/json"
"errors"
"io"
"reflect"
"strconv"
)
// Implements the json.Unmarshaler interface.
func (j *Json) UnmarshalJSON(p []byte) error {
dec := json.NewDecoder(bytes.NewBuffer(p))
dec.UseNumber()
return dec.Decode(&j.data)
}
// NewFromReader returns a *Json by decoding from an io.Reader
func NewFromReader(r io.Reader) (*Json, error) {
j := new(Json)
dec := json.NewDecoder(r)
dec.UseNumber()
err := dec.Decode(&j.data)
return j, err
}
// Float64 coerces into a float64
func (j *Json) Float64() (float64, error) {
switch j.data.(type) {
case json.Number:
return j.data.(json.Number).Float64()
case float32, float64:
return reflect.ValueOf(j.data).Float(), nil
case int, int8, int16, int32, int64:
return float64(reflect.ValueOf(j.data).Int()), nil
case uint, uint8, uint16, uint32, uint64:
return float64(reflect.ValueOf(j.data).Uint()), nil
}
return 0, errors.New("invalid value type")
}
// Int coerces into an int
func (j *Json) Int() (int, error) {
switch j.data.(type) {
case json.Number:
i, err := j.data.(json.Number).Int64()
return int(i), err
case float32, float64:
return int(reflect.ValueOf(j.data).Float()), nil
case int, int8, int16, int32, int64:
return int(reflect.ValueOf(j.data).Int()), nil
case uint, uint8, uint16, uint32, uint64:
return int(reflect.ValueOf(j.data).Uint()), nil
}
return 0, errors.New("invalid value type")
}
// Int64 coerces into an int64
func (j *Json) Int64() (int64, error) {
switch j.data.(type) {
case json.Number:
return j.data.(json.Number).Int64()
case float32, float64:
return int64(reflect.ValueOf(j.data).Float()), nil
case int, int8, int16, int32, int64:
return reflect.ValueOf(j.data).Int(), nil
case uint, uint8, uint16, uint32, uint64:
return int64(reflect.ValueOf(j.data).Uint()), nil
}
return 0, errors.New("invalid value type")
}
// Uint64 coerces into an uint64
func (j *Json) Uint64() (uint64, error) {
switch j.data.(type) {
case json.Number:
return strconv.ParseUint(j.data.(json.Number).String(), 10, 64)
case float32, float64:
return uint64(reflect.ValueOf(j.data).Float()), nil
case int, int8, int16, int32, int64:
return uint64(reflect.ValueOf(j.data).Int()), nil
case uint, uint8, uint16, uint32, uint64:
return reflect.ValueOf(j.data).Uint(), nil
}
return 0, errors.New("invalid value type")
}
+10 -6
View File
@@ -3,9 +3,13 @@ language: go
go_import_path: go.uber.org/atomic
go:
- 1.7
- 1.8
- 1.9
- 1.11.x
- 1.12.x
matrix:
include:
- go: 1.12.x
env: NO_TEST=yes LINT=yes
cache:
directories:
@@ -15,9 +19,9 @@ install:
- make install_ci
script:
- make test_ci
- scripts/test-ubergo.sh
- make lint
- test -n "$NO_TEST" || make test_ci
- test -n "$NO_TEST" || scripts/test-ubergo.sh
- test -z "$LINT" || make install_lint lint
after_success:
- bash <(curl -s https://codecov.io/bash)
+10 -23
View File
@@ -1,24 +1,13 @@
PACKAGES := $(shell glide nv)
# Many Go tools take file globs or directories as arguments instead of packages.
PACKAGE_FILES ?= *.go
# The linting tools evolve with each Go version, so run them only on the latest
# stable release.
GO_VERSION := $(shell go version | cut -d " " -f 3)
GO_MINOR_VERSION := $(word 2,$(subst ., ,$(GO_VERSION)))
LINTABLE_MINOR_VERSIONS := 7 8
ifneq ($(filter $(LINTABLE_MINOR_VERSIONS),$(GO_MINOR_VERSION)),)
SHOULD_LINT := true
endif
# For pre go1.6
export GO15VENDOREXPERIMENT=1
.PHONY: build
build:
go build -i $(PACKAGES)
go build -i ./...
.PHONY: install
@@ -29,7 +18,7 @@ install:
.PHONY: test
test:
go test -cover -race $(PACKAGES)
go test -cover -race ./...
.PHONY: install_ci
@@ -37,26 +26,24 @@ install_ci: install
go get github.com/wadey/gocovmerge
go get github.com/mattn/goveralls
go get golang.org/x/tools/cmd/cover
ifdef SHOULD_LINT
go get github.com/golang/lint/golint
endif
.PHONY: install_lint
install_lint:
go get golang.org/x/lint/golint
.PHONY: lint
lint:
ifdef SHOULD_LINT
@rm -rf lint.log
@echo "Checking formatting..."
@gofmt -d -s $(PACKAGE_FILES) 2>&1 | tee lint.log
@echo "Checking vet..."
@$(foreach dir,$(PACKAGE_FILES),go tool vet $(dir) 2>&1 | tee -a lint.log;)
@go vet ./... 2>&1 | tee -a lint.log;)
@echo "Checking lint..."
@$(foreach dir,$(PKGS),golint $(dir) 2>&1 | tee -a lint.log;)
@golint $$(go list ./...) 2>&1 | tee -a lint.log
@echo "Checking for unresolved FIXMEs..."
@git grep -i fixme | grep -v -e vendor -e Makefile | tee -a lint.log
@[ ! -s lint.log ]
else
@echo "Skipping linters on" $(GO_VERSION)
endif
.PHONY: test_ci
+3 -3
View File
@@ -23,13 +23,13 @@ See the [documentation][doc] for a complete API specification.
## Development Status
Stable.
<hr>
___
Released under the [MIT License](LICENSE.txt).
[doc-img]: https://godoc.org/github.com/uber-go/atomic?status.svg
[doc]: https://godoc.org/go.uber.org/atomic
[ci-img]: https://travis-ci.org/uber-go/atomic.svg?branch=master
[ci]: https://travis-ci.org/uber-go/atomic
[ci-img]: https://travis-ci.com/uber-go/atomic.svg?branch=master
[ci]: https://travis-ci.com/uber-go/atomic
[cov-img]: https://codecov.io/gh/uber-go/atomic/branch/master/graph/badge.svg
[cov]: https://codecov.io/gh/uber-go/atomic
[reportcard-img]: https://goreportcard.com/badge/go.uber.org/atomic
+55
View File
@@ -0,0 +1,55 @@
// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
// Error is an atomic type-safe wrapper around Value for errors
type Error struct{ v Value }
// errorHolder is non-nil holder for error object.
// atomic.Value panics on saving nil object, so err object needs to be
// wrapped with valid object first.
type errorHolder struct{ err error }
// NewError creates new atomic error object
func NewError(err error) *Error {
e := &Error{}
if err != nil {
e.Store(err)
}
return e
}
// Load atomically loads the wrapped error
func (e *Error) Load() error {
v := e.v.Load()
if v == nil {
return nil
}
eh := v.(errorHolder)
return eh.err
}
// Store atomically stores error.
// NOTE: a holder object is allocated on each Store call.
func (e *Error) Store(err error) {
e.v.Store(errorHolder{err: err})
}
+2 -2
View File
@@ -1,8 +1,8 @@
language: go
sudo: false
go:
- 1.9.x
- 1.10.x
- 1.11.x
- 1.12.x
go_import_path: go.uber.org/zap
env:
global:
+22
View File
@@ -1,5 +1,22 @@
# Changelog
## 1.10.0 (29 Apr 2019)
Bugfixes:
* [#657][]: Fix `MapObjectEncoder.AppendByteString` not adding value as a
string.
* [#706][]: Fix incorrect call depth to determine caller in Go 1.12.
Enhancements:
* [#610][]: Add `zaptest.WrapOptions` to wrap `zap.Option` for creating test
loggers.
* [#675][]: Don't panic when encoding a String field.
* [#704][]: Disable HTML escaping for JSON objects encoded using the
reflect-based encoder.
Thanks to @iaroslav-ciupin, @lelenanam, @joa, @NWilson for their contributions
to this release.
## v1.9.1 (06 Aug 2018)
Bugfixes:
@@ -303,3 +320,8 @@ upgrade to the upcoming stable release.
[#572]: https://github.com/uber-go/zap/pull/572
[#606]: https://github.com/uber-go/zap/pull/606
[#614]: https://github.com/uber-go/zap/pull/614
[#657]: https://github.com/uber-go/zap/pull/657
[#706]: https://github.com/uber-go/zap/pull/706
[#610]: https://github.com/uber-go/zap/pull/610
[#675]: https://github.com/uber-go/zap/pull/675
[#704]: https://github.com/uber-go/zap/pull/704
+2 -2
View File
@@ -9,7 +9,7 @@ PKG_FILES ?= *.go zapcore benchmarks buffer zapgrpc zaptest zaptest/observer int
# stable release.
GO_VERSION := $(shell go version | cut -d " " -f 3)
GO_MINOR_VERSION := $(word 2,$(subst ., ,$(GO_VERSION)))
LINTABLE_MINOR_VERSIONS := 10
LINTABLE_MINOR_VERSIONS := 12
ifneq ($(filter $(LINTABLE_MINOR_VERSIONS),$(GO_MINOR_VERSION)),)
SHOULD_LINT := true
endif
@@ -45,7 +45,7 @@ ifdef SHOULD_LINT
@echo "Installing test dependencies for vet..."
@go test -i $(PKGS)
@echo "Checking vet..."
@$(foreach dir,$(PKG_FILES),go tool vet $(VET_RULES) $(dir) 2>&1 | tee -a lint.log;)
@go vet $(VET_RULES) $(PKGS) 2>&1 | tee -a lint.log
@echo "Checking lint..."
@$(foreach dir,$(PKGS),golint $(dir) 2>&1 | tee -a lint.log;)
@echo "Checking for unresolved FIXMEs..."
-1
View File
@@ -31,7 +31,6 @@ import (
)
const (
_stdLogDefaultDepth = 2
_loggerWriterDepth = 2
_programmerErrorTemplate = "You've found a bug in zap! Please file a bug at " +
"https://github.com/uber-go/zap/issues/new and reference this error: %v"
+26
View File
@@ -0,0 +1,26 @@
// Copyright (c) 2019 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// See #682 for more information.
// +build go1.12
package zap
const _stdLogDefaultDepth = 1
+26
View File
@@ -0,0 +1,26 @@
// Copyright (c) 2019 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// See #682 for more information.
// +build !go1.12
package zap
const _stdLogDefaultDepth = 2
+12 -1
View File
@@ -160,7 +160,7 @@ func (f Field) AddTo(enc ObjectEncoder) {
case NamespaceType:
enc.OpenNamespace(f.Key)
case StringerType:
enc.AddString(f.Key, f.Interface.(fmt.Stringer).String())
err = encodeStringer(f.Key, f.Interface, enc)
case ErrorType:
encodeError(f.Key, f.Interface.(error), enc)
case SkipType:
@@ -199,3 +199,14 @@ func addFields(enc ObjectEncoder, fields []Field) {
fields[i].AddTo(enc)
}
}
func encodeStringer(key string, stringer interface{}, enc ObjectEncoder) (err error) {
defer func() {
if v := recover(); v != nil {
err = fmt.Errorf("PANIC=%v", v)
}
}()
enc.AddString(key, stringer.(fmt.Stringer).String())
return
}
+3
View File
@@ -137,6 +137,9 @@ func (enc *jsonEncoder) resetReflectBuf() {
if enc.reflectBuf == nil {
enc.reflectBuf = bufferpool.Get()
enc.reflectEnc = json.NewEncoder(enc.reflectBuf)
// For consistency with our custom JSON encoder.
enc.reflectEnc.SetEscapeHTML(false)
} else {
enc.reflectBuf.Reset()
}
+1 -1
View File
@@ -158,7 +158,7 @@ func (s *sliceArrayEncoder) AppendReflected(v interface{}) error {
}
func (s *sliceArrayEncoder) AppendBool(v bool) { s.elems = append(s.elems, v) }
func (s *sliceArrayEncoder) AppendByteString(v []byte) { s.elems = append(s.elems, v) }
func (s *sliceArrayEncoder) AppendByteString(v []byte) { s.elems = append(s.elems, string(v)) }
func (s *sliceArrayEncoder) AppendComplex128(v complex128) { s.elems = append(s.elems, v) }
func (s *sliceArrayEncoder) AppendComplex64(v complex64) { s.elems = append(s.elems, v) }
func (s *sliceArrayEncoder) AppendDuration(v time.Duration) { s.elems = append(s.elems, v) }
+2 -4
View File
@@ -4,8 +4,6 @@ github.com/DataDog/zstd
github.com/Shopify/sarama
# github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705
github.com/StackExchange/wmi
# github.com/bitly/go-simplejson v0.5.0
github.com/bitly/go-simplejson
# github.com/davecgh/go-spew v1.1.1
github.com/davecgh/go-spew/spew
# github.com/eapache/go-resiliency v1.1.0
@@ -74,11 +72,11 @@ github.com/tidwall/match
github.com/tidwall/pretty
# github.com/ugorji/go v1.1.4
github.com/ugorji/go/codec
# go.uber.org/atomic v1.3.2
# go.uber.org/atomic v1.4.0
go.uber.org/atomic
# go.uber.org/multierr v1.1.0
go.uber.org/multierr
# go.uber.org/zap v1.9.1
# go.uber.org/zap v1.10.0
go.uber.org/zap
go.uber.org/zap/internal/bufferpool
go.uber.org/zap/zapcore