mirror of
https://github.com/fhmq/hmq.git
synced 2026-08-29 22:13:11 +00:00
upate plugin logic
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -15,8 +15,8 @@
|
||||
"certFile": "ssl/server/cert.pem",
|
||||
"keyFile": "ssl/server/key.pem"
|
||||
},
|
||||
"plugins": [
|
||||
"authhttp",
|
||||
"kafka"
|
||||
]
|
||||
"plugins": {
|
||||
"auth": "authhttp",
|
||||
"bridge": "kafka"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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),
|
||||
@@ -0,0 +1,7 @@
|
||||
package bridge
|
||||
|
||||
type mockMQ struct{}
|
||||
|
||||
func (m *mockMQ) Publish(e *Elements) error {
|
||||
return nil
|
||||
}
|
||||
-10
@@ -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
@@ -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
@@ -1,13 +0,0 @@
|
||||
### go-simplejson
|
||||
|
||||
a Go package to interact with arbitrary JSON
|
||||
|
||||
[](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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) }
|
||||
|
||||
Vendored
+2
-4
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user