Compare commits
9 Commits
feat/input
...
v0.2.0
Author | SHA1 | Date | |
---|---|---|---|
8234a0cefa | |||
f1566b8e4a | |||
71c93f2e73 | |||
fdedd70471 | |||
0fe45a3c9c | |||
3d81336c9b | |||
d0c8ef76fc | |||
5a99160f65 | |||
c2f3756cef |
1
.gitignore
vendored
1
.gitignore
vendored
@ -284,3 +284,4 @@ local.properties
|
||||
|
||||
./rc-*
|
||||
rc-simulator
|
||||
rc-simulator.*
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM --platform=$BUILDPLATFORM golang:alpine AS builder
|
||||
FROM --platform=$BUILDPLATFORM golang:1.17-alpine AS builder
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
ARG BUILDPLATFORM
|
||||
|
@ -9,7 +9,7 @@ Usage of ./rc-simulator:
|
||||
-debug
|
||||
Debug logs
|
||||
-events-topic-frame string
|
||||
Mqtt topic to events gateway frames, use MQTT_TOPIC_FRAME if args not set
|
||||
Mqtt topic to events gateway frames, use MQTT_TOPIC_CAMERA if args not set
|
||||
-events-topic-steering string
|
||||
Mqtt topic to events gateway steering, use MQTT_TOPIC_STEERING if args not set
|
||||
-events-topic-throttle string
|
||||
|
49
build-docker.sh
Executable file
49
build-docker.sh
Executable file
@ -0,0 +1,49 @@
|
||||
#! /bin/bash
|
||||
|
||||
IMAGE_NAME=robocar-simulator
|
||||
TAG=$(git describe)
|
||||
FULL_IMAGE_NAME=docker.io/cyrilix/${IMAGE_NAME}:${TAG}
|
||||
BINARY=rc-simulator
|
||||
|
||||
GOTAGS="-tags netgo"
|
||||
|
||||
image_build(){
|
||||
local platform=$1
|
||||
|
||||
|
||||
GOOS=$(echo $platform | cut -f1 -d/) && \
|
||||
GOARCH=$(echo $platform | cut -f2 -d/) && \
|
||||
GOARM=$(echo $platform | cut -f3 -d/ | sed "s/v//" )
|
||||
VARIANT="--variant $(echo $platform | cut -f3 -d/ )"
|
||||
if [[ -z "$GOARM" ]] ;
|
||||
then
|
||||
VARIANT=""
|
||||
fi
|
||||
|
||||
local binary_suffix="$GOARCH$(echo $platform | cut -f3 -d/ )"
|
||||
|
||||
local containerName="$IMAGE_NAME-$GOARCH$GOARM"
|
||||
|
||||
|
||||
printf "\n\nBuild go binary %s\n\n" "${BINARY}.${binary_suffix}"
|
||||
CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} GOARM=${GOARM} go build -mod vendor -a ${GOTAGS} -o "${BINARY}.${binary_suffix}" ./cmd/${BINARY}/
|
||||
|
||||
buildah --os "$GOOS" --arch "$GOARCH" $VARIANT --name "$containerName" from gcr.io/distroless/static
|
||||
buildah config --user 1234 "$containerName"
|
||||
buildah copy "$containerName" "${BINARY}.${binary_suffix}" /go/bin/$BINARY
|
||||
buildah config --entrypoint '["/go/bin/'$BINARY'"]' "${containerName}"
|
||||
|
||||
buildah commit --rm --manifest $IMAGE_NAME "${containerName}" "${containerName}"
|
||||
}
|
||||
|
||||
buildah rmi localhost/$IMAGE_NAME
|
||||
buildah manifest rm localhost/${IMAGE_NAME}
|
||||
|
||||
image_build linux/amd64
|
||||
image_build linux/arm64
|
||||
image_build linux/arm/v7
|
||||
|
||||
|
||||
# push image
|
||||
printf "\n\nPush manifest to %s\n\n" ${FULL_IMAGE_NAME}
|
||||
buildah manifest push --rm -f v2s2 "localhost/$IMAGE_NAME" "docker://$FULL_IMAGE_NAME" --all
|
@ -2,14 +2,19 @@ package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/cyrilix/robocar-base/cli"
|
||||
events2 "github.com/cyrilix/robocar-protobuf/go/events"
|
||||
"github.com/cyrilix/robocar-simulator/pkg/events"
|
||||
"github.com/cyrilix/robocar-simulator/pkg/gateway"
|
||||
"github.com/cyrilix/robocar-simulator/pkg/simulator"
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
"github.com/golang/protobuf/proto"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.uber.org/zap"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const DefaultClientId = "robocar-simulator"
|
||||
@ -25,30 +30,110 @@ func main() {
|
||||
|
||||
cli.InitMqttFlags(DefaultClientId, &mqttBroker, &username, &password, &clientId, &mqttQos, &mqttRetain)
|
||||
|
||||
flag.StringVar(&topicFrame, "events-topic-frame", os.Getenv("MQTT_TOPIC_FRAME"), "Mqtt topic to events gateway frames, use MQTT_TOPIC_FRAME if args not set")
|
||||
flag.StringVar(&topicFrame, "events-topic-steering", os.Getenv("MQTT_TOPIC_STEERING"), "Mqtt topic to events gateway steering, use MQTT_TOPIC_STEERING if args not set")
|
||||
flag.StringVar(&topicFrame, "events-topic-throttle", os.Getenv("MQTT_TOPIC_THROTTLE"), "Mqtt topic to events gateway throttle, use MQTT_TOPIC_THROTTLE if args not set")
|
||||
flag.StringVar(&topicFrame, "topic-steering-ctrl", os.Getenv("MQTT_TOPIC_STEERING_CTRL"), "Mqtt topic to send steering instructions, use MQTT_TOPIC_STEERING_CTRL if args not set")
|
||||
flag.StringVar(&topicFrame, "topic-throttle-ctrl", os.Getenv("MQTT_TOPIC_THROTTLE_CTRL"), "Mqtt topic to send throttle instructions, use MQTT_TOPIC_THROTTLE_CTRL if args not set")
|
||||
flag.StringVar(&topicFrame, "events-topic-camera", os.Getenv("MQTT_TOPIC_CAMERA"), "Mqtt topic to events gateway frames, use MQTT_TOPIC_CAMERA if args not set")
|
||||
flag.StringVar(&topicSteering, "events-topic-steering", os.Getenv("MQTT_TOPIC_STEERING"), "Mqtt topic to events gateway steering, use MQTT_TOPIC_STEERING if args not set")
|
||||
flag.StringVar(&topicThrottle, "events-topic-throttle", os.Getenv("MQTT_TOPIC_THROTTLE"), "Mqtt topic to events gateway throttle, use MQTT_TOPIC_THROTTLE if args not set")
|
||||
flag.StringVar(&topicCtrlSteering, "topic-steering-ctrl", os.Getenv("MQTT_TOPIC_STEERING_CTRL"), "Mqtt topic to send steering instructions, use MQTT_TOPIC_STEERING_CTRL if args not set")
|
||||
flag.StringVar(&topicCtrlThrottle, "topic-throttle-ctrl", os.Getenv("MQTT_TOPIC_THROTTLE_CTRL"), "Mqtt topic to send throttle instructions, use MQTT_TOPIC_THROTTLE_CTRL if args not set")
|
||||
flag.StringVar(&address, "simulator-address", "127.0.0.1:9091", "Simulator address")
|
||||
flag.BoolVar(&debug, "debug", false, "Debug logs")
|
||||
|
||||
var carName, carStyle, carColor string
|
||||
var carFontSize int
|
||||
carStyles := []string{
|
||||
string(simulator.CarConfigBodyStyleDonkey),
|
||||
string(simulator.CarConfigBodyStyleBare),
|
||||
string(simulator.CarConfigBodyStyleCar01),
|
||||
}
|
||||
flag.StringVar(&carName, "car-name", "simulator-gateway", "Car name to display")
|
||||
flag.StringVar(&carStyle, "car-style", string(simulator.CarConfigBodyStyleDonkey), fmt.Sprintf("Car style, only %s", strings.Join(carStyles, ",")))
|
||||
flag.StringVar(&carColor, "car-color", "0,0,0", "Color car as rgb value")
|
||||
flag.IntVar(&carFontSize, "car-font-size", 0, "Car font size")
|
||||
|
||||
var racerName, racerBio, racerCountry, racerGuid string
|
||||
flag.StringVar(&racerName, "racer-name", "", "")
|
||||
flag.StringVar(&racerBio, "racer-bio", "", "")
|
||||
flag.StringVar(&racerCountry, "racer-country", "", "")
|
||||
flag.StringVar(&racerGuid, "racer-guid", "", "")
|
||||
|
||||
var cameraFov, cameraImgW, cameraImgH, cameraImgD int
|
||||
var cameraFishEyeX, cameraFishEyeY float64
|
||||
var cameraOffsetX, cameraOffsetY, cameraOffsetZ, cameraRotX float64
|
||||
var cameraImgEnc string
|
||||
flag.IntVar(&cameraFov, "camera-fov", 90, "")
|
||||
flag.Float64Var(&cameraFishEyeX, "camera-fish-eye-x", 0.4, "")
|
||||
flag.Float64Var(&cameraFishEyeY, "camera-fish-eye-y", 0.7, "")
|
||||
flag.IntVar(&cameraImgW, "camera-img-w", 160, "image width")
|
||||
flag.IntVar(&cameraImgH, "camera-img-h", 128, "image height")
|
||||
flag.IntVar(&cameraImgD, "camera-img-d", 3, "Image depth")
|
||||
flag.StringVar(&cameraImgEnc, "camera-img-enc", string(simulator.CameraImageEncJpeg), "")
|
||||
flag.Float64Var(&cameraOffsetX, "camera-offset-x", 0, "moves camera left/right")
|
||||
flag.Float64Var(&cameraOffsetY, "camera-offset-y", 1.120395, "moves camera up/down")
|
||||
flag.Float64Var(&cameraOffsetZ, "camera-offset-z", 0.5528488, "moves camera forward/back")
|
||||
flag.Float64Var(&cameraRotX, "camera-rot-x", 15.0, "rotate the camera")
|
||||
|
||||
flag.Parse()
|
||||
if len(os.Args) <= 1 {
|
||||
flag.PrintDefaults()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
config := zap.NewDevelopmentConfig()
|
||||
if debug {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
config.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
|
||||
} else {
|
||||
config.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
|
||||
}
|
||||
lgr, err := config.Build()
|
||||
if err != nil {
|
||||
log.Fatalf("unable to init logger: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := lgr.Sync(); err != nil {
|
||||
log.Printf("unable to Sync logger: %v\n", err)
|
||||
}
|
||||
}()
|
||||
zap.ReplaceGlobals(lgr)
|
||||
|
||||
client, err := cli.Connect(mqttBroker, username, password, clientId)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to connect to events broker: %v", err)
|
||||
zap.S().Fatalf("unable to connect to events broker: %v", err)
|
||||
}
|
||||
defer client.Disconnect(10)
|
||||
|
||||
gtw := gateway.New(address)
|
||||
bodyColors := strings.Split(carColor, ",")
|
||||
carConfig := simulator.CarConfigMsg{
|
||||
MsgType: simulator.MsgTypeCarConfig,
|
||||
BodyStyle: simulator.CarStyle(carStyle),
|
||||
BodyR: bodyColors[0],
|
||||
BodyG: bodyColors[1],
|
||||
BodyB: bodyColors[2],
|
||||
CarName: carName,
|
||||
FontSize: strconv.Itoa(carFontSize),
|
||||
}
|
||||
racer := simulator.RacerBioMsg{
|
||||
MsgType: simulator.MsgTypeRacerInfo,
|
||||
RacerName: racerName,
|
||||
CarName: carName,
|
||||
Bio: racerBio,
|
||||
Country: racerCountry,
|
||||
Guid: racerGuid,
|
||||
}
|
||||
camera := simulator.CamConfigMsg{
|
||||
MsgType: simulator.MsgTypeCameraConfig,
|
||||
Fov: strconv.Itoa(cameraFov),
|
||||
FishEyeX: fmt.Sprintf("%.2f", cameraFishEyeX),
|
||||
FishEyeY: fmt.Sprintf("%.2f",cameraFishEyeY),
|
||||
ImgW: strconv.Itoa(cameraImgW),
|
||||
ImgH: strconv.Itoa(cameraImgH),
|
||||
ImgD: strconv.Itoa(cameraImgD),
|
||||
ImgEnc: simulator.CameraImageEnc(cameraImgEnc),
|
||||
OffsetX: fmt.Sprintf("%.2f",cameraOffsetX),
|
||||
OffsetY: fmt.Sprintf("%.2f", cameraOffsetY),
|
||||
OffsetZ: fmt.Sprintf("%.2f", cameraOffsetZ),
|
||||
RotX: fmt.Sprintf("%.2f", cameraRotX),
|
||||
}
|
||||
gtw := gateway.New(address, &carConfig, &racer, &camera)
|
||||
defer gtw.Stop()
|
||||
|
||||
msgPub := events.NewMsgPublisher(
|
||||
@ -59,45 +144,46 @@ func main() {
|
||||
topicThrottle,
|
||||
)
|
||||
defer msgPub.Stop()
|
||||
msgPub.Start()
|
||||
|
||||
cli.HandleExit(gtw)
|
||||
|
||||
err = gtw.Start()
|
||||
if err != nil {
|
||||
log.Fatalf("unable to start service: %v", err)
|
||||
}
|
||||
msgPub.Start()
|
||||
|
||||
if topicCtrlSteering != "" {
|
||||
log.Infof("configure mqtt route on steering command")
|
||||
client.AddRoute(topicCtrlSteering, func(client mqtt.Client, message mqtt.Message) {
|
||||
zap.S().Info("configure mqtt route on steering command")
|
||||
client.Subscribe(topicCtrlSteering, byte(mqttQos), func(client mqtt.Client, message mqtt.Message) {
|
||||
onSteeringCommand(gtw, message)
|
||||
})
|
||||
}
|
||||
if topicCtrlThrottle != "" {
|
||||
log.Infof("configure mqtt route on throttle command")
|
||||
client.AddRoute(topicCtrlThrottle, func(client mqtt.Client, message mqtt.Message) {
|
||||
zap.S().Info("configure mqtt route on throttle command")
|
||||
client.Subscribe(topicCtrlThrottle, byte(mqttQos), func(client mqtt.Client, message mqtt.Message) {
|
||||
onThrottleCommand(gtw, message)
|
||||
})
|
||||
}
|
||||
|
||||
err = gtw.Start()
|
||||
if err != nil {
|
||||
zap.S().Fatalf("unable to start service: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func onSteeringCommand(c *gateway.Gateway, message mqtt.Message) {
|
||||
var steeringMsg *events2.SteeringMessage
|
||||
err := proto.Unmarshal(message.Payload(), steeringMsg)
|
||||
var steeringMsg events2.SteeringMessage
|
||||
err := proto.Unmarshal(message.Payload(), &steeringMsg)
|
||||
if err != nil {
|
||||
log.Errorf("unable to unmarshal steering msg: %v", err)
|
||||
zap.S().Errorf("unable to unmarshal steering msg: %v", err)
|
||||
return
|
||||
}
|
||||
c.WriteSteering(steeringMsg)
|
||||
c.WriteSteering(&steeringMsg)
|
||||
}
|
||||
|
||||
func onThrottleCommand(c *gateway.Gateway, message mqtt.Message) {
|
||||
var throttleMsg *events2.ThrottleMessage
|
||||
err := proto.Unmarshal(message.Payload(), throttleMsg)
|
||||
var throttleMsg events2.ThrottleMessage
|
||||
err := proto.Unmarshal(message.Payload(), &throttleMsg)
|
||||
if err != nil {
|
||||
log.Errorf("unable to unmarshal throttle msg: %v", err)
|
||||
zap.S().Errorf("unable to unmarshal throttle msg: %v", err)
|
||||
return
|
||||
}
|
||||
c.WriteThrottle(throttleMsg)
|
||||
c.WriteThrottle(&throttleMsg)
|
||||
}
|
||||
|
24
go.mod
24
go.mod
@ -1,12 +1,22 @@
|
||||
module github.com/cyrilix/robocar-simulator
|
||||
|
||||
go 1.15
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/avast/retry-go v2.6.0+incompatible
|
||||
github.com/cyrilix/robocar-base v0.1.2
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.2
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.1
|
||||
github.com/golang/protobuf v1.4.3
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/avast/retry-go v3.0.0+incompatible
|
||||
github.com/cyrilix/robocar-base v0.1.4
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.3
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.5
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
go.uber.org/zap v1.19.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
)
|
||||
|
51
go.sum
51
go.sum
@ -4,14 +4,21 @@ github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcy
|
||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||
github.com/avast/retry-go v2.6.0+incompatible h1:FelcMrm7Bxacr1/RM8+/eqkDkmVN7tjlsy51dOzB3LI=
|
||||
github.com/avast/retry-go v2.6.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
|
||||
github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
|
||||
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/cyrilix/robocar-base v0.1.2 h1:bhT5ohhviodCOd5usy013ctwu7ko+IfyDXnYHg7lJ8I=
|
||||
github.com/cyrilix/robocar-base v0.1.2/go.mod h1:G2SiYNUDAIv+65XWpiHnCXj7Jz2V6pOBLaIrcasGkww=
|
||||
github.com/cyrilix/robocar-base v0.1.4 h1:nfnjRwAcCfS7xGu6tW9rZhmc/HZIsuDJX5NFhgX5dWE=
|
||||
github.com/cyrilix/robocar-base v0.1.4/go.mod h1:Tt04UmbGBiQtU0Cn3wFD0q7XoyokTwIlWYQxThKI+04=
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.2 h1:eWwu7T07uvABh74bWOJa77alUs6VaWNEPd7Zezua2Cs=
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.2/go.mod h1:xj7H/a7qpvXgmW1983Fjd143Mz9Yt0C6RCxvB8M6pEM=
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.3 h1:iPHw2+7FVXG2C4+Th1m11hQ+2RpAQzlxKhc5M7XOa6Q=
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.3/go.mod h1:xb95cK07lYXnKcHZKnGafmAgYRrqZWZgV9LMiJAp+gE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -21,6 +28,8 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.1 h1:6F5FYb1hxVSZS+p0ji5xBQamc5ltOolTYRy5R15uVmI=
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.1/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y=
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
@ -42,11 +51,15 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
@ -74,11 +87,14 @@ github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQ
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@ -88,21 +104,40 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/testcontainers/testcontainers-go v0.9.0/go.mod h1:b22BFXhRbg4PJmeMVWh6ftqjyZHgiIl3w274e9r3C2E=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
|
||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U=
|
||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -112,14 +147,26 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180810170437-e96c4e24768d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
@ -130,6 +177,9 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@ -141,5 +191,6 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v0.0.0-20181223230014-1083505acf35/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
@ -5,9 +5,9 @@ import (
|
||||
"github.com/cyrilix/robocar-simulator/pkg/gateway"
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
"github.com/golang/protobuf/proto"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"sync"
|
||||
"time"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func NewMsgPublisher(srcEvents gateway.SimulatorSource, p Publisher, topicFrame, topicSteering, topicThrottle string) *MsgPublisher {
|
||||
@ -59,7 +59,7 @@ func (m *MsgPublisher) Stop() {
|
||||
}
|
||||
|
||||
func (m *MsgPublisher) listenThrottle() {
|
||||
logr := log.WithField("msg_type", "throttleChan")
|
||||
logr := zap.S().With("msg_type", "throttleChan")
|
||||
msgChan := m.srcEvents.SubscribeThrottle()
|
||||
for {
|
||||
select {
|
||||
@ -83,7 +83,7 @@ func (m *MsgPublisher) listenThrottle() {
|
||||
}
|
||||
|
||||
func (m *MsgPublisher) listenSteering() {
|
||||
logr := log.WithField("msg_type", "steeringChan")
|
||||
logr := zap.S().With("msg_type", "steeringChan")
|
||||
msgChan := m.srcEvents.SubscribeSteering()
|
||||
for {
|
||||
select {
|
||||
@ -107,10 +107,15 @@ func (m *MsgPublisher) listenSteering() {
|
||||
}
|
||||
|
||||
func (m *MsgPublisher) listenFrame() {
|
||||
logr := log.WithField("msg_type", "frame")
|
||||
logr := zap.S().With("msg_type", "frame")
|
||||
msgChan := m.srcEvents.SubscribeFrame()
|
||||
for {
|
||||
msg := <-msgChan
|
||||
if msg == nil {
|
||||
// channel closed
|
||||
break
|
||||
}
|
||||
logr.Debugf("new frame %v", msg.Id)
|
||||
if m.topicFrame == "" {
|
||||
return
|
||||
}
|
||||
|
@ -4,8 +4,74 @@ import (
|
||||
"github.com/cyrilix/robocar-protobuf/go/events"
|
||||
"github.com/cyrilix/robocar-simulator/pkg/simulator"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
func TestGateway_Start(t *testing.T) {
|
||||
|
||||
simulatorMock := Gw2SimMock{}
|
||||
err := simulatorMock.listen()
|
||||
if err != nil {
|
||||
t.Errorf("unable to start mock gw: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := simulatorMock.Close(); err != nil {
|
||||
t.Errorf("unable to stop simulator mock: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
carConfig := simulator.CarConfigMsg{
|
||||
MsgType: simulator.MsgTypeCarConfig,
|
||||
BodyStyle: simulator.CarConfigBodyStyleCar01,
|
||||
CarName: "car-test",
|
||||
}
|
||||
camConfig :=simulator.CamConfigMsg{
|
||||
MsgType: simulator.MsgTypeCameraConfig,
|
||||
Fov: "0",
|
||||
FishEyeX: "0",
|
||||
FishEyeY: "0",
|
||||
ImgW: "120",
|
||||
ImgH: "50",
|
||||
ImgD: "0",
|
||||
ImgEnc: simulator.CameraImageEncJpeg,
|
||||
OffsetX: "0",
|
||||
OffsetY: "0",
|
||||
OffsetZ: "0",
|
||||
RotX: "0",
|
||||
}
|
||||
gw := New(simulatorMock.Addr(),
|
||||
&carConfig,
|
||||
&simulator.RacerBioMsg{},
|
||||
&camConfig,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to init simulator gateway: %v", err)
|
||||
}
|
||||
go gw.Start()
|
||||
defer gw.Close()
|
||||
|
||||
carNotify := simulatorMock.NotifyCar()
|
||||
select {
|
||||
case <- time.Tick(500 * time.Millisecond):
|
||||
t.Errorf("a car configuration message should be send")
|
||||
case msg := <-carNotify:
|
||||
if *msg != carConfig {
|
||||
t.Errorf("[carConfig] invalid car config: %v, wants %v", &msg, carConfig)
|
||||
}
|
||||
}
|
||||
camNotify := simulatorMock.NotifyCamera()
|
||||
select {
|
||||
case <- time.Tick(500 * time.Millisecond):
|
||||
t.Errorf("a camera configuration message should be send")
|
||||
case msg := <-camNotify:
|
||||
if *msg != camConfig {
|
||||
t.Errorf("[carConfig] invalid camera config: %v, wants %v", &msg, camConfig)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGateway_WriteSteering(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
@ -18,38 +84,38 @@ func TestGateway_WriteSteering(t *testing.T) {
|
||||
&events.SteeringMessage{Steering: 0.5, Confidence: 1},
|
||||
nil,
|
||||
simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.5,
|
||||
Throttle: 0,
|
||||
Brake: 0,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.50",
|
||||
Throttle: "0.0",
|
||||
Brake: "0.0",
|
||||
}},
|
||||
{"Update steering",
|
||||
&events.SteeringMessage{Steering: -0.5, Confidence: 1},
|
||||
&simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.2,
|
||||
Throttle: 0,
|
||||
Brake: 0,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.2",
|
||||
Throttle: "0.0",
|
||||
Brake: "0.0",
|
||||
},
|
||||
simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: -0.5,
|
||||
Throttle: 0,
|
||||
Brake: 0,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "-0.50",
|
||||
Throttle: "0.0",
|
||||
Brake: "0.0",
|
||||
}},
|
||||
{"Update steering shouldn't erase throttle value",
|
||||
&events.SteeringMessage{Steering: -0.3, Confidence: 1},
|
||||
&simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.2,
|
||||
Throttle: 0.6,
|
||||
Brake: 0.1,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.2",
|
||||
Throttle: "0.6",
|
||||
Brake: "0.1",
|
||||
},
|
||||
simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: -0.3,
|
||||
Throttle: 0.6,
|
||||
Brake: 0.1,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "-0.30",
|
||||
Throttle: "0.6",
|
||||
Brake: "0.1",
|
||||
}},
|
||||
}
|
||||
|
||||
@ -64,19 +130,24 @@ func TestGateway_WriteSteering(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
|
||||
gw := New(simulatorMock.Addr())
|
||||
gw := New(simulatorMock.Addr(),
|
||||
&simulator.CarConfigMsg{MsgType: simulator.MsgTypeCarConfig},
|
||||
&simulator.RacerBioMsg{},
|
||||
&simulator.CamConfigMsg{})
|
||||
if err != nil {
|
||||
t.Fatalf("unable to init simulator gateway: %v", err)
|
||||
}
|
||||
go gw.Start()
|
||||
defer gw.Close()
|
||||
//go gw.Start()
|
||||
//defer gw.Close()
|
||||
//<- simulatorMock.NotifyCar()
|
||||
//<- simulatorMock.NotifyCamera()
|
||||
|
||||
for _, c := range cases {
|
||||
gw.lastControl = c.previousMsg
|
||||
|
||||
gw.WriteSteering(c.msg)
|
||||
|
||||
ctrlMsg := <-simulatorMock.Notify()
|
||||
ctrlMsg := <-simulatorMock.NotifyCtrl()
|
||||
if *ctrlMsg != c.expectedMsg {
|
||||
t.Errorf("[%v] bad messge received: %#v, wants %#v", c.name, ctrlMsg, c.expectedMsg)
|
||||
}
|
||||
@ -95,80 +166,80 @@ func TestGateway_WriteThrottle(t *testing.T) {
|
||||
&events.ThrottleMessage{Throttle: 0.5, Confidence: 1},
|
||||
nil,
|
||||
simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0,
|
||||
Throttle: 0.5,
|
||||
Brake: 0,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.0",
|
||||
Throttle: "0.50",
|
||||
Brake: "0.0",
|
||||
}},
|
||||
{"Update Throttle",
|
||||
&events.ThrottleMessage{Throttle: 0.6, Confidence: 1},
|
||||
&simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0,
|
||||
Throttle: 0.4,
|
||||
Brake: 0,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0",
|
||||
Throttle: "0.4",
|
||||
Brake: "0",
|
||||
},
|
||||
simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0,
|
||||
Throttle: 0.6,
|
||||
Brake: 0,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0",
|
||||
Throttle: "0.60",
|
||||
Brake: "0.0",
|
||||
}},
|
||||
{"Update steering shouldn't erase throttle value",
|
||||
&events.ThrottleMessage{Throttle: 0.3, Confidence: 1},
|
||||
&simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.2,
|
||||
Throttle: 0.6,
|
||||
Brake: 0.,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.2",
|
||||
Throttle: "0.6",
|
||||
Brake: "0.0",
|
||||
},
|
||||
simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.2,
|
||||
Throttle: 0.3,
|
||||
Brake: 0.,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.2",
|
||||
Throttle: "0.30",
|
||||
Brake: "0.0",
|
||||
}},
|
||||
{"Throttle to brake",
|
||||
&events.ThrottleMessage{Throttle: -0.7, Confidence: 1},
|
||||
&simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.2,
|
||||
Throttle: 0.6,
|
||||
Brake: 0.,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.2",
|
||||
Throttle: "0.6",
|
||||
Brake: "0.0",
|
||||
},
|
||||
simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.2,
|
||||
Throttle: 0.,
|
||||
Brake: 0.7,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.2",
|
||||
Throttle: "0.0",
|
||||
Brake: "0.70",
|
||||
}},
|
||||
{"Update brake",
|
||||
&events.ThrottleMessage{Throttle: -0.2, Confidence: 1},
|
||||
&simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.2,
|
||||
Throttle: 0.,
|
||||
Brake: 0.5,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.2",
|
||||
Throttle: "0.0",
|
||||
Brake: "0.5",
|
||||
},
|
||||
simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.2,
|
||||
Throttle: 0.,
|
||||
Brake: 0.2,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.2",
|
||||
Throttle: "0.0",
|
||||
Brake: "0.20",
|
||||
}},
|
||||
{"Brake to throttle",
|
||||
&events.ThrottleMessage{Throttle: 0.9, Confidence: 1},
|
||||
&simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.2,
|
||||
Throttle: 0.,
|
||||
Brake: 0.4,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.2",
|
||||
Throttle: "0.0",
|
||||
Brake: "0.4",
|
||||
},
|
||||
simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.2,
|
||||
Throttle: 0.9,
|
||||
Brake: 0.,
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.2",
|
||||
Throttle: "0.90",
|
||||
Brake: "0.0",
|
||||
}},
|
||||
}
|
||||
|
||||
@ -183,17 +254,21 @@ func TestGateway_WriteThrottle(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
|
||||
gw := New(simulatorMock.Addr())
|
||||
if err != nil {
|
||||
t.Fatalf("unable to init simulator gateway: %v", err)
|
||||
}
|
||||
gw := New(simulatorMock.Addr(), &simulator.CarConfigMsg{MsgType: simulator.MsgTypeCarConfig},
|
||||
&simulator.RacerBioMsg{},
|
||||
&simulator.CamConfigMsg{})
|
||||
|
||||
//go gw.Start()
|
||||
|
||||
//<- simulatorMock.NotifyCar()
|
||||
//<- simulatorMock.NotifyCamera()
|
||||
|
||||
for _, c := range cases {
|
||||
gw.lastControl = c.previousMsg
|
||||
|
||||
gw.WriteThrottle(c.msg)
|
||||
|
||||
ctrlMsg := <-simulatorMock.Notify()
|
||||
ctrlMsg := <-simulatorMock.NotifyCtrl()
|
||||
if *ctrlMsg != c.expectedMsg {
|
||||
t.Errorf("[%v] bad messge received: %#v, wants %#v", c.name, ctrlMsg, c.expectedMsg)
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"github.com/cyrilix/robocar-protobuf/go/events"
|
||||
"github.com/cyrilix/robocar-simulator/pkg/simulator"
|
||||
"github.com/golang/protobuf/ptypes/timestamp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.uber.org/zap"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
@ -31,117 +31,146 @@ type ThrottleSource interface {
|
||||
SubscribeThrottle() <-chan *events.ThrottleMessage
|
||||
}
|
||||
|
||||
func New(addressSimulator string) *Gateway {
|
||||
l := log.WithField("simulator", addressSimulator)
|
||||
func New(addressSimulator string, car *simulator.CarConfigMsg, racer *simulator.RacerBioMsg, camera *simulator.CamConfigMsg) *Gateway {
|
||||
l := zap.S().With("simulator", addressSimulator)
|
||||
l.Info("run gateway from simulator")
|
||||
|
||||
return &Gateway{
|
||||
address: addressSimulator,
|
||||
log: l,
|
||||
frameSubscribers: make(map[chan<- *events.FrameMessage]interface{}),
|
||||
steeringSubscribers: make(map[chan<- *events.SteeringMessage]interface{}),
|
||||
throttleSubscribers: make(map[chan<- *events.ThrottleMessage]interface{}),
|
||||
address: addressSimulator,
|
||||
log: l,
|
||||
frameSubscribers: make(map[chan<- *events.FrameMessage]interface{}),
|
||||
steeringSubscribers: make(map[chan<- *events.SteeringMessage]interface{}),
|
||||
throttleSubscribers: make(map[chan<- *events.ThrottleMessage]interface{}),
|
||||
telemetrySubscribers: make(map[chan *simulator.TelemetryMsg]interface{}),
|
||||
carSubscribers: make(map[chan *simulator.Msg]interface{}),
|
||||
racerSubscribers: make(map[chan *simulator.Msg]interface{}),
|
||||
cameraSubscribers: make(map[chan *simulator.Msg]interface{}),
|
||||
carConfig: car,
|
||||
racer: racer,
|
||||
cameraConfig: camera,
|
||||
}
|
||||
}
|
||||
|
||||
/* Simulator interface to events gateway frames into events topicFrame */
|
||||
// Gateway is Simulator interface to events gateway frames into events topicFrame
|
||||
type Gateway struct {
|
||||
cancel chan interface{}
|
||||
|
||||
address string
|
||||
muConn sync.Mutex
|
||||
conn io.ReadWriteCloser
|
||||
|
||||
muCommand sync.Mutex
|
||||
muConn sync.Mutex
|
||||
conn io.ReadWriteCloser
|
||||
|
||||
muControl sync.Mutex
|
||||
lastControl *simulator.ControlMsg
|
||||
|
||||
log *log.Entry
|
||||
log *zap.SugaredLogger
|
||||
|
||||
frameSubscribers map[chan<- *events.FrameMessage]interface{}
|
||||
steeringSubscribers map[chan<- *events.SteeringMessage]interface{}
|
||||
throttleSubscribers map[chan<- *events.ThrottleMessage]interface{}
|
||||
|
||||
telemetrySubscribers map[chan *simulator.TelemetryMsg]interface{}
|
||||
carSubscribers map[chan *simulator.Msg]interface{}
|
||||
racerSubscribers map[chan *simulator.Msg]interface{}
|
||||
cameraSubscribers map[chan *simulator.Msg]interface{}
|
||||
|
||||
carConfig *simulator.CarConfigMsg
|
||||
racer *simulator.RacerBioMsg
|
||||
cameraConfig *simulator.CamConfigMsg
|
||||
}
|
||||
|
||||
func (p *Gateway) Start() error {
|
||||
p.log.Info("connect to simulator")
|
||||
p.cancel = make(chan interface{})
|
||||
msgChan := make(chan *simulator.TelemetryMsg)
|
||||
func (g *Gateway) Start() error {
|
||||
g.log.Info("connect to simulator")
|
||||
g.cancel = make(chan interface{})
|
||||
msgChan := g.subscribeTelemetryEvents()
|
||||
|
||||
go p.run(msgChan)
|
||||
go g.run()
|
||||
|
||||
err := g.writeRacerConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to configure racer to server: %v", err)
|
||||
}
|
||||
err = g.writeCarConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to configure car to server: %v", err)
|
||||
}
|
||||
err = g.writeCameraConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to configure camera to server: %v", err)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case msg := <-msgChan:
|
||||
fr := p.publishFrame(msg)
|
||||
go p.publishInputSteering(msg, fr)
|
||||
go p.publishInputThrottle(msg, fr)
|
||||
case <-p.cancel:
|
||||
fr := g.publishFrame(msg)
|
||||
go g.publishInputSteering(msg, fr)
|
||||
go g.publishInputThrottle(msg, fr)
|
||||
case <-g.cancel:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Gateway) Stop() {
|
||||
p.log.Info("close simulator gateway")
|
||||
close(p.cancel)
|
||||
func (g *Gateway) Stop() {
|
||||
g.log.Info("close simulator gateway")
|
||||
close(g.cancel)
|
||||
|
||||
if err := p.Close(); err != nil {
|
||||
p.log.Warnf("unexpected error while simulator connection is closed: %v", err)
|
||||
if err := g.Close(); err != nil {
|
||||
g.log.Warnf("unexpected error while simulator connection is closed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Gateway) Close() error {
|
||||
for c := range p.frameSubscribers {
|
||||
func (g *Gateway) Close() error {
|
||||
for c := range g.frameSubscribers {
|
||||
close(c)
|
||||
}
|
||||
for c := range p.steeringSubscribers {
|
||||
for c := range g.steeringSubscribers {
|
||||
close(c)
|
||||
}
|
||||
for c := range p.throttleSubscribers {
|
||||
for c := range g.throttleSubscribers {
|
||||
close(c)
|
||||
}
|
||||
if p.conn == nil {
|
||||
p.log.Warn("no connection to close")
|
||||
if g.conn == nil {
|
||||
g.log.Warn("no connection to close")
|
||||
return nil
|
||||
}
|
||||
if err := p.conn.Close(); err != nil {
|
||||
if err := g.conn.Close(); err != nil {
|
||||
return fmt.Errorf("unable to close connection to simulator: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Gateway) run(msgChan chan<- *simulator.TelemetryMsg) {
|
||||
err := p.connect()
|
||||
func (g *Gateway) run() {
|
||||
err := g.connect()
|
||||
if err != nil {
|
||||
p.log.Panicf("unable to connect to simulator: %v", err)
|
||||
g.log.Panicf("unable to connect to simulator: %v", err)
|
||||
}
|
||||
|
||||
reader := bufio.NewReader(p.conn)
|
||||
|
||||
err = retry.Do(
|
||||
func() error { return p.listen(msgChan, reader) },
|
||||
func() error { return g.listen() },
|
||||
)
|
||||
if err != nil {
|
||||
p.log.Errorf("unable to connect to server: %v", err)
|
||||
g.log.Errorf("unable to connect to server: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Gateway) connect() error {
|
||||
p.muConn.Lock()
|
||||
defer p.muConn.Unlock()
|
||||
func (g *Gateway) connect() error {
|
||||
g.muConn.Lock()
|
||||
defer g.muConn.Unlock()
|
||||
|
||||
if p.conn != nil {
|
||||
if g.conn != nil {
|
||||
// already connected
|
||||
return nil
|
||||
}
|
||||
err := retry.Do(func() error {
|
||||
p.log.Info("connect to simulator")
|
||||
conn, err := connect(p.address)
|
||||
g.log.Info("connect to simulator")
|
||||
conn, err := connect(g.address)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to connect to simulator at %v", p.address)
|
||||
return fmt.Errorf("unable to connect to simulator at %v", g.address)
|
||||
}
|
||||
p.conn = conn
|
||||
p.log.Info("connection success")
|
||||
g.conn = conn
|
||||
g.log.Info("connection success")
|
||||
return nil
|
||||
},
|
||||
retry.Delay(1*time.Second),
|
||||
@ -149,30 +178,83 @@ func (p *Gateway) connect() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *Gateway) listen(msgChan chan<- *simulator.TelemetryMsg, reader *bufio.Reader) error {
|
||||
func (g *Gateway) listen() error {
|
||||
reader := bufio.NewReader(g.conn)
|
||||
|
||||
for {
|
||||
rawLine, err := reader.ReadBytes('\n')
|
||||
if err == io.EOF {
|
||||
p.log.Info("Connection closed")
|
||||
g.log.Info("Connection closed")
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read response: %v", err)
|
||||
}
|
||||
|
||||
var msg simulator.TelemetryMsg
|
||||
var msg simulator.Msg
|
||||
err = json.Unmarshal(rawLine, &msg)
|
||||
if err != nil {
|
||||
p.log.Errorf("unable to unmarshal simulator msg '%v': %v", string(rawLine), err)
|
||||
g.log.Errorf("unable to unmarshal simulator msg '%v': %v", string(rawLine), err)
|
||||
}
|
||||
if "telemetry" != msg.MsgType {
|
||||
continue
|
||||
|
||||
switch msg.MsgType {
|
||||
case simulator.MsgTypeTelemetry:
|
||||
g.broadcastTelemetryMsg(rawLine)
|
||||
case simulator.MsgTypeCarLoaded:
|
||||
g.broadcastCarMsg(rawLine)
|
||||
case simulator.MsgTypeRacerInfo:
|
||||
g.broadcastRacerMsg(rawLine)
|
||||
default:
|
||||
g.log.Warnf("unmanaged simulator message: %v", string(rawLine))
|
||||
}
|
||||
msgChan <- &msg
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Gateway) publishFrame(msgSim *simulator.TelemetryMsg) *events.FrameRef {
|
||||
func (g *Gateway) broadcastTelemetryMsg(rawLine []byte) {
|
||||
for c := range g.telemetrySubscribers {
|
||||
|
||||
var tMsg simulator.TelemetryMsg
|
||||
err := json.Unmarshal(rawLine, &tMsg)
|
||||
if err != nil {
|
||||
g.log.Errorf("unable to unmarshal telemetry simulator msg '%v': %v", string(rawLine), err)
|
||||
}
|
||||
c <- &tMsg
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gateway) broadcastCarMsg(rawLine []byte) {
|
||||
for c := range g.carSubscribers {
|
||||
var tMsg simulator.Msg
|
||||
err := json.Unmarshal(rawLine, &tMsg)
|
||||
if err != nil {
|
||||
g.log.Errorf("unable to unmarshal car simulator msg '%v': %v", string(rawLine), err)
|
||||
}
|
||||
c <- &tMsg
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gateway) broadcastRacerMsg(rawLine []byte) {
|
||||
for c := range g.racerSubscribers {
|
||||
var tMsg simulator.Msg
|
||||
err := json.Unmarshal(rawLine, &tMsg)
|
||||
if err != nil {
|
||||
g.log.Errorf("unable to unmarshal racer simulator msg '%v': %v", string(rawLine), err)
|
||||
}
|
||||
c <- &tMsg
|
||||
}
|
||||
}
|
||||
func (g *Gateway) broadcastCameraMsg(rawLine []byte) {
|
||||
for c := range g.cameraSubscribers {
|
||||
var tMsg simulator.Msg
|
||||
err := json.Unmarshal(rawLine, &tMsg)
|
||||
if err != nil {
|
||||
g.log.Errorf("unable to unmarshal camera simulator msg '%v': %v", string(rawLine), err)
|
||||
}
|
||||
c <- &tMsg
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gateway) publishFrame(msgSim *simulator.TelemetryMsg) *events.FrameRef {
|
||||
now := time.Now()
|
||||
frameRef := &events.FrameRef{
|
||||
Name: "gateway",
|
||||
@ -187,55 +269,97 @@ func (p *Gateway) publishFrame(msgSim *simulator.TelemetryMsg) *events.FrameRef
|
||||
Frame: msgSim.Image,
|
||||
}
|
||||
|
||||
log.Debugf("events frame '%v/%v'", msg.Id.Name, msg.Id.Id)
|
||||
for fs := range p.frameSubscribers {
|
||||
g.log.Debugf("events frame '%v/%v'", msg.Id.Name, msg.Id.Id)
|
||||
|
||||
for fs := range g.frameSubscribers {
|
||||
fs <- msg
|
||||
}
|
||||
return frameRef
|
||||
}
|
||||
|
||||
func (p *Gateway) publishInputSteering(msgSim *simulator.TelemetryMsg, frameRef *events.FrameRef) {
|
||||
func (g *Gateway) publishInputSteering(msgSim *simulator.TelemetryMsg, frameRef *events.FrameRef) {
|
||||
steering := &events.SteeringMessage{
|
||||
FrameRef: frameRef,
|
||||
Steering: float32(msgSim.SteeringAngle),
|
||||
Confidence: 1.0,
|
||||
}
|
||||
|
||||
log.Debugf("events steering '%v'", steering.Steering)
|
||||
for ss := range p.steeringSubscribers {
|
||||
g.log.Debugf("events steering '%v'", steering.Steering)
|
||||
for ss := range g.steeringSubscribers {
|
||||
ss <- steering
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Gateway) publishInputThrottle(msgSim *simulator.TelemetryMsg, frameRef *events.FrameRef) {
|
||||
func (g *Gateway) publishInputThrottle(msgSim *simulator.TelemetryMsg, frameRef *events.FrameRef) {
|
||||
msg := &events.ThrottleMessage{
|
||||
FrameRef: frameRef,
|
||||
Throttle: float32(msgSim.Throttle),
|
||||
Confidence: 1.0,
|
||||
}
|
||||
|
||||
log.Debugf("events throttle '%v'", msg.Throttle)
|
||||
for ts := range p.throttleSubscribers {
|
||||
g.log.Debugf("events throttle '%v'", msg.Throttle)
|
||||
for ts := range g.throttleSubscribers {
|
||||
ts <- msg
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Gateway) SubscribeFrame() <-chan *events.FrameMessage {
|
||||
func (g *Gateway) SubscribeFrame() <-chan *events.FrameMessage {
|
||||
frameChan := make(chan *events.FrameMessage)
|
||||
p.frameSubscribers[frameChan] = struct{}{}
|
||||
g.frameSubscribers[frameChan] = struct{}{}
|
||||
return frameChan
|
||||
}
|
||||
func (p *Gateway) SubscribeSteering() <-chan *events.SteeringMessage {
|
||||
func (g *Gateway) SubscribeSteering() <-chan *events.SteeringMessage {
|
||||
steeringChan := make(chan *events.SteeringMessage)
|
||||
p.steeringSubscribers[steeringChan] = struct{}{}
|
||||
g.steeringSubscribers[steeringChan] = struct{}{}
|
||||
return steeringChan
|
||||
}
|
||||
func (p *Gateway) SubscribeThrottle() <-chan *events.ThrottleMessage {
|
||||
func (g *Gateway) SubscribeThrottle() <-chan *events.ThrottleMessage {
|
||||
throttleChan := make(chan *events.ThrottleMessage)
|
||||
p.throttleSubscribers[throttleChan] = struct{}{}
|
||||
g.throttleSubscribers[throttleChan] = struct{}{}
|
||||
return throttleChan
|
||||
}
|
||||
|
||||
func (g *Gateway) subscribeTelemetryEvents() chan *simulator.TelemetryMsg {
|
||||
telemetryChan := make(chan *simulator.TelemetryMsg)
|
||||
g.telemetrySubscribers[telemetryChan] = struct{}{}
|
||||
return telemetryChan
|
||||
}
|
||||
func (g *Gateway) unsubscribeTelemetryEvents(telemetryChan chan *simulator.TelemetryMsg) {
|
||||
delete(g.telemetrySubscribers, telemetryChan)
|
||||
close(telemetryChan)
|
||||
}
|
||||
func (g *Gateway) subscribeCarEvents() chan *simulator.Msg {
|
||||
carChan := make(chan *simulator.Msg)
|
||||
g.carSubscribers[carChan] = struct{}{}
|
||||
return carChan
|
||||
}
|
||||
func (g *Gateway) unsubscribeCarEvents(carChan chan *simulator.Msg) {
|
||||
delete(g.carSubscribers, carChan)
|
||||
close(carChan)
|
||||
}
|
||||
|
||||
func (g *Gateway) subscribeRacerEvents() chan *simulator.Msg {
|
||||
racerChan := make(chan *simulator.Msg)
|
||||
g.racerSubscribers[racerChan] = struct{}{}
|
||||
return racerChan
|
||||
}
|
||||
|
||||
func (g *Gateway) unsubscribeRacerEvents(racerChan chan *simulator.Msg) {
|
||||
delete(g.racerSubscribers, racerChan)
|
||||
close(racerChan)
|
||||
}
|
||||
|
||||
func (g *Gateway) subscribeCameraEvents() chan *simulator.Msg {
|
||||
cameraChan := make(chan *simulator.Msg)
|
||||
g.cameraSubscribers[cameraChan] = struct{}{}
|
||||
return cameraChan
|
||||
}
|
||||
|
||||
func (g *Gateway) unsubscribeCameraEvents(cameraChan chan *simulator.Msg) {
|
||||
delete(g.cameraSubscribers, cameraChan)
|
||||
close(cameraChan)
|
||||
}
|
||||
|
||||
var connect = func(address string) (io.ReadWriteCloser, error) {
|
||||
conn, err := net.Dial("tcp", address)
|
||||
if err != nil {
|
||||
@ -244,63 +368,144 @@ var connect = func(address string) (io.ReadWriteCloser, error) {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (p *Gateway) WriteSteering(message *events.SteeringMessage) {
|
||||
p.muControl.Lock()
|
||||
defer p.muControl.Unlock()
|
||||
p.initLastControlMsg()
|
||||
func (g *Gateway) WriteSteering(message *events.SteeringMessage) {
|
||||
g.muControl.Lock()
|
||||
defer g.muControl.Unlock()
|
||||
g.initLastControlMsg()
|
||||
|
||||
p.lastControl.Steering = message.Steering
|
||||
p.writeControlCommandToSimulator()
|
||||
g.lastControl.Steering = fmt.Sprintf("%.2f", message.Steering)
|
||||
g.writeControlCommandToSimulator()
|
||||
}
|
||||
|
||||
func (p *Gateway) writeControlCommandToSimulator() {
|
||||
if err := p.connect(); err != nil {
|
||||
p.log.Errorf("unable to connect to simulator to send control command: %v", err)
|
||||
return
|
||||
}
|
||||
w := bufio.NewWriter(p.conn)
|
||||
content, err := json.Marshal(p.lastControl)
|
||||
func (g *Gateway) writeControlCommandToSimulator() {
|
||||
content, err := json.Marshal(g.lastControl)
|
||||
if err != nil {
|
||||
p.log.Errorf("unable to marshall control msg \"%#v\": %v", p.lastControl, err)
|
||||
g.log.Errorf("unable to marshall control msg \"%#v\": %v", g.lastControl, err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = w.Write(append(content, '\n'))
|
||||
err = g.writeCommand(content)
|
||||
if err != nil {
|
||||
p.log.Errorf("unable to write control msg \"%#v\" to simulator: %v", p.lastControl, err)
|
||||
return
|
||||
g.log.Errorf("unable to send control command to simulator: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gateway) writeCommand(content []byte) error {
|
||||
g.muCommand.Lock()
|
||||
defer g.muCommand.Unlock()
|
||||
|
||||
if err := g.connect(); err != nil {
|
||||
g.log.Errorf("unable to connect to simulator to send control command: %v", err)
|
||||
return nil
|
||||
}
|
||||
g.log.Debugf("write command to simulator: %v", string(content))
|
||||
w := bufio.NewWriter(g.conn)
|
||||
|
||||
_, err := w.Write(append(content, '\n'))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to write control msg \"%#v\" to simulator: %v", g.lastControl, err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
p.log.Errorf("unable to flush control msg \"%#v\" to simulator: %v", p.lastControl, err)
|
||||
return
|
||||
return fmt.Errorf("unable to flush control msg \"%#v\" to simulator: %v", g.lastControl, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Gateway) WriteThrottle(message *events.ThrottleMessage) {
|
||||
p.muControl.Lock()
|
||||
defer p.muControl.Unlock()
|
||||
p.initLastControlMsg()
|
||||
func (g *Gateway) WriteThrottle(message *events.ThrottleMessage) {
|
||||
g.muControl.Lock()
|
||||
defer g.muControl.Unlock()
|
||||
g.initLastControlMsg()
|
||||
|
||||
if message.Throttle > 0 {
|
||||
p.lastControl.Throttle = message.Throttle
|
||||
p.lastControl.Brake = 0.
|
||||
g.lastControl.Throttle = fmt.Sprintf("%.2f", message.Throttle)
|
||||
g.lastControl.Brake = "0.0"
|
||||
} else {
|
||||
p.lastControl.Throttle = 0.
|
||||
p.lastControl.Brake = -1 * message.Throttle
|
||||
g.lastControl.Throttle = "0.0"
|
||||
g.lastControl.Brake = fmt.Sprintf("%.2f", -1*message.Throttle)
|
||||
}
|
||||
|
||||
p.writeControlCommandToSimulator()
|
||||
g.writeControlCommandToSimulator()
|
||||
}
|
||||
|
||||
func (p *Gateway) initLastControlMsg() {
|
||||
if p.lastControl != nil {
|
||||
func (g *Gateway) initLastControlMsg() {
|
||||
if g.lastControl != nil {
|
||||
return
|
||||
}
|
||||
p.lastControl = &simulator.ControlMsg{
|
||||
MsgType: "control",
|
||||
Steering: 0.,
|
||||
Throttle: 0.,
|
||||
Brake: 0.,
|
||||
g.lastControl = &simulator.ControlMsg{
|
||||
MsgType: simulator.MsgTypeControl,
|
||||
Steering: "0.0",
|
||||
Throttle: "0.0",
|
||||
Brake: "0.0",
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gateway) writeCarConfig() error {
|
||||
carChan := g.subscribeCarEvents()
|
||||
defer g.unsubscribeCarEvents(carChan)
|
||||
|
||||
g.log.Info("Send car configuration")
|
||||
|
||||
content, err := json.Marshal(g.carConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to marshall car config msg \"%#v\": %v", g.lastControl, err)
|
||||
}
|
||||
|
||||
err = g.writeCommand(content)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to send car config to simulator: %v", err)
|
||||
}
|
||||
|
||||
msg := <-carChan
|
||||
g.log.Infof("Car loaded: %v", msg)
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateway) writeRacerConfig() error {
|
||||
racerChan := g.subscribeRacerEvents()
|
||||
defer g.unsubscribeRacerEvents(racerChan)
|
||||
|
||||
g.log.Info("Send racer configuration")
|
||||
|
||||
content, err := json.Marshal(g.racer)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to marshall racer config msg \"%#v\": %v", g.lastControl, err)
|
||||
}
|
||||
|
||||
err = g.writeCommand(content)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to send racer config to simulator: %v", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case msg := <-racerChan:
|
||||
g.log.Infof("Racer loaded: %v", msg)
|
||||
case <-time.Tick(250 * time.Millisecond):
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateway) writeCameraConfig() error {
|
||||
cameraChan := g.subscribeCameraEvents()
|
||||
defer g.unsubscribeCameraEvents(cameraChan)
|
||||
|
||||
g.log.Info("Send camera configuration")
|
||||
|
||||
content, err := json.Marshal(g.cameraConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to marshall camera config msg \"%#v\": %v", g.lastControl, err)
|
||||
}
|
||||
|
||||
err = g.writeCommand(content)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to send camera config to simulator: %v", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case msg := <-cameraChan:
|
||||
g.log.Infof("Camera configured: %v", msg)
|
||||
case <-time.Tick(250 * time.Millisecond):
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -2,8 +2,10 @@ package gateway
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/cyrilix/robocar-protobuf/go/events"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/cyrilix/robocar-simulator/pkg/simulator"
|
||||
"go.uber.org/zap"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -23,7 +25,11 @@ func TestGateway_ListenEvents(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
|
||||
gw := New(simulatorMock.Addr())
|
||||
gw := New(simulatorMock.Addr(),
|
||||
&simulator.CarConfigMsg{MsgType: simulator.MsgTypeCarConfig},
|
||||
&simulator.RacerBioMsg{},
|
||||
&simulator.CamConfigMsg{},
|
||||
)
|
||||
go func() {
|
||||
err := gw.Start()
|
||||
if err != nil {
|
||||
@ -40,7 +46,9 @@ func TestGateway_ListenEvents(t *testing.T) {
|
||||
throttleChannel := gw.SubscribeThrottle()
|
||||
|
||||
simulatorMock.WaitConnection()
|
||||
log.Trace("read test data")
|
||||
simulatorMock.EmitMsg(fmt.Sprintf("{\"msg_type\": \"%s\"}", simulator.MsgTypeCarLoaded))
|
||||
|
||||
zap.S().Debug("read test data")
|
||||
testContent, err := ioutil.ReadFile("testdata/msg.json")
|
||||
lines := strings.Split(string(testContent), "\n")
|
||||
|
||||
@ -85,7 +93,7 @@ func TestGateway_ListenEvents(t *testing.T) {
|
||||
throttleIdRef = msg.FrameRef
|
||||
wg.Done()
|
||||
case <-finished:
|
||||
log.Trace("loop ended")
|
||||
zap.S().Debugf("loop ended")
|
||||
endLoop = true
|
||||
case <-timeout:
|
||||
t.Errorf("not all event are published")
|
||||
|
@ -5,23 +5,38 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/cyrilix/robocar-simulator/pkg/simulator"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.uber.org/zap"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Gw2SimMock struct {
|
||||
initMsgsOnce sync.Once
|
||||
initOnce sync.Once
|
||||
|
||||
ln net.Listener
|
||||
notifyChan chan *simulator.ControlMsg
|
||||
initNotifyChan sync.Once
|
||||
notifyCtrlChan chan *simulator.ControlMsg
|
||||
notifyCarChan chan *simulator.CarConfigMsg
|
||||
notifyCamChan chan *simulator.CamConfigMsg
|
||||
}
|
||||
|
||||
func (c *Gw2SimMock) Notify() <-chan *simulator.ControlMsg {
|
||||
c.initNotifyChan.Do(func() { c.notifyChan = make(chan *simulator.ControlMsg) })
|
||||
return c.notifyChan
|
||||
func (c *Gw2SimMock) init(){
|
||||
c.notifyCtrlChan = make(chan *simulator.ControlMsg)
|
||||
c.notifyCarChan = make(chan *simulator.CarConfigMsg)
|
||||
c.notifyCamChan = make(chan *simulator.CamConfigMsg)
|
||||
}
|
||||
|
||||
func (c *Gw2SimMock) NotifyCtrl() <-chan *simulator.ControlMsg {
|
||||
c.initOnce.Do(c.init)
|
||||
return c.notifyCtrlChan
|
||||
}
|
||||
func (c *Gw2SimMock) NotifyCar() <-chan *simulator.CarConfigMsg {
|
||||
c.initOnce.Do(c.init)
|
||||
return c.notifyCarChan
|
||||
}
|
||||
func (c *Gw2SimMock) NotifyCamera() <-chan *simulator.CamConfigMsg {
|
||||
c.initOnce.Do(c.init)
|
||||
return c.notifyCamChan
|
||||
}
|
||||
|
||||
func (c *Gw2SimMock) listen() error {
|
||||
@ -36,7 +51,7 @@ func (c *Gw2SimMock) listen() error {
|
||||
for {
|
||||
conn, err := c.ln.Accept()
|
||||
if err != nil {
|
||||
log.Debugf("connection close: %v", err)
|
||||
zap.S().Debugf("connection close: %v", err)
|
||||
break
|
||||
}
|
||||
go c.handleConnection(conn)
|
||||
@ -50,10 +65,13 @@ func (c *Gw2SimMock) Addr() string {
|
||||
}
|
||||
|
||||
func (c *Gw2SimMock) handleConnection(conn net.Conn) {
|
||||
c.initNotifyChan.Do(func() { c.notifyChan = make(chan *simulator.ControlMsg) })
|
||||
log := zap.S()
|
||||
c.initOnce.Do(c.init)
|
||||
reader := bufio.NewReader(conn)
|
||||
writer := bufio.NewWriter(conn)
|
||||
|
||||
for {
|
||||
rawCmd, err := reader.ReadBytes('\n')
|
||||
rawMsg, err := reader.ReadBytes('\n')
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
log.Debug("connection closed")
|
||||
@ -62,26 +80,71 @@ func (c *Gw2SimMock) handleConnection(conn net.Conn) {
|
||||
log.Errorf("unable to read request: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
var msg simulator.ControlMsg
|
||||
err = json.Unmarshal(rawCmd, &msg)
|
||||
var msg simulator.Msg
|
||||
err = json.Unmarshal(rawMsg, &msg)
|
||||
if err != nil {
|
||||
log.Errorf("unable to unmarchal control msg \"%v\": %v", string(rawCmd), err)
|
||||
log.Errorf("unable to unmarshal msg \"%v\": %v", string(rawMsg), err)
|
||||
continue
|
||||
}
|
||||
|
||||
c.notifyChan <- &msg
|
||||
switch msg.MsgType {
|
||||
case simulator.MsgTypeControl:
|
||||
var msgControl simulator.ControlMsg
|
||||
err = json.Unmarshal(rawMsg, &msgControl)
|
||||
if err != nil {
|
||||
log.Errorf("unable to unmarshal control msg \"%v\": %v", string(rawMsg), err)
|
||||
continue
|
||||
}
|
||||
c.notifyCtrlChan <- &msgControl
|
||||
case simulator.MsgTypeCarConfig:
|
||||
var msgCar simulator.CarConfigMsg
|
||||
err = json.Unmarshal(rawMsg, &msgCar)
|
||||
if err != nil {
|
||||
log.Errorf("unable to unmarshal car msg \"%v\": %v", string(rawMsg), err)
|
||||
continue
|
||||
}
|
||||
c.notifyCarChan <- &msgCar
|
||||
carLoadedMsg := simulator.Msg{MsgType: simulator.MsgTypeCarLoaded}
|
||||
resp, err := json.Marshal(&carLoadedMsg)
|
||||
if err != nil {
|
||||
log.Errorf("unable to generate car loaded response: %v", err)
|
||||
continue
|
||||
}
|
||||
_, err = writer.WriteString(string(resp) + "\n")
|
||||
if err != nil {
|
||||
log.Errorf("unable to write car loaded response: %v", err)
|
||||
continue
|
||||
}
|
||||
err = writer.Flush()
|
||||
if err != nil {
|
||||
log.Errorf("unable to flush car loaded response: %v", err)
|
||||
continue
|
||||
}
|
||||
case simulator.MsgTypeCameraConfig:
|
||||
var msgCam simulator.CamConfigMsg
|
||||
err = json.Unmarshal(rawMsg, &msgCam)
|
||||
if err != nil {
|
||||
log.Errorf("unable to unmarshal camera msg \"%v\": %v", string(rawMsg), err)
|
||||
continue
|
||||
}
|
||||
c.notifyCamChan <- &msgCam
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Gw2SimMock) Close() error {
|
||||
log.Debugf("close mock server")
|
||||
zap.S().Debugf("close mock server")
|
||||
err := c.ln.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to close mock server: %v", err)
|
||||
}
|
||||
if c.notifyChan != nil {
|
||||
close(c.notifyChan)
|
||||
if c.notifyCtrlChan != nil {
|
||||
close(c.notifyCtrlChan)
|
||||
}
|
||||
if c.notifyCarChan != nil {
|
||||
close(c.notifyCarChan)
|
||||
}
|
||||
if c.notifyCamChan != nil {
|
||||
close(c.notifyCamChan)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -92,7 +155,7 @@ type Sim2GwMock struct {
|
||||
conn net.Conn
|
||||
writer *bufio.Writer
|
||||
newConnection chan net.Conn
|
||||
logger *log.Entry
|
||||
logger *zap.SugaredLogger
|
||||
}
|
||||
|
||||
func (c *Sim2GwMock) EmitMsg(p string) (err error) {
|
||||
@ -125,7 +188,7 @@ func (c *Sim2GwMock) WaitConnection() {
|
||||
}
|
||||
|
||||
func (c *Sim2GwMock) Start() error {
|
||||
c.logger = log.WithField("simulator", "mock")
|
||||
c.logger = zap.S().With("simulator", "mock")
|
||||
c.newConnection = make(chan net.Conn)
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:")
|
||||
c.ln = ln
|
||||
|
@ -1,7 +1,22 @@
|
||||
package simulator
|
||||
|
||||
type MsgType string
|
||||
|
||||
const (
|
||||
MsgTypeControl = MsgType("control")
|
||||
MsgTypeTelemetry = MsgType("telemetry")
|
||||
MsgTypeCarConfig = MsgType("car_config")
|
||||
MsgTypeCarLoaded = MsgType("car_loaded")
|
||||
MsgTypeRacerInfo = MsgType("racer_info")
|
||||
MsgTypeCameraConfig = MsgType("cam_config")
|
||||
)
|
||||
|
||||
type Msg struct {
|
||||
MsgType MsgType `json:"msg_type"`
|
||||
}
|
||||
|
||||
type TelemetryMsg struct {
|
||||
MsgType string `json:"msg_type"`
|
||||
MsgType MsgType `json:"msg_type"`
|
||||
SteeringAngle float64 `json:"steering_angle"`
|
||||
Throttle float64 `json:"throttle"`
|
||||
Speed float64 `json:"speed"`
|
||||
@ -14,10 +29,88 @@ type TelemetryMsg struct {
|
||||
Cte float64 `json:"cte"`
|
||||
}
|
||||
|
||||
/* Json msg used to control cars. MsgType must be filled with "control" */
|
||||
// ControlMsg is json msg used to control cars. MsgType must be filled with "control"
|
||||
type ControlMsg struct {
|
||||
MsgType string `json:"msg_type"`
|
||||
Steering float32 `json:"steering"`
|
||||
Throttle float32 `json:"throttle"`
|
||||
Brake float32 `json:"brake"`
|
||||
MsgType MsgType `json:"msg_type"`
|
||||
Steering string `json:"steering"`
|
||||
Throttle string `json:"throttle"`
|
||||
Brake string `json:"brake"`
|
||||
}
|
||||
|
||||
type GetSceneNamesMsg struct {
|
||||
MsgType MsgType `json:"msg_type"`
|
||||
SceneName string `json:"scene_name"`
|
||||
}
|
||||
|
||||
type LoadSceneMsg struct {
|
||||
MsgType MsgType `json:"msg_type"`
|
||||
SceneName string `json:"scene_name"`
|
||||
}
|
||||
|
||||
type CarStyle string
|
||||
|
||||
const (
|
||||
CarConfigBodyStyleDonkey = CarStyle("donkey")
|
||||
CarConfigBodyStyleBare = CarStyle("bare")
|
||||
CarConfigBodyStyleCar01 = CarStyle("car01")
|
||||
)
|
||||
|
||||
/*
|
||||
# body_style = "donkey" | "bare" | "car01" choice of string
|
||||
# body_rgb = (128, 128, 128) tuple of ints
|
||||
# car_name = "string less than 64 char"
|
||||
*/
|
||||
type CarConfigMsg struct {
|
||||
MsgType MsgType `json:"msg_type"`
|
||||
BodyStyle CarStyle `json:"body_style"`
|
||||
BodyR string `json:"body_r"`
|
||||
BodyG string `json:"body_g"`
|
||||
BodyB string `json:"body_b"`
|
||||
CarName string `json:"car_name"`
|
||||
FontSize string `json:"font_size"`
|
||||
}
|
||||
|
||||
/*
|
||||
# car_name = "string less than 64 char"
|
||||
# guid = "some random string"
|
||||
*/
|
||||
type RacerBioMsg struct {
|
||||
MsgType MsgType `json:"msg_type"`
|
||||
RacerName string `json:"racer_name"`
|
||||
CarName string `json:"car_name"`
|
||||
Bio string `json:"bio"`
|
||||
Country string `json:"country"`
|
||||
Guid string `json:"guid"`
|
||||
}
|
||||
|
||||
type CameraImageEnc string
|
||||
|
||||
const (
|
||||
CameraImageEncJpeg = CameraImageEnc("JPG")
|
||||
CameraImageEncPng = CameraImageEnc("PNG")
|
||||
CameraImageEncTga = CameraImageEnc("TGA")
|
||||
)
|
||||
|
||||
/* Camera config
|
||||
set any field to Zero to get the default camera setting.
|
||||
offset_x moves camera left/right
|
||||
offset_y moves camera up/down
|
||||
offset_z moves camera forward/back
|
||||
rot_x will rotate the camera
|
||||
with fish_eye_x/y == 0.0 then you get no distortion
|
||||
img_enc can be one of JPG|PNG|TGA
|
||||
*/
|
||||
type CamConfigMsg struct {
|
||||
MsgType MsgType `json:"msg_type"`
|
||||
Fov string `json:"fov"`
|
||||
FishEyeX string `json:"fish_eye_x"`
|
||||
FishEyeY string `json:"fish_eye_y"`
|
||||
ImgW string `json:"img_w"`
|
||||
ImgH string `json:"img_h"`
|
||||
ImgD string `json:"img_d"`
|
||||
ImgEnc CameraImageEnc `json:"img_enc"`
|
||||
OffsetX string `json:"offset_x"`
|
||||
OffsetY string `json:"offset_y"`
|
||||
OffsetZ string `json:"offset_z"`
|
||||
RotX string `json:"rot_x"`
|
||||
}
|
||||
|
5
vendor/github.com/avast/retry-go/.travis.yml
generated
vendored
5
vendor/github.com/avast/retry-go/.travis.yml
generated
vendored
@ -1,13 +1,14 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.6
|
||||
- 1.7
|
||||
- 1.8
|
||||
- 1.9
|
||||
- "1.10"
|
||||
- 1.11
|
||||
- 1.12
|
||||
- 1.13
|
||||
- 1.14
|
||||
- 1.15
|
||||
|
||||
install:
|
||||
- make setup
|
||||
|
37
vendor/github.com/avast/retry-go/README.md
generated
vendored
37
vendor/github.com/avast/retry-go/README.md
generated
vendored
@ -64,6 +64,12 @@ nonintuitive interface (for me)
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
3.0.0
|
||||
|
||||
* `DelayTypeFunc` accepts a new parameter `err` - this breaking change affects
|
||||
only your custom Delay Functions. This change allow [make delay functions based
|
||||
on error](examples/delay_based_on_error_test.go).
|
||||
|
||||
1.0.2 -> 2.0.0
|
||||
|
||||
* argument of `retry.Delay` is final delay (no multiplication by `retry.Units`
|
||||
@ -91,13 +97,14 @@ var (
|
||||
DefaultRetryIf = IsRecoverable
|
||||
DefaultDelayType = CombineDelay(BackOffDelay, RandomDelay)
|
||||
DefaultLastErrorOnly = false
|
||||
DefaultContext = context.Background()
|
||||
)
|
||||
```
|
||||
|
||||
#### func BackOffDelay
|
||||
|
||||
```go
|
||||
func BackOffDelay(n uint, config *Config) time.Duration
|
||||
func BackOffDelay(n uint, _ error, config *Config) time.Duration
|
||||
```
|
||||
BackOffDelay is a DelayType which increases delay between consecutive retries
|
||||
|
||||
@ -110,7 +117,7 @@ func Do(retryableFunc RetryableFunc, opts ...Option) error
|
||||
#### func FixedDelay
|
||||
|
||||
```go
|
||||
func FixedDelay(_ uint, config *Config) time.Duration
|
||||
func FixedDelay(_ uint, _ error, config *Config) time.Duration
|
||||
```
|
||||
FixedDelay is a DelayType which keeps delay the same through all iterations
|
||||
|
||||
@ -124,7 +131,7 @@ IsRecoverable checks if error is an instance of `unrecoverableError`
|
||||
#### func RandomDelay
|
||||
|
||||
```go
|
||||
func RandomDelay(_ uint, config *Config) time.Duration
|
||||
func RandomDelay(_ uint, _ error, config *Config) time.Duration
|
||||
```
|
||||
RandomDelay is a DelayType which picks a random delay up to config.maxJitter
|
||||
|
||||
@ -146,9 +153,11 @@ type Config struct {
|
||||
#### type DelayTypeFunc
|
||||
|
||||
```go
|
||||
type DelayTypeFunc func(n uint, config *Config) time.Duration
|
||||
type DelayTypeFunc func(n uint, err error, config *Config) time.Duration
|
||||
```
|
||||
|
||||
DelayTypeFunc is called to return the next delay to wait after the retriable
|
||||
function fails on `err` after `n` attempts.
|
||||
|
||||
#### func CombineDelay
|
||||
|
||||
@ -207,6 +216,26 @@ func Attempts(attempts uint) Option
|
||||
```
|
||||
Attempts set count of retry default is 10
|
||||
|
||||
#### func Context
|
||||
|
||||
```go
|
||||
func Context(ctx context.Context) Option
|
||||
```
|
||||
Context allow to set context of retry default are Background context
|
||||
|
||||
example of immediately cancellation (maybe it isn't the best example, but it
|
||||
describes behavior enough; I hope)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
|
||||
retry.Do(
|
||||
func() error {
|
||||
...
|
||||
},
|
||||
retry.Context(ctx),
|
||||
)
|
||||
|
||||
#### func Delay
|
||||
|
||||
```go
|
||||
|
2
vendor/github.com/avast/retry-go/VERSION
generated
vendored
2
vendor/github.com/avast/retry-go/VERSION
generated
vendored
@ -1 +1 @@
|
||||
2.6.0
|
||||
3.0.0
|
||||
|
65
vendor/github.com/avast/retry-go/options.go
generated
vendored
65
vendor/github.com/avast/retry-go/options.go
generated
vendored
@ -1,6 +1,8 @@
|
||||
package retry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
@ -12,7 +14,8 @@ type RetryIfFunc func(error) bool
|
||||
// n = count of attempts
|
||||
type OnRetryFunc func(n uint, err error)
|
||||
|
||||
type DelayTypeFunc func(n uint, config *Config) time.Duration
|
||||
// DelayTypeFunc is called to return the next delay to wait after the retriable function fails on `err` after `n` attempts.
|
||||
type DelayTypeFunc func(n uint, err error, config *Config) time.Duration
|
||||
|
||||
type Config struct {
|
||||
attempts uint
|
||||
@ -23,6 +26,9 @@ type Config struct {
|
||||
retryIf RetryIfFunc
|
||||
delayType DelayTypeFunc
|
||||
lastErrorOnly bool
|
||||
context context.Context
|
||||
|
||||
maxBackOffN uint
|
||||
}
|
||||
|
||||
// Option represents an option for retry.
|
||||
@ -76,28 +82,49 @@ func DelayType(delayType DelayTypeFunc) Option {
|
||||
}
|
||||
|
||||
// BackOffDelay is a DelayType which increases delay between consecutive retries
|
||||
func BackOffDelay(n uint, config *Config) time.Duration {
|
||||
return config.delay * (1 << n)
|
||||
func BackOffDelay(n uint, _ error, config *Config) time.Duration {
|
||||
// 1 << 63 would overflow signed int64 (time.Duration), thus 62.
|
||||
const max uint = 62
|
||||
|
||||
if config.maxBackOffN == 0 {
|
||||
if config.delay <= 0 {
|
||||
config.delay = 1
|
||||
}
|
||||
|
||||
config.maxBackOffN = max - uint(math.Floor(math.Log2(float64(config.delay))))
|
||||
}
|
||||
|
||||
if n > config.maxBackOffN {
|
||||
n = config.maxBackOffN
|
||||
}
|
||||
|
||||
return config.delay << n
|
||||
}
|
||||
|
||||
// FixedDelay is a DelayType which keeps delay the same through all iterations
|
||||
func FixedDelay(_ uint, config *Config) time.Duration {
|
||||
func FixedDelay(_ uint, _ error, config *Config) time.Duration {
|
||||
return config.delay
|
||||
}
|
||||
|
||||
// RandomDelay is a DelayType which picks a random delay up to config.maxJitter
|
||||
func RandomDelay(_ uint, config *Config) time.Duration {
|
||||
func RandomDelay(_ uint, _ error, config *Config) time.Duration {
|
||||
return time.Duration(rand.Int63n(int64(config.maxJitter)))
|
||||
}
|
||||
|
||||
// CombineDelay is a DelayType the combines all of the specified delays into a new DelayTypeFunc
|
||||
func CombineDelay(delays ...DelayTypeFunc) DelayTypeFunc {
|
||||
return func(n uint, config *Config) time.Duration {
|
||||
var total time.Duration
|
||||
const maxInt64 = uint64(math.MaxInt64)
|
||||
|
||||
return func(n uint, err error, config *Config) time.Duration {
|
||||
var total uint64
|
||||
for _, delay := range delays {
|
||||
total += delay(n, config)
|
||||
total += uint64(delay(n, err, config))
|
||||
if total > maxInt64 {
|
||||
total = maxInt64
|
||||
}
|
||||
}
|
||||
return total
|
||||
|
||||
return time.Duration(total)
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,3 +176,23 @@ func RetryIf(retryIf RetryIfFunc) Option {
|
||||
c.retryIf = retryIf
|
||||
}
|
||||
}
|
||||
|
||||
// Context allow to set context of retry
|
||||
// default are Background context
|
||||
//
|
||||
// example of immediately cancellation (maybe it isn't the best example, but it describes behavior enough; I hope)
|
||||
//
|
||||
// ctx, cancel := context.WithCancel(context.Background())
|
||||
// cancel()
|
||||
//
|
||||
// retry.Do(
|
||||
// func() error {
|
||||
// ...
|
||||
// },
|
||||
// retry.Context(ctx),
|
||||
// )
|
||||
func Context(ctx context.Context) Option {
|
||||
return func(c *Config) {
|
||||
c.context = ctx
|
||||
}
|
||||
}
|
||||
|
23
vendor/github.com/avast/retry-go/retry.go
generated
vendored
23
vendor/github.com/avast/retry-go/retry.go
generated
vendored
@ -43,8 +43,14 @@ SEE ALSO
|
||||
|
||||
* [matryer/try](https://github.com/matryer/try) - very popular package, nonintuitive interface (for me)
|
||||
|
||||
|
||||
BREAKING CHANGES
|
||||
|
||||
3.0.0
|
||||
|
||||
* `DelayTypeFunc` accepts a new parameter `err` - this breaking change affects only your custom Delay Functions. This change allow [make delay functions based on error](examples/delay_based_on_error_test.go).
|
||||
|
||||
|
||||
1.0.2 -> 2.0.0
|
||||
|
||||
* argument of `retry.Delay` is final delay (no multiplication by `retry.Units` anymore)
|
||||
@ -65,6 +71,7 @@ BREAKING CHANGES
|
||||
package retry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@ -81,6 +88,7 @@ var (
|
||||
DefaultRetryIf = IsRecoverable
|
||||
DefaultDelayType = CombineDelay(BackOffDelay, RandomDelay)
|
||||
DefaultLastErrorOnly = false
|
||||
DefaultContext = context.Background()
|
||||
)
|
||||
|
||||
func Do(retryableFunc RetryableFunc, opts ...Option) error {
|
||||
@ -95,6 +103,7 @@ func Do(retryableFunc RetryableFunc, opts ...Option) error {
|
||||
retryIf: DefaultRetryIf,
|
||||
delayType: DefaultDelayType,
|
||||
lastErrorOnly: DefaultLastErrorOnly,
|
||||
context: DefaultContext,
|
||||
}
|
||||
|
||||
//apply opts
|
||||
@ -102,6 +111,10 @@ func Do(retryableFunc RetryableFunc, opts ...Option) error {
|
||||
opt(config)
|
||||
}
|
||||
|
||||
if err := config.context.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var errorLog Error
|
||||
if !config.lastErrorOnly {
|
||||
errorLog = make(Error, config.attempts)
|
||||
@ -127,11 +140,17 @@ func Do(retryableFunc RetryableFunc, opts ...Option) error {
|
||||
break
|
||||
}
|
||||
|
||||
delayTime := config.delayType(n, config)
|
||||
delayTime := config.delayType(n, err, config)
|
||||
if config.maxDelay > 0 && delayTime > config.maxDelay {
|
||||
delayTime = config.maxDelay
|
||||
}
|
||||
time.Sleep(delayTime)
|
||||
|
||||
select {
|
||||
case <-time.After(delayTime):
|
||||
case <-config.context.Done():
|
||||
return config.context.Err()
|
||||
}
|
||||
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
6
vendor/github.com/cyrilix/robocar-protobuf/go/events/events.pb.go
generated
vendored
6
vendor/github.com/cyrilix/robocar-protobuf/go/events/events.pb.go
generated
vendored
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0-devel
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.12.4
|
||||
// source: events/events.proto
|
||||
|
||||
@ -966,8 +966,8 @@ var file_events_events_proto_rawDesc = []byte{
|
||||
0x50, 0x49, 0x4c, 0x4f, 0x54, 0x10, 0x02, 0x2a, 0x32, 0x0a, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x4f,
|
||||
0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x59, 0x10, 0x00, 0x12, 0x07,
|
||||
0x0a, 0x03, 0x43, 0x41, 0x52, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x55, 0x4d, 0x50, 0x10,
|
||||
0x02, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x4c, 0x4f, 0x54, 0x10, 0x03, 0x42, 0x08, 0x5a, 0x06, 0x65,
|
||||
0x76, 0x65, 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x02, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x4c, 0x4f, 0x54, 0x10, 0x03, 0x42, 0x0a, 0x5a, 0x08, 0x2e,
|
||||
0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
8
vendor/github.com/eclipse/paho.mqtt.golang/README.md
generated
vendored
8
vendor/github.com/eclipse/paho.mqtt.golang/README.md
generated
vendored
@ -104,8 +104,12 @@ func main() {
|
||||
|
||||
* Seemingly random disconnections may be caused by another client connecting to the broker with the same client
|
||||
identifier; this is as per the [spec](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc384800405).
|
||||
* A `MessageHandler` (called when a new message is received) must not block. If you wish to perform a long-running task,
|
||||
or publish a message, then please use a go routine (blocking in the handler is a common cause of unexpected `pingresp
|
||||
* Unless ordered delivery of messages is essential (and you have configured your broker to support this e.g.
|
||||
`max_inflight_messages=1` in mosquitto) then set `ClientOptions.SetOrderMatters(false)`. Doing so will avoid the
|
||||
below issue (deadlocks due to blocking message handlers).
|
||||
* A `MessageHandler` (called when a new message is received) must not block (unless
|
||||
`ClientOptions.SetOrderMatters(false)` set). If you wish to perform a long-running task, or publish a message, then
|
||||
please use a go routine (blocking in the handler is a common cause of unexpected `pingresp
|
||||
not received, disconnecting` errors).
|
||||
* When QOS1+ subscriptions have been created previously and you connect with `CleanSession` set to false it is possible that the broker will deliver retained
|
||||
messages before `Subscribe` can be called. To process these messages either configure a handler with `AddRoute` or
|
||||
|
112
vendor/github.com/eclipse/paho.mqtt.golang/client.go
generated
vendored
112
vendor/github.com/eclipse/paho.mqtt.golang/client.go
generated
vendored
@ -55,6 +55,8 @@ const (
|
||||
// information can be found in their respective documentation.
|
||||
// Numerous connection options may be specified by configuring a
|
||||
// and then supplying a ClientOptions type.
|
||||
// Implementations of Client must be safe for concurrent use by multiple
|
||||
// goroutines
|
||||
type Client interface {
|
||||
// IsConnected returns a bool signifying whether
|
||||
// the client is connected or not.
|
||||
@ -75,11 +77,21 @@ type Client interface {
|
||||
// Returns a token to track delivery of the message to the broker
|
||||
Publish(topic string, qos byte, retained bool, payload interface{}) Token
|
||||
// Subscribe starts a new subscription. Provide a MessageHandler to be executed when
|
||||
// a message is published on the topic provided, or nil for the default handler
|
||||
// a message is published on the topic provided, or nil for the default handler.
|
||||
//
|
||||
// If options.OrderMatters is true (the default) then callback must not block or
|
||||
// call functions within this package that may block (e.g. Publish) other than in
|
||||
// a new go routine.
|
||||
// callback must be safe for concurrent use by multiple goroutines.
|
||||
Subscribe(topic string, qos byte, callback MessageHandler) Token
|
||||
// SubscribeMultiple starts a new subscription for multiple topics. Provide a MessageHandler to
|
||||
// be executed when a message is published on one of the topics provided, or nil for the
|
||||
// default handler
|
||||
// default handler.
|
||||
//
|
||||
// If options.OrderMatters is true (the default) then callback must not block or
|
||||
// call functions within this package that may block (e.g. Publish) other than in
|
||||
// a new go routine.
|
||||
// callback must be safe for concurrent use by multiple goroutines.
|
||||
SubscribeMultiple(filters map[string]byte, callback MessageHandler) Token
|
||||
// Unsubscribe will end the subscription from each of the topics provided.
|
||||
// Messages published to those topics from other clients will no longer be
|
||||
@ -87,7 +99,13 @@ type Client interface {
|
||||
Unsubscribe(topics ...string) Token
|
||||
// AddRoute allows you to add a handler for messages on a specific topic
|
||||
// without making a subscription. For example having a different handler
|
||||
// for parts of a wildcard subscription
|
||||
// for parts of a wildcard subscription or for receiving retained messages
|
||||
// upon connection (before Sub scribe can be processed).
|
||||
//
|
||||
// If options.OrderMatters is true (the default) then callback must not block or
|
||||
// call functions within this package that may block (e.g. Publish) other than in
|
||||
// a new go routine.
|
||||
// callback must be safe for concurrent use by multiple goroutines.
|
||||
AddRoute(topic string, callback MessageHandler)
|
||||
// OptionsReader returns a ClientOptionsReader which is a copy of the clientoptions
|
||||
// in use by the client.
|
||||
@ -95,6 +113,8 @@ type Client interface {
|
||||
}
|
||||
|
||||
// client implements the Client interface
|
||||
// clients are safe for concurrent use by multiple
|
||||
// goroutines
|
||||
type client struct {
|
||||
lastSent atomic.Value // time.Time - the last time a packet was successfully sent to network
|
||||
lastReceived atomic.Value // time.Time - the last time a packet was successfully received from network
|
||||
@ -153,6 +173,11 @@ func NewClient(o *ClientOptions) Client {
|
||||
// AddRoute allows you to add a handler for messages on a specific topic
|
||||
// without making a subscription. For example having a different handler
|
||||
// for parts of a wildcard subscription
|
||||
//
|
||||
// If options.OrderMatters is true (the default) then callback must not block or
|
||||
// call functions within this package that may block (e.g. Publish) other than in
|
||||
// a new go routine.
|
||||
// callback must be safe for concurrent use by multiple goroutines.
|
||||
func (c *client) AddRoute(topic string, callback MessageHandler) {
|
||||
if callback != nil {
|
||||
c.msgRouter.addRoute(topic, callback)
|
||||
@ -354,8 +379,13 @@ func (c *client) attemptConnection() (net.Conn, byte, bool, error) {
|
||||
cm := newConnectMsgFromOptions(&c.options, broker)
|
||||
DEBUG.Println(CLI, "about to write new connect msg")
|
||||
CONN:
|
||||
tlsCfg := c.options.TLSConfig
|
||||
if c.options.OnConnectAttempt != nil {
|
||||
DEBUG.Println(CLI, "using custom onConnectAttempt handler...")
|
||||
tlsCfg = c.options.OnConnectAttempt(broker, c.options.TLSConfig)
|
||||
}
|
||||
// Start by opening the network connection (tcp, tls, ws) etc
|
||||
conn, err = openConnection(broker, c.options.TLSConfig, c.options.ConnectTimeout, c.options.HTTPHeaders, c.options.WebsocketOptions)
|
||||
conn, err = openConnection(broker, tlsCfg, c.options.ConnectTimeout, c.options.HTTPHeaders, c.options.WebsocketOptions)
|
||||
if err != nil {
|
||||
ERROR.Println(CLI, err.Error())
|
||||
WARN.Println(CLI, "failed to connect to broker, trying next")
|
||||
@ -372,7 +402,7 @@ func (c *client) attemptConnection() (net.Conn, byte, bool, error) {
|
||||
|
||||
// We may be have to attempt the connection with MQTT 3.1
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
_ = conn.Close()
|
||||
}
|
||||
if !c.options.protocolVersionExplicit && protocolVersion == 4 { // try falling back to 3.1?
|
||||
DEBUG.Println(CLI, "Trying reconnect using MQTT 3.1 protocol")
|
||||
@ -409,12 +439,22 @@ func (c *client) Disconnect(quiesce uint) {
|
||||
|
||||
dm := packets.NewControlPacket(packets.Disconnect).(*packets.DisconnectPacket)
|
||||
dt := newToken(packets.Disconnect)
|
||||
c.oboundP <- &PacketAndToken{p: dm, t: dt}
|
||||
disconnectSent := false
|
||||
select {
|
||||
case c.oboundP <- &PacketAndToken{p: dm, t: dt}:
|
||||
disconnectSent = true
|
||||
case <-c.commsStopped:
|
||||
WARN.Println("Disconnect packet could not be sent because comms stopped")
|
||||
case <-time.After(time.Duration(quiesce) * time.Millisecond):
|
||||
WARN.Println("Disconnect packet not sent due to timeout")
|
||||
}
|
||||
|
||||
// wait for work to finish, or quiesce time consumed
|
||||
DEBUG.Println(CLI, "calling WaitTimeout")
|
||||
dt.WaitTimeout(time.Duration(quiesce) * time.Millisecond)
|
||||
DEBUG.Println(CLI, "WaitTimeout done")
|
||||
if disconnectSent {
|
||||
DEBUG.Println(CLI, "calling WaitTimeout")
|
||||
dt.WaitTimeout(time.Duration(quiesce) * time.Millisecond)
|
||||
DEBUG.Println(CLI, "WaitTimeout done")
|
||||
}
|
||||
} else {
|
||||
WARN.Println(CLI, "Disconnect() called but not connected (disconnected/reconnecting)")
|
||||
c.setConnected(disconnected)
|
||||
@ -459,10 +499,13 @@ func (c *client) internalConnLost(err error) {
|
||||
DEBUG.Println(CLI, "internalConnLost waiting on workers")
|
||||
<-stopDone
|
||||
DEBUG.Println(CLI, "internalConnLost workers stopped")
|
||||
if c.options.CleanSession && !c.options.AutoReconnect {
|
||||
// It is possible that Disconnect was called which led to this error so reconnection depends upon status
|
||||
reconnect := c.options.AutoReconnect && c.connectionStatus() > connecting
|
||||
|
||||
if c.options.CleanSession && !reconnect {
|
||||
c.messageIds.cleanUp()
|
||||
}
|
||||
if c.options.AutoReconnect {
|
||||
if reconnect {
|
||||
c.setConnected(reconnecting)
|
||||
go c.reconnect()
|
||||
} else {
|
||||
@ -476,8 +519,8 @@ func (c *client) internalConnLost(err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// startCommsWorkers is called when the connection is up. It starts off all of the routines needed to process incoming and
|
||||
// outgoing messages.
|
||||
// startCommsWorkers is called when the connection is up.
|
||||
// It starts off all of the routines needed to process incoming and outgoing messages.
|
||||
// Returns true if the comms workers were started (i.e. they were not already running)
|
||||
func (c *client) startCommsWorkers(conn net.Conn, inboundFromStore <-chan packets.ControlPacket) bool {
|
||||
DEBUG.Println(CLI, "startCommsWorkers called")
|
||||
@ -564,7 +607,22 @@ func (c *client) startCommsWorkers(conn net.Conn, inboundFromStore <-chan packet
|
||||
commsIncomingPub = nil
|
||||
continue
|
||||
}
|
||||
incomingPubChan <- pub
|
||||
// Care is needed here because an error elsewhere could trigger a deadlock
|
||||
sendPubLoop:
|
||||
for {
|
||||
select {
|
||||
case incomingPubChan <- pub:
|
||||
break sendPubLoop
|
||||
case err, ok := <-commsErrors:
|
||||
if !ok { // commsErrors has been closed so we can ignore it
|
||||
commsErrors = nil
|
||||
continue
|
||||
}
|
||||
ERROR.Println(CLI, "Connect comms goroutine - error triggered during send Pub", err)
|
||||
c.internalConnLost(err) // no harm in calling this if the connection is already down (or shutdown is in progress)
|
||||
continue
|
||||
}
|
||||
}
|
||||
case err, ok := <-commsErrors:
|
||||
if !ok {
|
||||
commsErrors = nil
|
||||
@ -686,10 +744,10 @@ func (c *client) Publish(topic string, qos byte, retained bool, payload interfac
|
||||
// Subscribe starts a new subscription. Provide a MessageHandler to be executed when
|
||||
// a message is published on the topic provided.
|
||||
//
|
||||
// Please note: you should try to keep the execution time of the callback to be
|
||||
// as low as possible, especially when SetOrderMatters(true) (the default) is in
|
||||
// place. Blocking calls in message handlers might otherwise delay delivery to
|
||||
// other message handlers.
|
||||
// If options.OrderMatters is true (the default) then callback must not block or
|
||||
// call functions within this package that may block (e.g. Publish) other than in
|
||||
// a new go routine.
|
||||
// callback must be safe for concurrent use by multiple goroutines.
|
||||
func (c *client) Subscribe(topic string, qos byte, callback MessageHandler) Token {
|
||||
token := newToken(packets.Subscribe).(*SubscribeToken)
|
||||
DEBUG.Println(CLI, "enter Subscribe")
|
||||
@ -766,6 +824,11 @@ func (c *client) Subscribe(topic string, qos byte, callback MessageHandler) Toke
|
||||
|
||||
// SubscribeMultiple starts a new subscription for multiple topics. Provide a MessageHandler to
|
||||
// be executed when a message is published on one of the topics provided.
|
||||
//
|
||||
// If options.OrderMatters is true (the default) then callback must not block or
|
||||
// call functions within this package that may block (e.g. Publish) other than in
|
||||
// a new go routine.
|
||||
// callback must be safe for concurrent use by multiple goroutines.
|
||||
func (c *client) SubscribeMultiple(filters map[string]byte, callback MessageHandler) Token {
|
||||
var err error
|
||||
token := newToken(packets.Subscribe).(*SubscribeToken)
|
||||
@ -869,7 +932,7 @@ func (c *client) resume(subscription bool, ibound chan packets.ControlPacket) {
|
||||
}
|
||||
details := packet.Details()
|
||||
if isKeyOutbound(key) {
|
||||
switch packet.(type) {
|
||||
switch p := packet.(type) {
|
||||
case *packets.SubscribePacket:
|
||||
if subscription {
|
||||
DEBUG.Println(STR, fmt.Sprintf("loaded pending subscribe (%d)", details.MessageID))
|
||||
@ -909,13 +972,22 @@ func (c *client) resume(subscription bool, ibound chan packets.ControlPacket) {
|
||||
return
|
||||
}
|
||||
case *packets.PublishPacket:
|
||||
// spec: If the DUP flag is set to 0, it indicates that this is the first occasion that the Client or
|
||||
// Server has attempted to send this MQTT PUBLISH Packet. If the DUP flag is set to 1, it indicates that
|
||||
// this might be re-delivery of an earlier attempt to send the Packet.
|
||||
//
|
||||
// If the message is in the store than an attempt at delivery has been made (note that the message may
|
||||
// never have made it onto the wire but tracking that would be complicated!).
|
||||
if p.Qos != 0 { // spec: The DUP flag MUST be set to 0 for all QoS 0 messages
|
||||
p.Dup = true
|
||||
}
|
||||
token := newToken(packets.Publish).(*PublishToken)
|
||||
token.messageID = details.MessageID
|
||||
c.claimID(token, details.MessageID)
|
||||
DEBUG.Println(STR, fmt.Sprintf("loaded pending publish (%d)", details.MessageID))
|
||||
DEBUG.Println(STR, details)
|
||||
select {
|
||||
case c.obound <- &PacketAndToken{p: packet, t: token}:
|
||||
case c.obound <- &PacketAndToken{p: p, t: token}:
|
||||
case <-c.stop:
|
||||
DEBUG.Println(STR, "resume exiting due to stop")
|
||||
return
|
||||
|
8
vendor/github.com/eclipse/paho.mqtt.golang/go.mod
generated
vendored
8
vendor/github.com/eclipse/paho.mqtt.golang/go.mod
generated
vendored
@ -1,8 +0,0 @@
|
||||
module github.com/eclipse/paho.mqtt.golang
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0
|
||||
)
|
8
vendor/github.com/eclipse/paho.mqtt.golang/go.sum
generated
vendored
8
vendor/github.com/eclipse/paho.mqtt.golang/go.sum
generated
vendored
@ -1,8 +0,0 @@
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U=
|
||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
5
vendor/github.com/eclipse/paho.mqtt.golang/netconn.go
generated
vendored
5
vendor/github.com/eclipse/paho.mqtt.golang/netconn.go
generated
vendored
@ -30,7 +30,8 @@ import (
|
||||
// This just establishes the network connection; once established the type of connection should be irrelevant
|
||||
//
|
||||
|
||||
// openConnection opens a network connection using the protocol indicated in the URL. Does not carry out any MQTT specific handshakes
|
||||
// openConnection opens a network connection using the protocol indicated in the URL.
|
||||
// Does not carry out any MQTT specific handshakes.
|
||||
func openConnection(uri *url.URL, tlsc *tls.Config, timeout time.Duration, headers http.Header, websocketOptions *WebsocketOptions) (net.Conn, error) {
|
||||
switch uri.Scheme {
|
||||
case "ws":
|
||||
@ -81,7 +82,7 @@ func openConnection(uri *url.URL, tlsc *tls.Config, timeout time.Duration, heade
|
||||
|
||||
err = tlsConn.Handshake()
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
_ = conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
32
vendor/github.com/eclipse/paho.mqtt.golang/options.go
generated
vendored
32
vendor/github.com/eclipse/paho.mqtt.golang/options.go
generated
vendored
@ -21,7 +21,6 @@ import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -50,7 +49,11 @@ type OnConnectHandler func(Client)
|
||||
// the initial connection is lost
|
||||
type ReconnectHandler func(Client, *ClientOptions)
|
||||
|
||||
// ClientOptions contains configurable options for an Client.
|
||||
// ConnectionAttemptHandler is invoked prior to making the initial connection.
|
||||
type ConnectionAttemptHandler func(broker *url.URL, tlsCfg *tls.Config) *tls.Config
|
||||
|
||||
// ClientOptions contains configurable options for an Client. Note that these should be set using the
|
||||
// relevant methods (e.g. AddBroker) rather than directly. See those functions for information on usage.
|
||||
type ClientOptions struct {
|
||||
Servers []*url.URL
|
||||
ClientID string
|
||||
@ -79,6 +82,7 @@ type ClientOptions struct {
|
||||
OnConnect OnConnectHandler
|
||||
OnConnectionLost ConnectionLostHandler
|
||||
OnReconnecting ReconnectHandler
|
||||
OnConnectAttempt ConnectionAttemptHandler
|
||||
WriteTimeout time.Duration
|
||||
MessageChannelDepth uint
|
||||
ResumeSubs bool
|
||||
@ -90,7 +94,7 @@ type ClientOptions struct {
|
||||
// default values.
|
||||
// Port: 1883
|
||||
// CleanSession: True
|
||||
// Order: True
|
||||
// Order: True (note: it is recommended that this be set to FALSE unless order is important)
|
||||
// KeepAlive: 30 (seconds)
|
||||
// ConnectTimeout: 30 (seconds)
|
||||
// MaxReconnectInterval 10 (minutes)
|
||||
@ -120,6 +124,7 @@ func NewClientOptions() *ClientOptions {
|
||||
Store: nil,
|
||||
OnConnect: nil,
|
||||
OnConnectionLost: DefaultConnectionLostHandler,
|
||||
OnConnectAttempt: nil,
|
||||
WriteTimeout: 0, // 0 represents timeout disabled
|
||||
ResumeSubs: false,
|
||||
HTTPHeaders: make(map[string][]string),
|
||||
@ -137,14 +142,12 @@ func NewClientOptions() *ClientOptions {
|
||||
//
|
||||
// An example broker URI would look like: tcp://foobar.com:1883
|
||||
func (o *ClientOptions) AddBroker(server string) *ClientOptions {
|
||||
re := regexp.MustCompile(`%(25)?`)
|
||||
if len(server) > 0 && server[0] == ':' {
|
||||
server = "127.0.0.1" + server
|
||||
}
|
||||
if !strings.Contains(server, "://") {
|
||||
server = "tcp://" + server
|
||||
}
|
||||
server = re.ReplaceAllLiteralString(server, "%25")
|
||||
brokerURI, err := url.Parse(server)
|
||||
if err != nil {
|
||||
ERROR.Println(CLI, "Failed to parse %q broker address: %s", server, err)
|
||||
@ -206,10 +209,13 @@ func (o *ClientOptions) SetCleanSession(clean bool) *ClientOptions {
|
||||
}
|
||||
|
||||
// SetOrderMatters will set the message routing to guarantee order within
|
||||
// each QoS level. By default, this value is true. If set to false,
|
||||
// each QoS level. By default, this value is true. If set to false (recommended),
|
||||
// this flag indicates that messages can be delivered asynchronously
|
||||
// from the client to the application and possibly arrive out of order.
|
||||
// Specifically, the message handler is called in its own go routine.
|
||||
// Note that setting this to true does not guarantee in-order delivery
|
||||
// (this is subject to broker settings like "max_inflight_messages=1" in mosquitto)
|
||||
// and if true then handlers must not block.
|
||||
func (o *ClientOptions) SetOrderMatters(order bool) *ClientOptions {
|
||||
o.Order = order
|
||||
return o
|
||||
@ -289,6 +295,11 @@ func (o *ClientOptions) SetBinaryWill(topic string, payload []byte, qos byte, re
|
||||
|
||||
// SetDefaultPublishHandler sets the MessageHandler that will be called when a message
|
||||
// is received that does not match any known subscriptions.
|
||||
//
|
||||
// If OrderMatters is true (the defaultHandler) then callback must not block or
|
||||
// call functions within this package that may block (e.g. Publish) other than in
|
||||
// a new go routine.
|
||||
// defaultHandler must be safe for concurrent use by multiple goroutines.
|
||||
func (o *ClientOptions) SetDefaultPublishHandler(defaultHandler MessageHandler) *ClientOptions {
|
||||
o.DefaultPublishHandler = defaultHandler
|
||||
return o
|
||||
@ -315,6 +326,15 @@ func (o *ClientOptions) SetReconnectingHandler(cb ReconnectHandler) *ClientOptio
|
||||
return o
|
||||
}
|
||||
|
||||
// SetConnectionAttemptHandler sets the ConnectionAttemptHandler callback to be executed prior
|
||||
// to each attempt to connect to an MQTT broker. Returns the *tls.Config that will be used when establishing
|
||||
// the connection (a copy of the tls.Config from ClientOptions will be passed in along with the broker URL).
|
||||
// This allows connection specific changes to be made to the *tls.Config.
|
||||
func (o *ClientOptions) SetConnectionAttemptHandler(onConnectAttempt ConnectionAttemptHandler) *ClientOptions {
|
||||
o.OnConnectAttempt = onConnectAttempt
|
||||
return o
|
||||
}
|
||||
|
||||
// SetWriteTimeout puts a limit on how long a mqtt publish should block until it unblocks with a
|
||||
// timeout error. A duration of 0 never times out. Default never times out
|
||||
func (o *ClientOptions) SetWriteTimeout(t time.Duration) *ClientOptions {
|
||||
|
6
vendor/github.com/eclipse/paho.mqtt.golang/packets/connect.go
generated
vendored
6
vendor/github.com/eclipse/paho.mqtt.golang/packets/connect.go
generated
vendored
@ -29,7 +29,11 @@ type ConnectPacket struct {
|
||||
}
|
||||
|
||||
func (c *ConnectPacket) String() string {
|
||||
return fmt.Sprintf("%s protocolversion: %d protocolname: %s cleansession: %t willflag: %t WillQos: %d WillRetain: %t Usernameflag: %t Passwordflag: %t keepalive: %d clientId: %s willtopic: %s willmessage: %s Username: %s Password: %s", c.FixedHeader, c.ProtocolVersion, c.ProtocolName, c.CleanSession, c.WillFlag, c.WillQos, c.WillRetain, c.UsernameFlag, c.PasswordFlag, c.Keepalive, c.ClientIdentifier, c.WillTopic, c.WillMessage, c.Username, c.Password)
|
||||
var password string
|
||||
if len(c.Password) > 0 {
|
||||
password = "<redacted>"
|
||||
}
|
||||
return fmt.Sprintf("%s protocolversion: %d protocolname: %s cleansession: %t willflag: %t WillQos: %d WillRetain: %t Usernameflag: %t Passwordflag: %t keepalive: %d clientId: %s willtopic: %s willmessage: %s Username: %s Password: %s", c.FixedHeader, c.ProtocolVersion, c.ProtocolName, c.CleanSession, c.WillFlag, c.WillQos, c.WillRetain, c.UsernameFlag, c.PasswordFlag, c.Keepalive, c.ClientIdentifier, c.WillTopic, c.WillMessage, c.Username, password)
|
||||
}
|
||||
|
||||
func (c *ConnectPacket) Write(w io.Writer) error {
|
||||
|
24
vendor/github.com/eclipse/paho.mqtt.golang/packets/packets.go
generated
vendored
24
vendor/github.com/eclipse/paho.mqtt.golang/packets/packets.go
generated
vendored
@ -81,17 +81,27 @@ var ConnackReturnCodes = map[uint8]string{
|
||||
255: "Connection Refused: Protocol Violation",
|
||||
}
|
||||
|
||||
var (
|
||||
ErrorRefusedBadProtocolVersion = errors.New("unacceptable protocol version")
|
||||
ErrorRefusedIDRejected = errors.New("identifier rejected")
|
||||
ErrorRefusedServerUnavailable = errors.New("server Unavailable")
|
||||
ErrorRefusedBadUsernameOrPassword = errors.New("bad user name or password")
|
||||
ErrorRefusedNotAuthorised = errors.New("not Authorized")
|
||||
ErrorNetworkError = errors.New("network Error")
|
||||
ErrorProtocolViolation = errors.New("protocol Violation")
|
||||
)
|
||||
|
||||
// ConnErrors is a map of the errors codes constants for Connect()
|
||||
// to a Go error
|
||||
var ConnErrors = map[byte]error{
|
||||
Accepted: nil,
|
||||
ErrRefusedBadProtocolVersion: errors.New("unacceptable protocol version"),
|
||||
ErrRefusedIDRejected: errors.New("identifier rejected"),
|
||||
ErrRefusedServerUnavailable: errors.New("server Unavailable"),
|
||||
ErrRefusedBadUsernameOrPassword: errors.New("bad user name or password"),
|
||||
ErrRefusedNotAuthorised: errors.New("not Authorized"),
|
||||
ErrNetworkError: errors.New("network Error"),
|
||||
ErrProtocolViolation: errors.New("protocol Violation"),
|
||||
ErrRefusedBadProtocolVersion: ErrorRefusedBadProtocolVersion,
|
||||
ErrRefusedIDRejected: ErrorRefusedIDRejected,
|
||||
ErrRefusedServerUnavailable: ErrorRefusedServerUnavailable,
|
||||
ErrRefusedBadUsernameOrPassword: ErrorRefusedBadUsernameOrPassword,
|
||||
ErrRefusedNotAuthorised: ErrorRefusedNotAuthorised,
|
||||
ErrNetworkError: ErrorNetworkError,
|
||||
ErrProtocolViolation: ErrorProtocolViolation,
|
||||
}
|
||||
|
||||
// ReadPacket takes an instance of an io.Reader (such as net.Conn) and attempts
|
||||
|
57
vendor/github.com/eclipse/paho.mqtt.golang/router.go
generated
vendored
57
vendor/github.com/eclipse/paho.mqtt.golang/router.go
generated
vendored
@ -132,13 +132,46 @@ func (r *router) setDefaultHandler(handler MessageHandler) {
|
||||
// associated callback (or the defaultHandler, if one exists and no other route matched). If
|
||||
// anything is sent down the stop channel the function will end.
|
||||
func (r *router) matchAndDispatch(messages <-chan *packets.PublishPacket, order bool, client *client) <-chan *PacketAndToken {
|
||||
ackChan := make(chan *PacketAndToken)
|
||||
go func() {
|
||||
var wg sync.WaitGroup
|
||||
ackOutChan := make(chan *PacketAndToken) // Channel returned to caller; closed when messages channel closed
|
||||
var ackInChan chan *PacketAndToken // ACKs generated by ackFunc get put onto this channel
|
||||
|
||||
stopAckCopy := make(chan struct{}) // Closure requests stop of go routine copying ackInChan to ackOutChan
|
||||
ackCopyStopped := make(chan struct{}) // Closure indicates that it is safe to close ackOutChan
|
||||
goRoutinesDone := make(chan struct{}) // closed on wg.Done()
|
||||
if order {
|
||||
ackInChan = ackOutChan // When order = true no go routines are used so safe to use one channel and close when done
|
||||
} else {
|
||||
// When order = false ACK messages are sent in go routines so ackInChan cannot be closed until all goroutines done
|
||||
ackInChan = make(chan *PacketAndToken)
|
||||
go func() { // go routine to copy from ackInChan to ackOutChan until stopped
|
||||
for {
|
||||
select {
|
||||
case a := <-ackInChan:
|
||||
ackOutChan <- a
|
||||
case <-stopAckCopy:
|
||||
close(ackCopyStopped) // Signal main go routine that it is safe to close ackOutChan
|
||||
for {
|
||||
select {
|
||||
case <-ackInChan: // drain ackInChan to ensure all goRoutines can complete cleanly (ACK dropped)
|
||||
DEBUG.Println(ROU, "matchAndDispatch received acknowledgment after processing stopped (ACK dropped).")
|
||||
case <-goRoutinesDone:
|
||||
close(ackInChan) // Nothing further should be sent (a panic is probably better than silent failure)
|
||||
DEBUG.Println(ROU, "matchAndDispatch order=false copy goroutine exiting.")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
go func() { // Main go routine handling inbound messages
|
||||
for message := range messages {
|
||||
// DEBUG.Println(ROU, "matchAndDispatch received message")
|
||||
sent := false
|
||||
r.RLock()
|
||||
m := messageFromPublish(message, ackFunc(ackChan, client.persist, message))
|
||||
m := messageFromPublish(message, ackFunc(ackInChan, client.persist, message))
|
||||
var handlers []MessageHandler
|
||||
for e := r.routes.Front(); e != nil; e = e.Next() {
|
||||
if e.Value.(*route).match(message.TopicName) {
|
||||
@ -146,9 +179,11 @@ func (r *router) matchAndDispatch(messages <-chan *packets.PublishPacket, order
|
||||
handlers = append(handlers, e.Value.(*route).callback)
|
||||
} else {
|
||||
hd := e.Value.(*route).callback
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
hd(client, m)
|
||||
m.Ack()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
sent = true
|
||||
@ -159,9 +194,11 @@ func (r *router) matchAndDispatch(messages <-chan *packets.PublishPacket, order
|
||||
if order {
|
||||
handlers = append(handlers, r.defaultHandler)
|
||||
} else {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
r.defaultHandler(client, m)
|
||||
m.Ack()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
} else {
|
||||
@ -175,8 +212,18 @@ func (r *router) matchAndDispatch(messages <-chan *packets.PublishPacket, order
|
||||
}
|
||||
// DEBUG.Println(ROU, "matchAndDispatch handled message")
|
||||
}
|
||||
close(ackChan)
|
||||
if order {
|
||||
close(ackOutChan)
|
||||
} else { // Ensure that nothing further will be written to ackOutChan before closing it
|
||||
close(stopAckCopy)
|
||||
<-ackCopyStopped
|
||||
close(ackOutChan)
|
||||
go func() {
|
||||
wg.Wait() // Note: If this remains running then the user has handlers that are not returning
|
||||
close(goRoutinesDone)
|
||||
}()
|
||||
}
|
||||
DEBUG.Println(ROU, "matchAndDispatch exiting")
|
||||
}()
|
||||
return ackChan
|
||||
return ackOutChan
|
||||
}
|
||||
|
16
vendor/github.com/eclipse/paho.mqtt.golang/websocket.go
generated
vendored
16
vendor/github.com/eclipse/paho.mqtt.golang/websocket.go
generated
vendored
@ -2,9 +2,11 @@ package mqtt
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -15,8 +17,11 @@ import (
|
||||
type WebsocketOptions struct {
|
||||
ReadBufferSize int
|
||||
WriteBufferSize int
|
||||
Proxy ProxyFunction
|
||||
}
|
||||
|
||||
type ProxyFunction func(req *http.Request) (*url.URL, error)
|
||||
|
||||
// NewWebsocket returns a new websocket and returns a net.Conn compatible interface using the gorilla/websocket package
|
||||
func NewWebsocket(host string, tlsc *tls.Config, timeout time.Duration, requestHeader http.Header, options *WebsocketOptions) (net.Conn, error) {
|
||||
if timeout == 0 {
|
||||
@ -27,9 +32,11 @@ func NewWebsocket(host string, tlsc *tls.Config, timeout time.Duration, requestH
|
||||
// Apply default options
|
||||
options = &WebsocketOptions{}
|
||||
}
|
||||
|
||||
if options.Proxy == nil {
|
||||
options.Proxy = http.ProxyFromEnvironment
|
||||
}
|
||||
dialer := &websocket.Dialer{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
Proxy: options.Proxy,
|
||||
HandshakeTimeout: timeout,
|
||||
EnableCompression: false,
|
||||
TLSClientConfig: tlsc,
|
||||
@ -38,9 +45,12 @@ func NewWebsocket(host string, tlsc *tls.Config, timeout time.Duration, requestH
|
||||
WriteBufferSize: options.WriteBufferSize,
|
||||
}
|
||||
|
||||
ws, _, err := dialer.Dial(host, requestHeader)
|
||||
ws, resp, err := dialer.Dial(host, requestHeader)
|
||||
|
||||
if err != nil {
|
||||
if resp != nil {
|
||||
WARN.Println(CLI, fmt.Sprintf("Websocket handshake failure. StatusCode: %d. Body: %s", resp.StatusCode, resp.Body))
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
10
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
10
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
@ -13,6 +13,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
@ -62,14 +63,7 @@ func FileDescriptor(s filePath) fileDescGZIP {
|
||||
// Find the descriptor in the v2 registry.
|
||||
var b []byte
|
||||
if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil {
|
||||
if fd, ok := fd.(interface{ ProtoLegacyRawDesc() []byte }); ok {
|
||||
b = fd.ProtoLegacyRawDesc()
|
||||
} else {
|
||||
// TODO: Use protodesc.ToFileDescriptorProto to construct
|
||||
// a descriptorpb.FileDescriptorProto and marshal it.
|
||||
// However, doing so causes the proto package to have a dependency
|
||||
// on descriptorpb, leading to cyclic dependency issues.
|
||||
}
|
||||
b, _ = Marshal(protodesc.ToFileDescriptorProto(fd))
|
||||
}
|
||||
|
||||
// Locally cache the raw descriptor form for the file.
|
||||
|
3
vendor/github.com/gorilla/websocket/go.mod
generated
vendored
3
vendor/github.com/gorilla/websocket/go.mod
generated
vendored
@ -1,3 +0,0 @@
|
||||
module github.com/gorilla/websocket
|
||||
|
||||
go 1.12
|
0
vendor/github.com/gorilla/websocket/go.sum
generated
vendored
0
vendor/github.com/gorilla/websocket/go.sum
generated
vendored
14
vendor/github.com/sirupsen/logrus/.travis.yml
generated
vendored
14
vendor/github.com/sirupsen/logrus/.travis.yml
generated
vendored
@ -4,14 +4,12 @@ git:
|
||||
depth: 1
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
go: [1.13.x, 1.14.x]
|
||||
os: [linux, osx]
|
||||
go: 1.15.x
|
||||
os: linux
|
||||
install:
|
||||
- ./travis/install.sh
|
||||
script:
|
||||
- ./travis/cross_build.sh
|
||||
- ./travis/lint.sh
|
||||
- export GOMAXPROCS=4
|
||||
- export GORACE=halt_on_error=1
|
||||
- go test -race -v ./...
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then go test -race -v -tags appengine ./... ; fi
|
||||
- cd ci
|
||||
- go run mage.go -v -w ../ crossBuild
|
||||
- go run mage.go -v -w ../ lint
|
||||
- go run mage.go -v -w ../ test
|
||||
|
36
vendor/github.com/sirupsen/logrus/CHANGELOG.md
generated
vendored
36
vendor/github.com/sirupsen/logrus/CHANGELOG.md
generated
vendored
@ -1,3 +1,39 @@
|
||||
# 1.8.1
|
||||
Code quality:
|
||||
* move magefile in its own subdir/submodule to remove magefile dependency on logrus consumer
|
||||
* improve timestamp format documentation
|
||||
|
||||
Fixes:
|
||||
* fix race condition on logger hooks
|
||||
|
||||
|
||||
# 1.8.0
|
||||
|
||||
Correct versioning number replacing v1.7.1.
|
||||
|
||||
# 1.7.1
|
||||
|
||||
Beware this release has introduced a new public API and its semver is therefore incorrect.
|
||||
|
||||
Code quality:
|
||||
* use go 1.15 in travis
|
||||
* use magefile as task runner
|
||||
|
||||
Fixes:
|
||||
* small fixes about new go 1.13 error formatting system
|
||||
* Fix for long time race condiction with mutating data hooks
|
||||
|
||||
Features:
|
||||
* build support for zos
|
||||
|
||||
# 1.7.0
|
||||
Fixes:
|
||||
* the dependency toward a windows terminal library has been removed
|
||||
|
||||
Features:
|
||||
* a new buffer pool management API has been added
|
||||
* a set of `<LogLevel>Fn()` functions have been added
|
||||
|
||||
# 1.6.0
|
||||
Fixes:
|
||||
* end of line cleanup
|
||||
|
2
vendor/github.com/sirupsen/logrus/README.md
generated
vendored
2
vendor/github.com/sirupsen/logrus/README.md
generated
vendored
@ -402,7 +402,7 @@ func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) {
|
||||
// source of the official loggers.
|
||||
serialized, err := json.Marshal(entry.Data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
|
||||
return nil, fmt.Errorf("Failed to marshal fields to JSON, %w", err)
|
||||
}
|
||||
return append(serialized, '\n'), nil
|
||||
}
|
||||
|
75
vendor/github.com/sirupsen/logrus/entry.go
generated
vendored
75
vendor/github.com/sirupsen/logrus/entry.go
generated
vendored
@ -78,6 +78,14 @@ func NewEntry(logger *Logger) *Entry {
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Dup() *Entry {
|
||||
data := make(Fields, len(entry.Data))
|
||||
for k, v := range entry.Data {
|
||||
data[k] = v
|
||||
}
|
||||
return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, Context: entry.Context, err: entry.err}
|
||||
}
|
||||
|
||||
// Returns the bytes representation of this entry from the formatter.
|
||||
func (entry *Entry) Bytes() ([]byte, error) {
|
||||
return entry.Logger.Formatter.Format(entry)
|
||||
@ -123,11 +131,9 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
|
||||
for k, v := range fields {
|
||||
isErrField := false
|
||||
if t := reflect.TypeOf(v); t != nil {
|
||||
switch t.Kind() {
|
||||
case reflect.Func:
|
||||
switch {
|
||||
case t.Kind() == reflect.Func, t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Func:
|
||||
isErrField = true
|
||||
case reflect.Ptr:
|
||||
isErrField = t.Elem().Kind() == reflect.Func
|
||||
}
|
||||
}
|
||||
if isErrField {
|
||||
@ -212,68 +218,72 @@ func (entry Entry) HasCaller() (has bool) {
|
||||
entry.Caller != nil
|
||||
}
|
||||
|
||||
// This function is not declared with a pointer value because otherwise
|
||||
// race conditions will occur when using multiple goroutines
|
||||
func (entry Entry) log(level Level, msg string) {
|
||||
func (entry *Entry) log(level Level, msg string) {
|
||||
var buffer *bytes.Buffer
|
||||
|
||||
// Default to now, but allow users to override if they want.
|
||||
//
|
||||
// We don't have to worry about polluting future calls to Entry#log()
|
||||
// with this assignment because this function is declared with a
|
||||
// non-pointer receiver.
|
||||
if entry.Time.IsZero() {
|
||||
entry.Time = time.Now()
|
||||
newEntry := entry.Dup()
|
||||
|
||||
if newEntry.Time.IsZero() {
|
||||
newEntry.Time = time.Now()
|
||||
}
|
||||
|
||||
entry.Level = level
|
||||
entry.Message = msg
|
||||
entry.Logger.mu.Lock()
|
||||
if entry.Logger.ReportCaller {
|
||||
entry.Caller = getCaller()
|
||||
}
|
||||
entry.Logger.mu.Unlock()
|
||||
newEntry.Level = level
|
||||
newEntry.Message = msg
|
||||
|
||||
entry.fireHooks()
|
||||
newEntry.Logger.mu.Lock()
|
||||
reportCaller := newEntry.Logger.ReportCaller
|
||||
newEntry.Logger.mu.Unlock()
|
||||
|
||||
if reportCaller {
|
||||
newEntry.Caller = getCaller()
|
||||
}
|
||||
|
||||
newEntry.fireHooks()
|
||||
|
||||
buffer = getBuffer()
|
||||
defer func() {
|
||||
entry.Buffer = nil
|
||||
newEntry.Buffer = nil
|
||||
putBuffer(buffer)
|
||||
}()
|
||||
buffer.Reset()
|
||||
entry.Buffer = buffer
|
||||
newEntry.Buffer = buffer
|
||||
|
||||
entry.write()
|
||||
newEntry.write()
|
||||
|
||||
entry.Buffer = nil
|
||||
newEntry.Buffer = nil
|
||||
|
||||
// To avoid Entry#log() returning a value that only would make sense for
|
||||
// panic() to use in Entry#Panic(), we avoid the allocation by checking
|
||||
// directly here.
|
||||
if level <= PanicLevel {
|
||||
panic(&entry)
|
||||
panic(newEntry)
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) fireHooks() {
|
||||
var tmpHooks LevelHooks
|
||||
entry.Logger.mu.Lock()
|
||||
defer entry.Logger.mu.Unlock()
|
||||
err := entry.Logger.Hooks.Fire(entry.Level, entry)
|
||||
tmpHooks = make(LevelHooks, len(entry.Logger.Hooks))
|
||||
for k, v := range entry.Logger.Hooks {
|
||||
tmpHooks[k] = v
|
||||
}
|
||||
entry.Logger.mu.Unlock()
|
||||
|
||||
err := tmpHooks.Fire(entry.Level, entry)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) write() {
|
||||
entry.Logger.mu.Lock()
|
||||
defer entry.Logger.mu.Unlock()
|
||||
serialized, err := entry.Logger.Formatter.Format(entry)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
|
||||
return
|
||||
}
|
||||
if _, err = entry.Logger.Out.Write(serialized); err != nil {
|
||||
entry.Logger.mu.Lock()
|
||||
defer entry.Logger.mu.Unlock()
|
||||
if _, err := entry.Logger.Out.Write(serialized); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
|
||||
}
|
||||
}
|
||||
@ -319,7 +329,6 @@ func (entry *Entry) Fatal(args ...interface{}) {
|
||||
|
||||
func (entry *Entry) Panic(args ...interface{}) {
|
||||
entry.Log(PanicLevel, args...)
|
||||
panic(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// Entry Printf family functions
|
||||
|
10
vendor/github.com/sirupsen/logrus/go.mod
generated
vendored
10
vendor/github.com/sirupsen/logrus/go.mod
generated
vendored
@ -1,10 +0,0 @@
|
||||
module github.com/sirupsen/logrus
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/testify v1.2.2
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037
|
||||
)
|
||||
|
||||
go 1.13
|
10
vendor/github.com/sirupsen/logrus/go.sum
generated
vendored
10
vendor/github.com/sirupsen/logrus/go.sum
generated
vendored
@ -1,10 +0,0 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
5
vendor/github.com/sirupsen/logrus/json_formatter.go
generated
vendored
5
vendor/github.com/sirupsen/logrus/json_formatter.go
generated
vendored
@ -23,6 +23,9 @@ func (f FieldMap) resolve(key fieldKey) string {
|
||||
// JSONFormatter formats logs into parsable json
|
||||
type JSONFormatter struct {
|
||||
// TimestampFormat sets the format used for marshaling timestamps.
|
||||
// The format to use is the same than for time.Format or time.Parse from the standard
|
||||
// library.
|
||||
// The standard Library already provides a set of predefined format.
|
||||
TimestampFormat string
|
||||
|
||||
// DisableTimestamp allows disabling automatic timestamps in output
|
||||
@ -118,7 +121,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
||||
encoder.SetIndent("", " ")
|
||||
}
|
||||
if err := encoder.Encode(data); err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err)
|
||||
return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err)
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
|
2
vendor/github.com/sirupsen/logrus/logger.go
generated
vendored
2
vendor/github.com/sirupsen/logrus/logger.go
generated
vendored
@ -12,7 +12,7 @@ import (
|
||||
// LogFunction For big messages, it can be more efficient to pass a function
|
||||
// and only call it if the log level is actually enables rather than
|
||||
// generating the log message and then checking if the level is enabled
|
||||
type LogFunction func()[]interface{}
|
||||
type LogFunction func() []interface{}
|
||||
|
||||
type Logger struct {
|
||||
// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
|
||||
|
2
vendor/github.com/sirupsen/logrus/terminal_check_unix.go
generated
vendored
2
vendor/github.com/sirupsen/logrus/terminal_check_unix.go
generated
vendored
@ -1,4 +1,4 @@
|
||||
// +build linux aix
|
||||
// +build linux aix zos
|
||||
// +build !js
|
||||
|
||||
package logrus
|
||||
|
7
vendor/github.com/sirupsen/logrus/text_formatter.go
generated
vendored
7
vendor/github.com/sirupsen/logrus/text_formatter.go
generated
vendored
@ -53,7 +53,10 @@ type TextFormatter struct {
|
||||
// the time passed since beginning of execution.
|
||||
FullTimestamp bool
|
||||
|
||||
// TimestampFormat to use for display when a full timestamp is printed
|
||||
// TimestampFormat to use for display when a full timestamp is printed.
|
||||
// The format to use is the same than for time.Format or time.Parse from the standard
|
||||
// library.
|
||||
// The standard Library already provides a set of predefined format.
|
||||
TimestampFormat string
|
||||
|
||||
// The fields are sorted by default for a consistent output. For applications
|
||||
@ -235,6 +238,8 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
|
||||
levelColor = yellow
|
||||
case ErrorLevel, FatalLevel, PanicLevel:
|
||||
levelColor = red
|
||||
case InfoLevel:
|
||||
levelColor = blue
|
||||
default:
|
||||
levelColor = blue
|
||||
}
|
||||
|
19
vendor/go.uber.org/atomic/.codecov.yml
generated
vendored
Normal file
19
vendor/go.uber.org/atomic/.codecov.yml
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
coverage:
|
||||
range: 80..100
|
||||
round: down
|
||||
precision: 2
|
||||
|
||||
status:
|
||||
project: # measuring the overall project coverage
|
||||
default: # context, you can create multiple ones with custom titles
|
||||
enabled: yes # must be yes|true to enable this status
|
||||
target: 100 # specify the target coverage for each commit status
|
||||
# option: "auto" (must increase from parent commit or pull request base)
|
||||
# option: "X%" a static target percentage to hit
|
||||
if_not_found: success # if parent is not found report status as success, error, or failure
|
||||
if_ci_failed: error # if ci fails report status as success, error, or failure
|
||||
|
||||
# Also update COVER_IGNORE_PKGS in the Makefile.
|
||||
ignore:
|
||||
- /internal/gen-atomicint/
|
||||
- /internal/gen-valuewrapper/
|
12
vendor/go.uber.org/atomic/.gitignore
generated
vendored
Normal file
12
vendor/go.uber.org/atomic/.gitignore
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/bin
|
||||
.DS_Store
|
||||
/vendor
|
||||
cover.html
|
||||
cover.out
|
||||
lint.log
|
||||
|
||||
# Binaries
|
||||
*.test
|
||||
|
||||
# Profiling output
|
||||
*.prof
|
27
vendor/go.uber.org/atomic/.travis.yml
generated
vendored
Normal file
27
vendor/go.uber.org/atomic/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go_import_path: go.uber.org/atomic
|
||||
|
||||
env:
|
||||
global:
|
||||
- GO111MODULE=on
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- go: oldstable
|
||||
- go: stable
|
||||
env: LINT=1
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- vendor
|
||||
|
||||
before_install:
|
||||
- go version
|
||||
|
||||
script:
|
||||
- test -z "$LINT" || make lint
|
||||
- make cover
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
76
vendor/go.uber.org/atomic/CHANGELOG.md
generated
vendored
Normal file
76
vendor/go.uber.org/atomic/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.7.0] - 2020-09-14
|
||||
### Added
|
||||
- Support JSON serialization and deserialization of primitive atomic types.
|
||||
- Support Text marshalling and unmarshalling for string atomics.
|
||||
|
||||
### Changed
|
||||
- Disallow incorrect comparison of atomic values in a non-atomic way.
|
||||
|
||||
### Removed
|
||||
- Remove dependency on `golang.org/x/{lint, tools}`.
|
||||
|
||||
## [1.6.0] - 2020-02-24
|
||||
### Changed
|
||||
- Drop library dependency on `golang.org/x/{lint, tools}`.
|
||||
|
||||
## [1.5.1] - 2019-11-19
|
||||
- Fix bug where `Bool.CAS` and `Bool.Toggle` do work correctly together
|
||||
causing `CAS` to fail even though the old value matches.
|
||||
|
||||
## [1.5.0] - 2019-10-29
|
||||
### Changed
|
||||
- With Go modules, only the `go.uber.org/atomic` import path is supported now.
|
||||
If you need to use the old import path, please add a `replace` directive to
|
||||
your `go.mod`.
|
||||
|
||||
## [1.4.0] - 2019-05-01
|
||||
### Added
|
||||
- Add `atomic.Error` type for atomic operations on `error` values.
|
||||
|
||||
## [1.3.2] - 2018-05-02
|
||||
### Added
|
||||
- Add `atomic.Duration` type for atomic operations on `time.Duration` values.
|
||||
|
||||
## [1.3.1] - 2017-11-14
|
||||
### Fixed
|
||||
- Revert optimization for `atomic.String.Store("")` which caused data races.
|
||||
|
||||
## [1.3.0] - 2017-11-13
|
||||
### Added
|
||||
- Add `atomic.Bool.CAS` for compare-and-swap semantics on bools.
|
||||
|
||||
### Changed
|
||||
- Optimize `atomic.String.Store("")` by avoiding an allocation.
|
||||
|
||||
## [1.2.0] - 2017-04-12
|
||||
### Added
|
||||
- Shadow `atomic.Value` from `sync/atomic`.
|
||||
|
||||
## [1.1.0] - 2017-03-10
|
||||
### Added
|
||||
- Add atomic `Float64` type.
|
||||
|
||||
### Changed
|
||||
- Support new `go.uber.org/atomic` import path.
|
||||
|
||||
## [1.0.0] - 2016-07-18
|
||||
|
||||
- Initial release.
|
||||
|
||||
[1.7.0]: https://github.com/uber-go/atomic/compare/v1.6.0...v1.7.0
|
||||
[1.6.0]: https://github.com/uber-go/atomic/compare/v1.5.1...v1.6.0
|
||||
[1.5.1]: https://github.com/uber-go/atomic/compare/v1.5.0...v1.5.1
|
||||
[1.5.0]: https://github.com/uber-go/atomic/compare/v1.4.0...v1.5.0
|
||||
[1.4.0]: https://github.com/uber-go/atomic/compare/v1.3.2...v1.4.0
|
||||
[1.3.2]: https://github.com/uber-go/atomic/compare/v1.3.1...v1.3.2
|
||||
[1.3.1]: https://github.com/uber-go/atomic/compare/v1.3.0...v1.3.1
|
||||
[1.3.0]: https://github.com/uber-go/atomic/compare/v1.2.0...v1.3.0
|
||||
[1.2.0]: https://github.com/uber-go/atomic/compare/v1.1.0...v1.2.0
|
||||
[1.1.0]: https://github.com/uber-go/atomic/compare/v1.0.0...v1.1.0
|
||||
[1.0.0]: https://github.com/uber-go/atomic/releases/tag/v1.0.0
|
19
vendor/go.uber.org/atomic/LICENSE.txt
generated
vendored
Normal file
19
vendor/go.uber.org/atomic/LICENSE.txt
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
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.
|
78
vendor/go.uber.org/atomic/Makefile
generated
vendored
Normal file
78
vendor/go.uber.org/atomic/Makefile
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
# Directory to place `go install`ed binaries into.
|
||||
export GOBIN ?= $(shell pwd)/bin
|
||||
|
||||
GOLINT = $(GOBIN)/golint
|
||||
GEN_ATOMICINT = $(GOBIN)/gen-atomicint
|
||||
GEN_ATOMICWRAPPER = $(GOBIN)/gen-atomicwrapper
|
||||
STATICCHECK = $(GOBIN)/staticcheck
|
||||
|
||||
GO_FILES ?= $(shell find . '(' -path .git -o -path vendor ')' -prune -o -name '*.go' -print)
|
||||
|
||||
# Also update ignore section in .codecov.yml.
|
||||
COVER_IGNORE_PKGS = \
|
||||
go.uber.org/atomic/internal/gen-atomicint \
|
||||
go.uber.org/atomic/internal/gen-atomicwrapper
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
go build ./...
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -race ./...
|
||||
|
||||
.PHONY: gofmt
|
||||
gofmt:
|
||||
$(eval FMT_LOG := $(shell mktemp -t gofmt.XXXXX))
|
||||
gofmt -e -s -l $(GO_FILES) > $(FMT_LOG) || true
|
||||
@[ ! -s "$(FMT_LOG)" ] || (echo "gofmt failed:" && cat $(FMT_LOG) && false)
|
||||
|
||||
$(GOLINT):
|
||||
cd tools && go install golang.org/x/lint/golint
|
||||
|
||||
$(STATICCHECK):
|
||||
cd tools && go install honnef.co/go/tools/cmd/staticcheck
|
||||
|
||||
$(GEN_ATOMICWRAPPER): $(wildcard ./internal/gen-atomicwrapper/*)
|
||||
go build -o $@ ./internal/gen-atomicwrapper
|
||||
|
||||
$(GEN_ATOMICINT): $(wildcard ./internal/gen-atomicint/*)
|
||||
go build -o $@ ./internal/gen-atomicint
|
||||
|
||||
.PHONY: golint
|
||||
golint: $(GOLINT)
|
||||
$(GOLINT) ./...
|
||||
|
||||
.PHONY: staticcheck
|
||||
staticcheck: $(STATICCHECK)
|
||||
$(STATICCHECK) ./...
|
||||
|
||||
.PHONY: lint
|
||||
lint: gofmt golint staticcheck generatenodirty
|
||||
|
||||
# comma separated list of packages to consider for code coverage.
|
||||
COVER_PKG = $(shell \
|
||||
go list -find ./... | \
|
||||
grep -v $(foreach pkg,$(COVER_IGNORE_PKGS),-e "^$(pkg)$$") | \
|
||||
paste -sd, -)
|
||||
|
||||
.PHONY: cover
|
||||
cover:
|
||||
go test -coverprofile=cover.out -coverpkg $(COVER_PKG) -v ./...
|
||||
go tool cover -html=cover.out -o cover.html
|
||||
|
||||
.PHONY: generate
|
||||
generate: $(GEN_ATOMICINT) $(GEN_ATOMICWRAPPER)
|
||||
go generate ./...
|
||||
|
||||
.PHONY: generatenodirty
|
||||
generatenodirty:
|
||||
@[ -z "$$(git status --porcelain)" ] || ( \
|
||||
echo "Working tree is dirty. Commit your changes first."; \
|
||||
exit 1 )
|
||||
@make generate
|
||||
@status=$$(git status --porcelain); \
|
||||
[ -z "$$status" ] || ( \
|
||||
echo "Working tree is dirty after `make generate`:"; \
|
||||
echo "$$status"; \
|
||||
echo "Please ensure that the generated code is up-to-date." )
|
63
vendor/go.uber.org/atomic/README.md
generated
vendored
Normal file
63
vendor/go.uber.org/atomic/README.md
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
# atomic [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![Go Report Card][reportcard-img]][reportcard]
|
||||
|
||||
Simple wrappers for primitive types to enforce atomic access.
|
||||
|
||||
## Installation
|
||||
|
||||
```shell
|
||||
$ go get -u go.uber.org/atomic@v1
|
||||
```
|
||||
|
||||
### Legacy Import Path
|
||||
|
||||
As of v1.5.0, the import path `go.uber.org/atomic` is the only supported way
|
||||
of using this package. If you are using Go modules, this package will fail to
|
||||
compile with the legacy import path path `github.com/uber-go/atomic`.
|
||||
|
||||
We recommend migrating your code to the new import path but if you're unable
|
||||
to do so, or if your dependencies are still using the old import path, you
|
||||
will have to add a `replace` directive to your `go.mod` file downgrading the
|
||||
legacy import path to an older version.
|
||||
|
||||
```
|
||||
replace github.com/uber-go/atomic => github.com/uber-go/atomic v1.4.0
|
||||
```
|
||||
|
||||
You can do so automatically by running the following command.
|
||||
|
||||
```shell
|
||||
$ go mod edit -replace github.com/uber-go/atomic=github.com/uber-go/atomic@v1.4.0
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
The standard library's `sync/atomic` is powerful, but it's easy to forget which
|
||||
variables must be accessed atomically. `go.uber.org/atomic` preserves all the
|
||||
functionality of the standard library, but wraps the primitive types to
|
||||
provide a safer, more convenient API.
|
||||
|
||||
```go
|
||||
var atom atomic.Uint32
|
||||
atom.Store(42)
|
||||
atom.Sub(2)
|
||||
atom.CAS(40, 11)
|
||||
```
|
||||
|
||||
See the [documentation][doc] for a complete API specification.
|
||||
|
||||
## Development Status
|
||||
|
||||
Stable.
|
||||
|
||||
---
|
||||
|
||||
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.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
|
||||
[reportcard]: https://goreportcard.com/report/go.uber.org/atomic
|
81
vendor/go.uber.org/atomic/bool.go
generated
vendored
Normal file
81
vendor/go.uber.org/atomic/bool.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
// @generated Code generated by gen-atomicwrapper.
|
||||
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// Bool is an atomic type-safe wrapper for bool values.
|
||||
type Bool struct {
|
||||
_ nocmp // disallow non-atomic comparison
|
||||
|
||||
v Uint32
|
||||
}
|
||||
|
||||
var _zeroBool bool
|
||||
|
||||
// NewBool creates a new Bool.
|
||||
func NewBool(v bool) *Bool {
|
||||
x := &Bool{}
|
||||
if v != _zeroBool {
|
||||
x.Store(v)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// Load atomically loads the wrapped bool.
|
||||
func (x *Bool) Load() bool {
|
||||
return truthy(x.v.Load())
|
||||
}
|
||||
|
||||
// Store atomically stores the passed bool.
|
||||
func (x *Bool) Store(v bool) {
|
||||
x.v.Store(boolToInt(v))
|
||||
}
|
||||
|
||||
// CAS is an atomic compare-and-swap for bool values.
|
||||
func (x *Bool) CAS(o, n bool) bool {
|
||||
return x.v.CAS(boolToInt(o), boolToInt(n))
|
||||
}
|
||||
|
||||
// Swap atomically stores the given bool and returns the old
|
||||
// value.
|
||||
func (x *Bool) Swap(o bool) bool {
|
||||
return truthy(x.v.Swap(boolToInt(o)))
|
||||
}
|
||||
|
||||
// MarshalJSON encodes the wrapped bool into JSON.
|
||||
func (x *Bool) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(x.Load())
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes a bool from JSON.
|
||||
func (x *Bool) UnmarshalJSON(b []byte) error {
|
||||
var v bool
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
x.Store(v)
|
||||
return nil
|
||||
}
|
53
vendor/go.uber.org/atomic/bool_ext.go
generated
vendored
Normal file
53
vendor/go.uber.org/atomic/bool_ext.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
//go:generate bin/gen-atomicwrapper -name=Bool -type=bool -wrapped=Uint32 -pack=boolToInt -unpack=truthy -cas -swap -json -file=bool.go
|
||||
|
||||
func truthy(n uint32) bool {
|
||||
return n == 1
|
||||
}
|
||||
|
||||
func boolToInt(b bool) uint32 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Toggle atomically negates the Boolean and returns the previous value.
|
||||
func (b *Bool) Toggle() bool {
|
||||
for {
|
||||
old := b.Load()
|
||||
if b.CAS(old, !old) {
|
||||
return old
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// String encodes the wrapped value as a string.
|
||||
func (b *Bool) String() string {
|
||||
return strconv.FormatBool(b.Load())
|
||||
}
|
23
vendor/go.uber.org/atomic/doc.go
generated
vendored
Normal file
23
vendor/go.uber.org/atomic/doc.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2020 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 provides simple wrappers around numerics to enforce atomic
|
||||
// access.
|
||||
package atomic
|
82
vendor/go.uber.org/atomic/duration.go
generated
vendored
Normal file
82
vendor/go.uber.org/atomic/duration.go
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
// @generated Code generated by gen-atomicwrapper.
|
||||
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Duration is an atomic type-safe wrapper for time.Duration values.
|
||||
type Duration struct {
|
||||
_ nocmp // disallow non-atomic comparison
|
||||
|
||||
v Int64
|
||||
}
|
||||
|
||||
var _zeroDuration time.Duration
|
||||
|
||||
// NewDuration creates a new Duration.
|
||||
func NewDuration(v time.Duration) *Duration {
|
||||
x := &Duration{}
|
||||
if v != _zeroDuration {
|
||||
x.Store(v)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// Load atomically loads the wrapped time.Duration.
|
||||
func (x *Duration) Load() time.Duration {
|
||||
return time.Duration(x.v.Load())
|
||||
}
|
||||
|
||||
// Store atomically stores the passed time.Duration.
|
||||
func (x *Duration) Store(v time.Duration) {
|
||||
x.v.Store(int64(v))
|
||||
}
|
||||
|
||||
// CAS is an atomic compare-and-swap for time.Duration values.
|
||||
func (x *Duration) CAS(o, n time.Duration) bool {
|
||||
return x.v.CAS(int64(o), int64(n))
|
||||
}
|
||||
|
||||
// Swap atomically stores the given time.Duration and returns the old
|
||||
// value.
|
||||
func (x *Duration) Swap(o time.Duration) time.Duration {
|
||||
return time.Duration(x.v.Swap(int64(o)))
|
||||
}
|
||||
|
||||
// MarshalJSON encodes the wrapped time.Duration into JSON.
|
||||
func (x *Duration) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(x.Load())
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes a time.Duration from JSON.
|
||||
func (x *Duration) UnmarshalJSON(b []byte) error {
|
||||
var v time.Duration
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
x.Store(v)
|
||||
return nil
|
||||
}
|
40
vendor/go.uber.org/atomic/duration_ext.go
generated
vendored
Normal file
40
vendor/go.uber.org/atomic/duration_ext.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
import "time"
|
||||
|
||||
//go:generate bin/gen-atomicwrapper -name=Duration -type=time.Duration -wrapped=Int64 -pack=int64 -unpack=time.Duration -cas -swap -json -imports time -file=duration.go
|
||||
|
||||
// Add atomically adds to the wrapped time.Duration and returns the new value.
|
||||
func (d *Duration) Add(n time.Duration) time.Duration {
|
||||
return time.Duration(d.v.Add(int64(n)))
|
||||
}
|
||||
|
||||
// Sub atomically subtracts from the wrapped time.Duration and returns the new value.
|
||||
func (d *Duration) Sub(n time.Duration) time.Duration {
|
||||
return time.Duration(d.v.Sub(int64(n)))
|
||||
}
|
||||
|
||||
// String encodes the wrapped value as a string.
|
||||
func (d *Duration) String() string {
|
||||
return d.Load().String()
|
||||
}
|
51
vendor/go.uber.org/atomic/error.go
generated
vendored
Normal file
51
vendor/go.uber.org/atomic/error.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
// @generated Code generated by gen-atomicwrapper.
|
||||
|
||||
// Copyright (c) 2020 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 for error values.
|
||||
type Error struct {
|
||||
_ nocmp // disallow non-atomic comparison
|
||||
|
||||
v Value
|
||||
}
|
||||
|
||||
var _zeroError error
|
||||
|
||||
// NewError creates a new Error.
|
||||
func NewError(v error) *Error {
|
||||
x := &Error{}
|
||||
if v != _zeroError {
|
||||
x.Store(v)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// Load atomically loads the wrapped error.
|
||||
func (x *Error) Load() error {
|
||||
return unpackError(x.v.Load())
|
||||
}
|
||||
|
||||
// Store atomically stores the passed error.
|
||||
func (x *Error) Store(v error) {
|
||||
x.v.Store(packError(v))
|
||||
}
|
39
vendor/go.uber.org/atomic/error_ext.go
generated
vendored
Normal file
39
vendor/go.uber.org/atomic/error_ext.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
// atomic.Value panics on nil inputs, or if the underlying type changes.
|
||||
// Stabilize by always storing a custom struct that we control.
|
||||
|
||||
//go:generate bin/gen-atomicwrapper -name=Error -type=error -wrapped=Value -pack=packError -unpack=unpackError -file=error.go
|
||||
|
||||
type packedError struct{ Value error }
|
||||
|
||||
func packError(v error) interface{} {
|
||||
return packedError{v}
|
||||
}
|
||||
|
||||
func unpackError(v interface{}) error {
|
||||
if err, ok := v.(packedError); ok {
|
||||
return err.Value
|
||||
}
|
||||
return nil
|
||||
}
|
76
vendor/go.uber.org/atomic/float64.go
generated
vendored
Normal file
76
vendor/go.uber.org/atomic/float64.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
// @generated Code generated by gen-atomicwrapper.
|
||||
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
)
|
||||
|
||||
// Float64 is an atomic type-safe wrapper for float64 values.
|
||||
type Float64 struct {
|
||||
_ nocmp // disallow non-atomic comparison
|
||||
|
||||
v Uint64
|
||||
}
|
||||
|
||||
var _zeroFloat64 float64
|
||||
|
||||
// NewFloat64 creates a new Float64.
|
||||
func NewFloat64(v float64) *Float64 {
|
||||
x := &Float64{}
|
||||
if v != _zeroFloat64 {
|
||||
x.Store(v)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// Load atomically loads the wrapped float64.
|
||||
func (x *Float64) Load() float64 {
|
||||
return math.Float64frombits(x.v.Load())
|
||||
}
|
||||
|
||||
// Store atomically stores the passed float64.
|
||||
func (x *Float64) Store(v float64) {
|
||||
x.v.Store(math.Float64bits(v))
|
||||
}
|
||||
|
||||
// CAS is an atomic compare-and-swap for float64 values.
|
||||
func (x *Float64) CAS(o, n float64) bool {
|
||||
return x.v.CAS(math.Float64bits(o), math.Float64bits(n))
|
||||
}
|
||||
|
||||
// MarshalJSON encodes the wrapped float64 into JSON.
|
||||
func (x *Float64) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(x.Load())
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes a float64 from JSON.
|
||||
func (x *Float64) UnmarshalJSON(b []byte) error {
|
||||
var v float64
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
x.Store(v)
|
||||
return nil
|
||||
}
|
47
vendor/go.uber.org/atomic/float64_ext.go
generated
vendored
Normal file
47
vendor/go.uber.org/atomic/float64_ext.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
import "strconv"
|
||||
|
||||
//go:generate bin/gen-atomicwrapper -name=Float64 -type=float64 -wrapped=Uint64 -pack=math.Float64bits -unpack=math.Float64frombits -cas -json -imports math -file=float64.go
|
||||
|
||||
// Add atomically adds to the wrapped float64 and returns the new value.
|
||||
func (f *Float64) Add(s float64) float64 {
|
||||
for {
|
||||
old := f.Load()
|
||||
new := old + s
|
||||
if f.CAS(old, new) {
|
||||
return new
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sub atomically subtracts from the wrapped float64 and returns the new value.
|
||||
func (f *Float64) Sub(s float64) float64 {
|
||||
return f.Add(-s)
|
||||
}
|
||||
|
||||
// String encodes the wrapped value as a string.
|
||||
func (f *Float64) String() string {
|
||||
// 'g' is the behavior for floats with %v.
|
||||
return strconv.FormatFloat(f.Load(), 'g', -1, 64)
|
||||
}
|
26
vendor/go.uber.org/atomic/gen.go
generated
vendored
Normal file
26
vendor/go.uber.org/atomic/gen.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
//go:generate bin/gen-atomicint -name=Int32 -wrapped=int32 -file=int32.go
|
||||
//go:generate bin/gen-atomicint -name=Int64 -wrapped=int64 -file=int64.go
|
||||
//go:generate bin/gen-atomicint -name=Uint32 -wrapped=uint32 -unsigned -file=uint32.go
|
||||
//go:generate bin/gen-atomicint -name=Uint64 -wrapped=uint64 -unsigned -file=uint64.go
|
102
vendor/go.uber.org/atomic/int32.go
generated
vendored
Normal file
102
vendor/go.uber.org/atomic/int32.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
// @generated Code generated by gen-atomicint.
|
||||
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Int32 is an atomic wrapper around int32.
|
||||
type Int32 struct {
|
||||
_ nocmp // disallow non-atomic comparison
|
||||
|
||||
v int32
|
||||
}
|
||||
|
||||
// NewInt32 creates a new Int32.
|
||||
func NewInt32(i int32) *Int32 {
|
||||
return &Int32{v: i}
|
||||
}
|
||||
|
||||
// Load atomically loads the wrapped value.
|
||||
func (i *Int32) Load() int32 {
|
||||
return atomic.LoadInt32(&i.v)
|
||||
}
|
||||
|
||||
// Add atomically adds to the wrapped int32 and returns the new value.
|
||||
func (i *Int32) Add(n int32) int32 {
|
||||
return atomic.AddInt32(&i.v, n)
|
||||
}
|
||||
|
||||
// Sub atomically subtracts from the wrapped int32 and returns the new value.
|
||||
func (i *Int32) Sub(n int32) int32 {
|
||||
return atomic.AddInt32(&i.v, -n)
|
||||
}
|
||||
|
||||
// Inc atomically increments the wrapped int32 and returns the new value.
|
||||
func (i *Int32) Inc() int32 {
|
||||
return i.Add(1)
|
||||
}
|
||||
|
||||
// Dec atomically decrements the wrapped int32 and returns the new value.
|
||||
func (i *Int32) Dec() int32 {
|
||||
return i.Sub(1)
|
||||
}
|
||||
|
||||
// CAS is an atomic compare-and-swap.
|
||||
func (i *Int32) CAS(old, new int32) bool {
|
||||
return atomic.CompareAndSwapInt32(&i.v, old, new)
|
||||
}
|
||||
|
||||
// Store atomically stores the passed value.
|
||||
func (i *Int32) Store(n int32) {
|
||||
atomic.StoreInt32(&i.v, n)
|
||||
}
|
||||
|
||||
// Swap atomically swaps the wrapped int32 and returns the old value.
|
||||
func (i *Int32) Swap(n int32) int32 {
|
||||
return atomic.SwapInt32(&i.v, n)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes the wrapped int32 into JSON.
|
||||
func (i *Int32) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(i.Load())
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes JSON into the wrapped int32.
|
||||
func (i *Int32) UnmarshalJSON(b []byte) error {
|
||||
var v int32
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
i.Store(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String encodes the wrapped value as a string.
|
||||
func (i *Int32) String() string {
|
||||
v := i.Load()
|
||||
return strconv.FormatInt(int64(v), 10)
|
||||
}
|
102
vendor/go.uber.org/atomic/int64.go
generated
vendored
Normal file
102
vendor/go.uber.org/atomic/int64.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
// @generated Code generated by gen-atomicint.
|
||||
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Int64 is an atomic wrapper around int64.
|
||||
type Int64 struct {
|
||||
_ nocmp // disallow non-atomic comparison
|
||||
|
||||
v int64
|
||||
}
|
||||
|
||||
// NewInt64 creates a new Int64.
|
||||
func NewInt64(i int64) *Int64 {
|
||||
return &Int64{v: i}
|
||||
}
|
||||
|
||||
// Load atomically loads the wrapped value.
|
||||
func (i *Int64) Load() int64 {
|
||||
return atomic.LoadInt64(&i.v)
|
||||
}
|
||||
|
||||
// Add atomically adds to the wrapped int64 and returns the new value.
|
||||
func (i *Int64) Add(n int64) int64 {
|
||||
return atomic.AddInt64(&i.v, n)
|
||||
}
|
||||
|
||||
// Sub atomically subtracts from the wrapped int64 and returns the new value.
|
||||
func (i *Int64) Sub(n int64) int64 {
|
||||
return atomic.AddInt64(&i.v, -n)
|
||||
}
|
||||
|
||||
// Inc atomically increments the wrapped int64 and returns the new value.
|
||||
func (i *Int64) Inc() int64 {
|
||||
return i.Add(1)
|
||||
}
|
||||
|
||||
// Dec atomically decrements the wrapped int64 and returns the new value.
|
||||
func (i *Int64) Dec() int64 {
|
||||
return i.Sub(1)
|
||||
}
|
||||
|
||||
// CAS is an atomic compare-and-swap.
|
||||
func (i *Int64) CAS(old, new int64) bool {
|
||||
return atomic.CompareAndSwapInt64(&i.v, old, new)
|
||||
}
|
||||
|
||||
// Store atomically stores the passed value.
|
||||
func (i *Int64) Store(n int64) {
|
||||
atomic.StoreInt64(&i.v, n)
|
||||
}
|
||||
|
||||
// Swap atomically swaps the wrapped int64 and returns the old value.
|
||||
func (i *Int64) Swap(n int64) int64 {
|
||||
return atomic.SwapInt64(&i.v, n)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes the wrapped int64 into JSON.
|
||||
func (i *Int64) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(i.Load())
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes JSON into the wrapped int64.
|
||||
func (i *Int64) UnmarshalJSON(b []byte) error {
|
||||
var v int64
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
i.Store(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String encodes the wrapped value as a string.
|
||||
func (i *Int64) String() string {
|
||||
v := i.Load()
|
||||
return strconv.FormatInt(int64(v), 10)
|
||||
}
|
35
vendor/go.uber.org/atomic/nocmp.go
generated
vendored
Normal file
35
vendor/go.uber.org/atomic/nocmp.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
// nocmp is an uncomparable struct. Embed this inside another struct to make
|
||||
// it uncomparable.
|
||||
//
|
||||
// type Foo struct {
|
||||
// nocmp
|
||||
// // ...
|
||||
// }
|
||||
//
|
||||
// This DOES NOT:
|
||||
//
|
||||
// - Disallow shallow copies of structs
|
||||
// - Disallow comparison of pointers to uncomparable structs
|
||||
type nocmp [0]func()
|
54
vendor/go.uber.org/atomic/string.go
generated
vendored
Normal file
54
vendor/go.uber.org/atomic/string.go
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
// @generated Code generated by gen-atomicwrapper.
|
||||
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
// String is an atomic type-safe wrapper for string values.
|
||||
type String struct {
|
||||
_ nocmp // disallow non-atomic comparison
|
||||
|
||||
v Value
|
||||
}
|
||||
|
||||
var _zeroString string
|
||||
|
||||
// NewString creates a new String.
|
||||
func NewString(v string) *String {
|
||||
x := &String{}
|
||||
if v != _zeroString {
|
||||
x.Store(v)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// Load atomically loads the wrapped string.
|
||||
func (x *String) Load() string {
|
||||
if v := x.v.Load(); v != nil {
|
||||
return v.(string)
|
||||
}
|
||||
return _zeroString
|
||||
}
|
||||
|
||||
// Store atomically stores the passed string.
|
||||
func (x *String) Store(v string) {
|
||||
x.v.Store(v)
|
||||
}
|
43
vendor/go.uber.org/atomic/string_ext.go
generated
vendored
Normal file
43
vendor/go.uber.org/atomic/string_ext.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
//go:generate bin/gen-atomicwrapper -name=String -type=string -wrapped=Value -file=string.go
|
||||
|
||||
// String returns the wrapped value.
|
||||
func (s *String) String() string {
|
||||
return s.Load()
|
||||
}
|
||||
|
||||
// MarshalText encodes the wrapped string into a textual form.
|
||||
//
|
||||
// This makes it encodable as JSON, YAML, XML, and more.
|
||||
func (s *String) MarshalText() ([]byte, error) {
|
||||
return []byte(s.Load()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText decodes text and replaces the wrapped string with it.
|
||||
//
|
||||
// This makes it decodable from JSON, YAML, XML, and more.
|
||||
func (s *String) UnmarshalText(b []byte) error {
|
||||
s.Store(string(b))
|
||||
return nil
|
||||
}
|
102
vendor/go.uber.org/atomic/uint32.go
generated
vendored
Normal file
102
vendor/go.uber.org/atomic/uint32.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
// @generated Code generated by gen-atomicint.
|
||||
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Uint32 is an atomic wrapper around uint32.
|
||||
type Uint32 struct {
|
||||
_ nocmp // disallow non-atomic comparison
|
||||
|
||||
v uint32
|
||||
}
|
||||
|
||||
// NewUint32 creates a new Uint32.
|
||||
func NewUint32(i uint32) *Uint32 {
|
||||
return &Uint32{v: i}
|
||||
}
|
||||
|
||||
// Load atomically loads the wrapped value.
|
||||
func (i *Uint32) Load() uint32 {
|
||||
return atomic.LoadUint32(&i.v)
|
||||
}
|
||||
|
||||
// Add atomically adds to the wrapped uint32 and returns the new value.
|
||||
func (i *Uint32) Add(n uint32) uint32 {
|
||||
return atomic.AddUint32(&i.v, n)
|
||||
}
|
||||
|
||||
// Sub atomically subtracts from the wrapped uint32 and returns the new value.
|
||||
func (i *Uint32) Sub(n uint32) uint32 {
|
||||
return atomic.AddUint32(&i.v, ^(n - 1))
|
||||
}
|
||||
|
||||
// Inc atomically increments the wrapped uint32 and returns the new value.
|
||||
func (i *Uint32) Inc() uint32 {
|
||||
return i.Add(1)
|
||||
}
|
||||
|
||||
// Dec atomically decrements the wrapped uint32 and returns the new value.
|
||||
func (i *Uint32) Dec() uint32 {
|
||||
return i.Sub(1)
|
||||
}
|
||||
|
||||
// CAS is an atomic compare-and-swap.
|
||||
func (i *Uint32) CAS(old, new uint32) bool {
|
||||
return atomic.CompareAndSwapUint32(&i.v, old, new)
|
||||
}
|
||||
|
||||
// Store atomically stores the passed value.
|
||||
func (i *Uint32) Store(n uint32) {
|
||||
atomic.StoreUint32(&i.v, n)
|
||||
}
|
||||
|
||||
// Swap atomically swaps the wrapped uint32 and returns the old value.
|
||||
func (i *Uint32) Swap(n uint32) uint32 {
|
||||
return atomic.SwapUint32(&i.v, n)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes the wrapped uint32 into JSON.
|
||||
func (i *Uint32) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(i.Load())
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes JSON into the wrapped uint32.
|
||||
func (i *Uint32) UnmarshalJSON(b []byte) error {
|
||||
var v uint32
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
i.Store(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String encodes the wrapped value as a string.
|
||||
func (i *Uint32) String() string {
|
||||
v := i.Load()
|
||||
return strconv.FormatUint(uint64(v), 10)
|
||||
}
|
102
vendor/go.uber.org/atomic/uint64.go
generated
vendored
Normal file
102
vendor/go.uber.org/atomic/uint64.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
// @generated Code generated by gen-atomicint.
|
||||
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Uint64 is an atomic wrapper around uint64.
|
||||
type Uint64 struct {
|
||||
_ nocmp // disallow non-atomic comparison
|
||||
|
||||
v uint64
|
||||
}
|
||||
|
||||
// NewUint64 creates a new Uint64.
|
||||
func NewUint64(i uint64) *Uint64 {
|
||||
return &Uint64{v: i}
|
||||
}
|
||||
|
||||
// Load atomically loads the wrapped value.
|
||||
func (i *Uint64) Load() uint64 {
|
||||
return atomic.LoadUint64(&i.v)
|
||||
}
|
||||
|
||||
// Add atomically adds to the wrapped uint64 and returns the new value.
|
||||
func (i *Uint64) Add(n uint64) uint64 {
|
||||
return atomic.AddUint64(&i.v, n)
|
||||
}
|
||||
|
||||
// Sub atomically subtracts from the wrapped uint64 and returns the new value.
|
||||
func (i *Uint64) Sub(n uint64) uint64 {
|
||||
return atomic.AddUint64(&i.v, ^(n - 1))
|
||||
}
|
||||
|
||||
// Inc atomically increments the wrapped uint64 and returns the new value.
|
||||
func (i *Uint64) Inc() uint64 {
|
||||
return i.Add(1)
|
||||
}
|
||||
|
||||
// Dec atomically decrements the wrapped uint64 and returns the new value.
|
||||
func (i *Uint64) Dec() uint64 {
|
||||
return i.Sub(1)
|
||||
}
|
||||
|
||||
// CAS is an atomic compare-and-swap.
|
||||
func (i *Uint64) CAS(old, new uint64) bool {
|
||||
return atomic.CompareAndSwapUint64(&i.v, old, new)
|
||||
}
|
||||
|
||||
// Store atomically stores the passed value.
|
||||
func (i *Uint64) Store(n uint64) {
|
||||
atomic.StoreUint64(&i.v, n)
|
||||
}
|
||||
|
||||
// Swap atomically swaps the wrapped uint64 and returns the old value.
|
||||
func (i *Uint64) Swap(n uint64) uint64 {
|
||||
return atomic.SwapUint64(&i.v, n)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes the wrapped uint64 into JSON.
|
||||
func (i *Uint64) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(i.Load())
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes JSON into the wrapped uint64.
|
||||
func (i *Uint64) UnmarshalJSON(b []byte) error {
|
||||
var v uint64
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
i.Store(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String encodes the wrapped value as a string.
|
||||
func (i *Uint64) String() string {
|
||||
v := i.Load()
|
||||
return strconv.FormatUint(uint64(v), 10)
|
||||
}
|
31
vendor/go.uber.org/atomic/value.go
generated
vendored
Normal file
31
vendor/go.uber.org/atomic/value.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2020 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
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
// Value shadows the type of the same name from sync/atomic
|
||||
// https://godoc.org/sync/atomic#Value
|
||||
type Value struct {
|
||||
atomic.Value
|
||||
|
||||
_ nocmp // disallow non-atomic comparison
|
||||
}
|
15
vendor/go.uber.org/multierr/.codecov.yml
generated
vendored
Normal file
15
vendor/go.uber.org/multierr/.codecov.yml
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
coverage:
|
||||
range: 80..100
|
||||
round: down
|
||||
precision: 2
|
||||
|
||||
status:
|
||||
project: # measuring the overall project coverage
|
||||
default: # context, you can create multiple ones with custom titles
|
||||
enabled: yes # must be yes|true to enable this status
|
||||
target: 100 # specify the target coverage for each commit status
|
||||
# option: "auto" (must increase from parent commit or pull request base)
|
||||
# option: "X%" a static target percentage to hit
|
||||
if_not_found: success # if parent is not found report status as success, error, or failure
|
||||
if_ci_failed: error # if ci fails report status as success, error, or failure
|
||||
|
4
vendor/go.uber.org/multierr/.gitignore
generated
vendored
Normal file
4
vendor/go.uber.org/multierr/.gitignore
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/vendor
|
||||
cover.html
|
||||
cover.out
|
||||
/bin
|
23
vendor/go.uber.org/multierr/.travis.yml
generated
vendored
Normal file
23
vendor/go.uber.org/multierr/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go_import_path: go.uber.org/multierr
|
||||
|
||||
env:
|
||||
global:
|
||||
- GO111MODULE=on
|
||||
|
||||
go:
|
||||
- oldstable
|
||||
- stable
|
||||
|
||||
before_install:
|
||||
- go version
|
||||
|
||||
script:
|
||||
- |
|
||||
set -e
|
||||
make lint
|
||||
make cover
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
60
vendor/go.uber.org/multierr/CHANGELOG.md
generated
vendored
Normal file
60
vendor/go.uber.org/multierr/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
Releases
|
||||
========
|
||||
|
||||
v1.6.0 (2020-09-14)
|
||||
===================
|
||||
|
||||
- Actually drop library dependency on development-time tooling.
|
||||
|
||||
|
||||
v1.5.0 (2020-02-24)
|
||||
===================
|
||||
|
||||
- Drop library dependency on development-time tooling.
|
||||
|
||||
|
||||
v1.4.0 (2019-11-04)
|
||||
===================
|
||||
|
||||
- Add `AppendInto` function to more ergonomically build errors inside a
|
||||
loop.
|
||||
|
||||
|
||||
v1.3.0 (2019-10-29)
|
||||
===================
|
||||
|
||||
- Switch to Go modules.
|
||||
|
||||
|
||||
v1.2.0 (2019-09-26)
|
||||
===================
|
||||
|
||||
- Support extracting and matching against wrapped errors with `errors.As`
|
||||
and `errors.Is`.
|
||||
|
||||
|
||||
v1.1.0 (2017-06-30)
|
||||
===================
|
||||
|
||||
- Added an `Errors(error) []error` function to extract the underlying list of
|
||||
errors for a multierr error.
|
||||
|
||||
|
||||
v1.0.0 (2017-05-31)
|
||||
===================
|
||||
|
||||
No changes since v0.2.0. This release is committing to making no breaking
|
||||
changes to the current API in the 1.X series.
|
||||
|
||||
|
||||
v0.2.0 (2017-04-11)
|
||||
===================
|
||||
|
||||
- Repeatedly appending to the same error is now faster due to fewer
|
||||
allocations.
|
||||
|
||||
|
||||
v0.1.0 (2017-31-03)
|
||||
===================
|
||||
|
||||
- Initial release
|
19
vendor/go.uber.org/multierr/LICENSE.txt
generated
vendored
Normal file
19
vendor/go.uber.org/multierr/LICENSE.txt
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2017 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.
|
42
vendor/go.uber.org/multierr/Makefile
generated
vendored
Normal file
42
vendor/go.uber.org/multierr/Makefile
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
# Directory to put `go install`ed binaries in.
|
||||
export GOBIN ?= $(shell pwd)/bin
|
||||
|
||||
GO_FILES := $(shell \
|
||||
find . '(' -path '*/.*' -o -path './vendor' ')' -prune \
|
||||
-o -name '*.go' -print | cut -b3-)
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
go build ./...
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -race ./...
|
||||
|
||||
.PHONY: gofmt
|
||||
gofmt:
|
||||
$(eval FMT_LOG := $(shell mktemp -t gofmt.XXXXX))
|
||||
@gofmt -e -s -l $(GO_FILES) > $(FMT_LOG) || true
|
||||
@[ ! -s "$(FMT_LOG)" ] || (echo "gofmt failed:" | cat - $(FMT_LOG) && false)
|
||||
|
||||
.PHONY: golint
|
||||
golint:
|
||||
@cd tools && go install golang.org/x/lint/golint
|
||||
@$(GOBIN)/golint ./...
|
||||
|
||||
.PHONY: staticcheck
|
||||
staticcheck:
|
||||
@cd tools && go install honnef.co/go/tools/cmd/staticcheck
|
||||
@$(GOBIN)/staticcheck ./...
|
||||
|
||||
.PHONY: lint
|
||||
lint: gofmt golint staticcheck
|
||||
|
||||
.PHONY: cover
|
||||
cover:
|
||||
go test -coverprofile=cover.out -coverpkg=./... -v ./...
|
||||
go tool cover -html=cover.out -o cover.html
|
||||
|
||||
update-license:
|
||||
@cd tools && go install go.uber.org/tools/update-license
|
||||
@$(GOBIN)/update-license $(GO_FILES)
|
23
vendor/go.uber.org/multierr/README.md
generated
vendored
Normal file
23
vendor/go.uber.org/multierr/README.md
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
# multierr [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
|
||||
|
||||
`multierr` allows combining one or more Go `error`s together.
|
||||
|
||||
## Installation
|
||||
|
||||
go get -u go.uber.org/multierr
|
||||
|
||||
## Status
|
||||
|
||||
Stable: No breaking changes will be made before 2.0.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Released under the [MIT License].
|
||||
|
||||
[MIT License]: LICENSE.txt
|
||||
[doc-img]: https://godoc.org/go.uber.org/multierr?status.svg
|
||||
[doc]: https://godoc.org/go.uber.org/multierr
|
||||
[ci-img]: https://travis-ci.com/uber-go/multierr.svg?branch=master
|
||||
[cov-img]: https://codecov.io/gh/uber-go/multierr/branch/master/graph/badge.svg
|
||||
[ci]: https://travis-ci.com/uber-go/multierr
|
||||
[cov]: https://codecov.io/gh/uber-go/multierr
|
449
vendor/go.uber.org/multierr/error.go
generated
vendored
Normal file
449
vendor/go.uber.org/multierr/error.go
generated
vendored
Normal file
@ -0,0 +1,449 @@
|
||||
// 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.
|
||||
|
||||
// Package multierr allows combining one or more errors together.
|
||||
//
|
||||
// Overview
|
||||
//
|
||||
// Errors can be combined with the use of the Combine function.
|
||||
//
|
||||
// multierr.Combine(
|
||||
// reader.Close(),
|
||||
// writer.Close(),
|
||||
// conn.Close(),
|
||||
// )
|
||||
//
|
||||
// If only two errors are being combined, the Append function may be used
|
||||
// instead.
|
||||
//
|
||||
// err = multierr.Append(reader.Close(), writer.Close())
|
||||
//
|
||||
// This makes it possible to record resource cleanup failures from deferred
|
||||
// blocks with the help of named return values.
|
||||
//
|
||||
// func sendRequest(req Request) (err error) {
|
||||
// conn, err := openConnection()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// defer func() {
|
||||
// err = multierr.Append(err, conn.Close())
|
||||
// }()
|
||||
// // ...
|
||||
// }
|
||||
//
|
||||
// The underlying list of errors for a returned error object may be retrieved
|
||||
// with the Errors function.
|
||||
//
|
||||
// errors := multierr.Errors(err)
|
||||
// if len(errors) > 0 {
|
||||
// fmt.Println("The following errors occurred:", errors)
|
||||
// }
|
||||
//
|
||||
// Advanced Usage
|
||||
//
|
||||
// Errors returned by Combine and Append MAY implement the following
|
||||
// interface.
|
||||
//
|
||||
// type errorGroup interface {
|
||||
// // Returns a slice containing the underlying list of errors.
|
||||
// //
|
||||
// // This slice MUST NOT be modified by the caller.
|
||||
// Errors() []error
|
||||
// }
|
||||
//
|
||||
// Note that if you need access to list of errors behind a multierr error, you
|
||||
// should prefer using the Errors function. That said, if you need cheap
|
||||
// read-only access to the underlying errors slice, you can attempt to cast
|
||||
// the error to this interface. You MUST handle the failure case gracefully
|
||||
// because errors returned by Combine and Append are not guaranteed to
|
||||
// implement this interface.
|
||||
//
|
||||
// var errors []error
|
||||
// group, ok := err.(errorGroup)
|
||||
// if ok {
|
||||
// errors = group.Errors()
|
||||
// } else {
|
||||
// errors = []error{err}
|
||||
// }
|
||||
package multierr // import "go.uber.org/multierr"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"go.uber.org/atomic"
|
||||
)
|
||||
|
||||
var (
|
||||
// Separator for single-line error messages.
|
||||
_singlelineSeparator = []byte("; ")
|
||||
|
||||
// Prefix for multi-line messages
|
||||
_multilinePrefix = []byte("the following errors occurred:")
|
||||
|
||||
// Prefix for the first and following lines of an item in a list of
|
||||
// multi-line error messages.
|
||||
//
|
||||
// For example, if a single item is:
|
||||
//
|
||||
// foo
|
||||
// bar
|
||||
//
|
||||
// It will become,
|
||||
//
|
||||
// - foo
|
||||
// bar
|
||||
_multilineSeparator = []byte("\n - ")
|
||||
_multilineIndent = []byte(" ")
|
||||
)
|
||||
|
||||
// _bufferPool is a pool of bytes.Buffers.
|
||||
var _bufferPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &bytes.Buffer{}
|
||||
},
|
||||
}
|
||||
|
||||
type errorGroup interface {
|
||||
Errors() []error
|
||||
}
|
||||
|
||||
// Errors returns a slice containing zero or more errors that the supplied
|
||||
// error is composed of. If the error is nil, a nil slice is returned.
|
||||
//
|
||||
// err := multierr.Append(r.Close(), w.Close())
|
||||
// errors := multierr.Errors(err)
|
||||
//
|
||||
// If the error is not composed of other errors, the returned slice contains
|
||||
// just the error that was passed in.
|
||||
//
|
||||
// Callers of this function are free to modify the returned slice.
|
||||
func Errors(err error) []error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Note that we're casting to multiError, not errorGroup. Our contract is
|
||||
// that returned errors MAY implement errorGroup. Errors, however, only
|
||||
// has special behavior for multierr-specific error objects.
|
||||
//
|
||||
// This behavior can be expanded in the future but I think it's prudent to
|
||||
// start with as little as possible in terms of contract and possibility
|
||||
// of misuse.
|
||||
eg, ok := err.(*multiError)
|
||||
if !ok {
|
||||
return []error{err}
|
||||
}
|
||||
|
||||
errors := eg.Errors()
|
||||
result := make([]error, len(errors))
|
||||
copy(result, errors)
|
||||
return result
|
||||
}
|
||||
|
||||
// multiError is an error that holds one or more errors.
|
||||
//
|
||||
// An instance of this is guaranteed to be non-empty and flattened. That is,
|
||||
// none of the errors inside multiError are other multiErrors.
|
||||
//
|
||||
// multiError formats to a semi-colon delimited list of error messages with
|
||||
// %v and with a more readable multi-line format with %+v.
|
||||
type multiError struct {
|
||||
copyNeeded atomic.Bool
|
||||
errors []error
|
||||
}
|
||||
|
||||
var _ errorGroup = (*multiError)(nil)
|
||||
|
||||
// Errors returns the list of underlying errors.
|
||||
//
|
||||
// This slice MUST NOT be modified.
|
||||
func (merr *multiError) Errors() []error {
|
||||
if merr == nil {
|
||||
return nil
|
||||
}
|
||||
return merr.errors
|
||||
}
|
||||
|
||||
func (merr *multiError) Error() string {
|
||||
if merr == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
buff := _bufferPool.Get().(*bytes.Buffer)
|
||||
buff.Reset()
|
||||
|
||||
merr.writeSingleline(buff)
|
||||
|
||||
result := buff.String()
|
||||
_bufferPool.Put(buff)
|
||||
return result
|
||||
}
|
||||
|
||||
func (merr *multiError) Format(f fmt.State, c rune) {
|
||||
if c == 'v' && f.Flag('+') {
|
||||
merr.writeMultiline(f)
|
||||
} else {
|
||||
merr.writeSingleline(f)
|
||||
}
|
||||
}
|
||||
|
||||
func (merr *multiError) writeSingleline(w io.Writer) {
|
||||
first := true
|
||||
for _, item := range merr.errors {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
w.Write(_singlelineSeparator)
|
||||
}
|
||||
io.WriteString(w, item.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (merr *multiError) writeMultiline(w io.Writer) {
|
||||
w.Write(_multilinePrefix)
|
||||
for _, item := range merr.errors {
|
||||
w.Write(_multilineSeparator)
|
||||
writePrefixLine(w, _multilineIndent, fmt.Sprintf("%+v", item))
|
||||
}
|
||||
}
|
||||
|
||||
// Writes s to the writer with the given prefix added before each line after
|
||||
// the first.
|
||||
func writePrefixLine(w io.Writer, prefix []byte, s string) {
|
||||
first := true
|
||||
for len(s) > 0 {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
w.Write(prefix)
|
||||
}
|
||||
|
||||
idx := strings.IndexByte(s, '\n')
|
||||
if idx < 0 {
|
||||
idx = len(s) - 1
|
||||
}
|
||||
|
||||
io.WriteString(w, s[:idx+1])
|
||||
s = s[idx+1:]
|
||||
}
|
||||
}
|
||||
|
||||
type inspectResult struct {
|
||||
// Number of top-level non-nil errors
|
||||
Count int
|
||||
|
||||
// Total number of errors including multiErrors
|
||||
Capacity int
|
||||
|
||||
// Index of the first non-nil error in the list. Value is meaningless if
|
||||
// Count is zero.
|
||||
FirstErrorIdx int
|
||||
|
||||
// Whether the list contains at least one multiError
|
||||
ContainsMultiError bool
|
||||
}
|
||||
|
||||
// Inspects the given slice of errors so that we can efficiently allocate
|
||||
// space for it.
|
||||
func inspect(errors []error) (res inspectResult) {
|
||||
first := true
|
||||
for i, err := range errors {
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
res.Count++
|
||||
if first {
|
||||
first = false
|
||||
res.FirstErrorIdx = i
|
||||
}
|
||||
|
||||
if merr, ok := err.(*multiError); ok {
|
||||
res.Capacity += len(merr.errors)
|
||||
res.ContainsMultiError = true
|
||||
} else {
|
||||
res.Capacity++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// fromSlice converts the given list of errors into a single error.
|
||||
func fromSlice(errors []error) error {
|
||||
res := inspect(errors)
|
||||
switch res.Count {
|
||||
case 0:
|
||||
return nil
|
||||
case 1:
|
||||
// only one non-nil entry
|
||||
return errors[res.FirstErrorIdx]
|
||||
case len(errors):
|
||||
if !res.ContainsMultiError {
|
||||
// already flat
|
||||
return &multiError{errors: errors}
|
||||
}
|
||||
}
|
||||
|
||||
nonNilErrs := make([]error, 0, res.Capacity)
|
||||
for _, err := range errors[res.FirstErrorIdx:] {
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if nested, ok := err.(*multiError); ok {
|
||||
nonNilErrs = append(nonNilErrs, nested.errors...)
|
||||
} else {
|
||||
nonNilErrs = append(nonNilErrs, err)
|
||||
}
|
||||
}
|
||||
|
||||
return &multiError{errors: nonNilErrs}
|
||||
}
|
||||
|
||||
// Combine combines the passed errors into a single error.
|
||||
//
|
||||
// If zero arguments were passed or if all items are nil, a nil error is
|
||||
// returned.
|
||||
//
|
||||
// Combine(nil, nil) // == nil
|
||||
//
|
||||
// If only a single error was passed, it is returned as-is.
|
||||
//
|
||||
// Combine(err) // == err
|
||||
//
|
||||
// Combine skips over nil arguments so this function may be used to combine
|
||||
// together errors from operations that fail independently of each other.
|
||||
//
|
||||
// multierr.Combine(
|
||||
// reader.Close(),
|
||||
// writer.Close(),
|
||||
// pipe.Close(),
|
||||
// )
|
||||
//
|
||||
// If any of the passed errors is a multierr error, it will be flattened along
|
||||
// with the other errors.
|
||||
//
|
||||
// multierr.Combine(multierr.Combine(err1, err2), err3)
|
||||
// // is the same as
|
||||
// multierr.Combine(err1, err2, err3)
|
||||
//
|
||||
// The returned error formats into a readable multi-line error message if
|
||||
// formatted with %+v.
|
||||
//
|
||||
// fmt.Sprintf("%+v", multierr.Combine(err1, err2))
|
||||
func Combine(errors ...error) error {
|
||||
return fromSlice(errors)
|
||||
}
|
||||
|
||||
// Append appends the given errors together. Either value may be nil.
|
||||
//
|
||||
// This function is a specialization of Combine for the common case where
|
||||
// there are only two errors.
|
||||
//
|
||||
// err = multierr.Append(reader.Close(), writer.Close())
|
||||
//
|
||||
// The following pattern may also be used to record failure of deferred
|
||||
// operations without losing information about the original error.
|
||||
//
|
||||
// func doSomething(..) (err error) {
|
||||
// f := acquireResource()
|
||||
// defer func() {
|
||||
// err = multierr.Append(err, f.Close())
|
||||
// }()
|
||||
func Append(left error, right error) error {
|
||||
switch {
|
||||
case left == nil:
|
||||
return right
|
||||
case right == nil:
|
||||
return left
|
||||
}
|
||||
|
||||
if _, ok := right.(*multiError); !ok {
|
||||
if l, ok := left.(*multiError); ok && !l.copyNeeded.Swap(true) {
|
||||
// Common case where the error on the left is constantly being
|
||||
// appended to.
|
||||
errs := append(l.errors, right)
|
||||
return &multiError{errors: errs}
|
||||
} else if !ok {
|
||||
// Both errors are single errors.
|
||||
return &multiError{errors: []error{left, right}}
|
||||
}
|
||||
}
|
||||
|
||||
// Either right or both, left and right, are multiErrors. Rely on usual
|
||||
// expensive logic.
|
||||
errors := [2]error{left, right}
|
||||
return fromSlice(errors[0:])
|
||||
}
|
||||
|
||||
// AppendInto appends an error into the destination of an error pointer and
|
||||
// returns whether the error being appended was non-nil.
|
||||
//
|
||||
// var err error
|
||||
// multierr.AppendInto(&err, r.Close())
|
||||
// multierr.AppendInto(&err, w.Close())
|
||||
//
|
||||
// The above is equivalent to,
|
||||
//
|
||||
// err := multierr.Append(r.Close(), w.Close())
|
||||
//
|
||||
// As AppendInto reports whether the provided error was non-nil, it may be
|
||||
// used to build a multierr error in a loop more ergonomically. For example:
|
||||
//
|
||||
// var err error
|
||||
// for line := range lines {
|
||||
// var item Item
|
||||
// if multierr.AppendInto(&err, parse(line, &item)) {
|
||||
// continue
|
||||
// }
|
||||
// items = append(items, item)
|
||||
// }
|
||||
//
|
||||
// Compare this with a verison that relies solely on Append:
|
||||
//
|
||||
// var err error
|
||||
// for line := range lines {
|
||||
// var item Item
|
||||
// if parseErr := parse(line, &item); parseErr != nil {
|
||||
// err = multierr.Append(err, parseErr)
|
||||
// continue
|
||||
// }
|
||||
// items = append(items, item)
|
||||
// }
|
||||
func AppendInto(into *error, err error) (errored bool) {
|
||||
if into == nil {
|
||||
// We panic if 'into' is nil. This is not documented above
|
||||
// because suggesting that the pointer must be non-nil may
|
||||
// confuse users into thinking that the error that it points
|
||||
// to must be non-nil.
|
||||
panic("misuse of multierr.AppendInto: into pointer must not be nil")
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
*into = Append(*into, err)
|
||||
return true
|
||||
}
|
8
vendor/go.uber.org/multierr/glide.yaml
generated
vendored
Normal file
8
vendor/go.uber.org/multierr/glide.yaml
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
package: go.uber.org/multierr
|
||||
import:
|
||||
- package: go.uber.org/atomic
|
||||
version: ^1
|
||||
testImport:
|
||||
- package: github.com/stretchr/testify
|
||||
subpackages:
|
||||
- assert
|
52
vendor/go.uber.org/multierr/go113.go
generated
vendored
Normal file
52
vendor/go.uber.org/multierr/go113.go
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
// 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.
|
||||
|
||||
// +build go1.13
|
||||
|
||||
package multierr
|
||||
|
||||
import "errors"
|
||||
|
||||
// As attempts to find the first error in the error list that matches the type
|
||||
// of the value that target points to.
|
||||
//
|
||||
// This function allows errors.As to traverse the values stored on the
|
||||
// multierr error.
|
||||
func (merr *multiError) As(target interface{}) bool {
|
||||
for _, err := range merr.Errors() {
|
||||
if errors.As(err, target) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Is attempts to match the provided error against errors in the error list.
|
||||
//
|
||||
// This function allows errors.Is to traverse the values stored on the
|
||||
// multierr error.
|
||||
func (merr *multiError) Is(target error) bool {
|
||||
for _, err := range merr.Errors() {
|
||||
if errors.Is(err, target) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
17
vendor/go.uber.org/zap/.codecov.yml
generated
vendored
Normal file
17
vendor/go.uber.org/zap/.codecov.yml
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
coverage:
|
||||
range: 80..100
|
||||
round: down
|
||||
precision: 2
|
||||
|
||||
status:
|
||||
project: # measuring the overall project coverage
|
||||
default: # context, you can create multiple ones with custom titles
|
||||
enabled: yes # must be yes|true to enable this status
|
||||
target: 95% # specify the target coverage for each commit status
|
||||
# option: "auto" (must increase from parent commit or pull request base)
|
||||
# option: "X%" a static target percentage to hit
|
||||
if_not_found: success # if parent is not found report status as success, error, or failure
|
||||
if_ci_failed: error # if ci fails report status as success, error, or failure
|
||||
ignore:
|
||||
- internal/readme/readme.go
|
||||
|
32
vendor/go.uber.org/zap/.gitignore
generated
vendored
Normal file
32
vendor/go.uber.org/zap/.gitignore
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
vendor
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
*.pprof
|
||||
*.out
|
||||
*.log
|
||||
|
||||
/bin
|
||||
cover.out
|
||||
cover.html
|
109
vendor/go.uber.org/zap/.readme.tmpl
generated
vendored
Normal file
109
vendor/go.uber.org/zap/.readme.tmpl
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
# :zap: zap [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
|
||||
|
||||
Blazing fast, structured, leveled logging in Go.
|
||||
|
||||
## Installation
|
||||
|
||||
`go get -u go.uber.org/zap`
|
||||
|
||||
Note that zap only supports the two most recent minor versions of Go.
|
||||
|
||||
## Quick Start
|
||||
|
||||
In contexts where performance is nice, but not critical, use the
|
||||
`SugaredLogger`. It's 4-10x faster than other structured logging
|
||||
packages and includes both structured and `printf`-style APIs.
|
||||
|
||||
```go
|
||||
logger, _ := zap.NewProduction()
|
||||
defer logger.Sync() // flushes buffer, if any
|
||||
sugar := logger.Sugar()
|
||||
sugar.Infow("failed to fetch URL",
|
||||
// Structured context as loosely typed key-value pairs.
|
||||
"url", url,
|
||||
"attempt", 3,
|
||||
"backoff", time.Second,
|
||||
)
|
||||
sugar.Infof("Failed to fetch URL: %s", url)
|
||||
```
|
||||
|
||||
When performance and type safety are critical, use the `Logger`. It's even
|
||||
faster than the `SugaredLogger` and allocates far less, but it only supports
|
||||
structured logging.
|
||||
|
||||
```go
|
||||
logger, _ := zap.NewProduction()
|
||||
defer logger.Sync()
|
||||
logger.Info("failed to fetch URL",
|
||||
// Structured context as strongly typed Field values.
|
||||
zap.String("url", url),
|
||||
zap.Int("attempt", 3),
|
||||
zap.Duration("backoff", time.Second),
|
||||
)
|
||||
```
|
||||
|
||||
See the [documentation][doc] and [FAQ](FAQ.md) for more details.
|
||||
|
||||
## Performance
|
||||
|
||||
For applications that log in the hot path, reflection-based serialization and
|
||||
string formatting are prohibitively expensive — they're CPU-intensive
|
||||
and make many small allocations. Put differently, using `encoding/json` and
|
||||
`fmt.Fprintf` to log tons of `interface{}`s makes your application slow.
|
||||
|
||||
Zap takes a different approach. It includes a reflection-free, zero-allocation
|
||||
JSON encoder, and the base `Logger` strives to avoid serialization overhead
|
||||
and allocations wherever possible. By building the high-level `SugaredLogger`
|
||||
on that foundation, zap lets users *choose* when they need to count every
|
||||
allocation and when they'd prefer a more familiar, loosely typed API.
|
||||
|
||||
As measured by its own [benchmarking suite][], not only is zap more performant
|
||||
than comparable structured logging packages — it's also faster than the
|
||||
standard library. Like all benchmarks, take these with a grain of salt.<sup
|
||||
id="anchor-versions">[1](#footnote-versions)</sup>
|
||||
|
||||
Log a message and 10 fields:
|
||||
|
||||
{{.BenchmarkAddingFields}}
|
||||
|
||||
Log a message with a logger that already has 10 fields of context:
|
||||
|
||||
{{.BenchmarkAccumulatedContext}}
|
||||
|
||||
Log a static string, without any context or `printf`-style templating:
|
||||
|
||||
{{.BenchmarkWithoutFields}}
|
||||
|
||||
## Development Status: Stable
|
||||
|
||||
All APIs are finalized, and no breaking changes will be made in the 1.x series
|
||||
of releases. Users of semver-aware dependency management systems should pin
|
||||
zap to `^1`.
|
||||
|
||||
## Contributing
|
||||
|
||||
We encourage and support an active, healthy community of contributors —
|
||||
including you! Details are in the [contribution guide](CONTRIBUTING.md) and
|
||||
the [code of conduct](CODE_OF_CONDUCT.md). The zap maintainers keep an eye on
|
||||
issues and pull requests, but you can also report any negative conduct to
|
||||
oss-conduct@uber.com. That email list is a private, safe space; even the zap
|
||||
maintainers don't have access, so don't hesitate to hold us to a high
|
||||
standard.
|
||||
|
||||
<hr>
|
||||
|
||||
Released under the [MIT License](LICENSE.txt).
|
||||
|
||||
<sup id="footnote-versions">1</sup> In particular, keep in mind that we may be
|
||||
benchmarking against slightly older versions of other packages. Versions are
|
||||
pinned in zap's [glide.lock][] file. [↩](#anchor-versions)
|
||||
|
||||
[doc-img]: https://godoc.org/go.uber.org/zap?status.svg
|
||||
[doc]: https://godoc.org/go.uber.org/zap
|
||||
[ci-img]: https://travis-ci.com/uber-go/zap.svg?branch=master
|
||||
[ci]: https://travis-ci.com/uber-go/zap
|
||||
[cov-img]: https://codecov.io/gh/uber-go/zap/branch/master/graph/badge.svg
|
||||
[cov]: https://codecov.io/gh/uber-go/zap
|
||||
[benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks
|
||||
[glide.lock]: https://github.com/uber-go/zap/blob/master/glide.lock
|
||||
|
516
vendor/go.uber.org/zap/CHANGELOG.md
generated
vendored
Normal file
516
vendor/go.uber.org/zap/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,516 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 1.19.1 (8 Sep 2021)
|
||||
|
||||
### Fixed
|
||||
* [#1001][]: JSON: Fix complex number encoding with negative imaginary part. Thanks to @hemantjadon.
|
||||
* [#1003][]: JSON: Fix inaccurate precision when encoding float32.
|
||||
|
||||
[#1001]: https://github.com/uber-go/zap/pull/1001
|
||||
[#1003]: https://github.com/uber-go/zap/pull/1003
|
||||
|
||||
## 1.19.0 (9 Aug 2021)
|
||||
|
||||
Enhancements:
|
||||
* [#975][]: Avoid panicking in Sampler core if the level is out of bounds.
|
||||
* [#984][]: Reduce the size of BufferedWriteSyncer by aligning the fields
|
||||
better.
|
||||
|
||||
[#975]: https://github.com/uber-go/zap/pull/975
|
||||
[#984]: https://github.com/uber-go/zap/pull/984
|
||||
|
||||
Thanks to @lancoLiu and @thockin for their contributions to this release.
|
||||
|
||||
## 1.18.1 (28 Jun 2021)
|
||||
|
||||
Bugfixes:
|
||||
* [#974][]: Fix nil dereference in logger constructed by `zap.NewNop`.
|
||||
|
||||
[#974]: https://github.com/uber-go/zap/pull/974
|
||||
|
||||
## 1.18.0 (28 Jun 2021)
|
||||
|
||||
Enhancements:
|
||||
* [#961][]: Add `zapcore.BufferedWriteSyncer`, a new `WriteSyncer` that buffers
|
||||
messages in-memory and flushes them periodically.
|
||||
* [#971][]: Add `zapio.Writer` to use a Zap logger as an `io.Writer`.
|
||||
* [#897][]: Add `zap.WithClock` option to control the source of time via the
|
||||
new `zapcore.Clock` interface.
|
||||
* [#949][]: Avoid panicking in `zap.SugaredLogger` when arguments of `*w`
|
||||
methods don't match expectations.
|
||||
* [#943][]: Add support for filtering by level or arbitrary matcher function to
|
||||
`zaptest/observer`.
|
||||
* [#691][]: Comply with `io.StringWriter` and `io.ByteWriter` in Zap's
|
||||
`buffer.Buffer`.
|
||||
|
||||
Thanks to @atrn0, @ernado, @heyanfu, @hnlq715, @zchee
|
||||
for their contributions to this release.
|
||||
|
||||
[#691]: https://github.com/uber-go/zap/pull/691
|
||||
[#897]: https://github.com/uber-go/zap/pull/897
|
||||
[#943]: https://github.com/uber-go/zap/pull/943
|
||||
[#949]: https://github.com/uber-go/zap/pull/949
|
||||
[#961]: https://github.com/uber-go/zap/pull/961
|
||||
[#971]: https://github.com/uber-go/zap/pull/971
|
||||
|
||||
## 1.17.0 (25 May 2021)
|
||||
|
||||
Bugfixes:
|
||||
* [#867][]: Encode `<nil>` for nil `error` instead of a panic.
|
||||
* [#931][], [#936][]: Update minimum version constraints to address
|
||||
vulnerabilities in dependencies.
|
||||
|
||||
Enhancements:
|
||||
* [#865][]: Improve alignment of fields of the Logger struct, reducing its
|
||||
size from 96 to 80 bytes.
|
||||
* [#881][]: Support `grpclog.LoggerV2` in zapgrpc.
|
||||
* [#903][]: Support URL-encoded POST requests to the AtomicLevel HTTP handler
|
||||
with the `application/x-www-form-urlencoded` content type.
|
||||
* [#912][]: Support multi-field encoding with `zap.Inline`.
|
||||
* [#913][]: Speed up SugaredLogger for calls with a single string.
|
||||
* [#928][]: Add support for filtering by field name to `zaptest/observer`.
|
||||
|
||||
Thanks to @ash2k, @FMLS, @jimmystewpot, @Oncilla, @tsoslow, @tylitianrui, @withshubh, and @wziww for their contributions to this release.
|
||||
|
||||
## 1.16.0 (1 Sep 2020)
|
||||
|
||||
Bugfixes:
|
||||
* [#828][]: Fix missing newline in IncreaseLevel error messages.
|
||||
* [#835][]: Fix panic in JSON encoder when encoding times or durations
|
||||
without specifying a time or duration encoder.
|
||||
* [#843][]: Honor CallerSkip when taking stack traces.
|
||||
* [#862][]: Fix the default file permissions to use `0666` and rely on the umask instead.
|
||||
* [#854][]: Encode `<nil>` for nil `Stringer` instead of a panic error log.
|
||||
|
||||
Enhancements:
|
||||
* [#629][]: Added `zapcore.TimeEncoderOfLayout` to easily create time encoders
|
||||
for custom layouts.
|
||||
* [#697][]: Added support for a configurable delimiter in the console encoder.
|
||||
* [#852][]: Optimize console encoder by pooling the underlying JSON encoder.
|
||||
* [#844][]: Add ability to include the calling function as part of logs.
|
||||
* [#843][]: Add `StackSkip` for including truncated stacks as a field.
|
||||
* [#861][]: Add options to customize Fatal behaviour for better testability.
|
||||
|
||||
Thanks to @SteelPhase, @tmshn, @lixingwang, @wyxloading, @moul, @segevfiner, @andy-retailnext and @jcorbin for their contributions to this release.
|
||||
|
||||
## 1.15.0 (23 Apr 2020)
|
||||
|
||||
Bugfixes:
|
||||
* [#804][]: Fix handling of `Time` values out of `UnixNano` range.
|
||||
* [#812][]: Fix `IncreaseLevel` being reset after a call to `With`.
|
||||
|
||||
Enhancements:
|
||||
* [#806][]: Add `WithCaller` option to supersede the `AddCaller` option. This
|
||||
allows disabling annotation of log entries with caller information if
|
||||
previously enabled with `AddCaller`.
|
||||
* [#813][]: Deprecate `NewSampler` constructor in favor of
|
||||
`NewSamplerWithOptions` which supports a `SamplerHook` option. This option
|
||||
adds support for monitoring sampling decisions through a hook.
|
||||
|
||||
Thanks to @danielbprice for their contributions to this release.
|
||||
|
||||
## 1.14.1 (14 Mar 2020)
|
||||
|
||||
Bugfixes:
|
||||
* [#791][]: Fix panic on attempting to build a logger with an invalid Config.
|
||||
* [#795][]: Vendoring Zap with `go mod vendor` no longer includes Zap's
|
||||
development-time dependencies.
|
||||
* [#799][]: Fix issue introduced in 1.14.0 that caused invalid JSON output to
|
||||
be generated for arrays of `time.Time` objects when using string-based time
|
||||
formats.
|
||||
|
||||
Thanks to @YashishDua for their contributions to this release.
|
||||
|
||||
## 1.14.0 (20 Feb 2020)
|
||||
|
||||
Enhancements:
|
||||
* [#771][]: Optimize calls for disabled log levels.
|
||||
* [#773][]: Add millisecond duration encoder.
|
||||
* [#775][]: Add option to increase the level of a logger.
|
||||
* [#786][]: Optimize time formatters using `Time.AppendFormat` where possible.
|
||||
|
||||
Thanks to @caibirdme for their contributions to this release.
|
||||
|
||||
## 1.13.0 (13 Nov 2019)
|
||||
|
||||
Enhancements:
|
||||
* [#758][]: Add `Intp`, `Stringp`, and other similar `*p` field constructors
|
||||
to log pointers to primitives with support for `nil` values.
|
||||
|
||||
Thanks to @jbizzle for their contributions to this release.
|
||||
|
||||
## 1.12.0 (29 Oct 2019)
|
||||
|
||||
Enhancements:
|
||||
* [#751][]: Migrate to Go modules.
|
||||
|
||||
## 1.11.0 (21 Oct 2019)
|
||||
|
||||
Enhancements:
|
||||
* [#725][]: Add `zapcore.OmitKey` to omit keys in an `EncoderConfig`.
|
||||
* [#736][]: Add `RFC3339` and `RFC3339Nano` time encoders.
|
||||
|
||||
Thanks to @juicemia, @uhthomas for their contributions to this release.
|
||||
|
||||
## 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:
|
||||
|
||||
* [#614][]: MapObjectEncoder should not ignore empty slices.
|
||||
|
||||
## v1.9.0 (19 Jul 2018)
|
||||
|
||||
Enhancements:
|
||||
* [#602][]: Reduce number of allocations when logging with reflection.
|
||||
* [#572][], [#606][]: Expose a registry for third-party logging sinks.
|
||||
|
||||
Thanks to @nfarah86, @AlekSi, @JeanMertz, @philippgille, @etsangsplk, and
|
||||
@dimroc for their contributions to this release.
|
||||
|
||||
## v1.8.0 (13 Apr 2018)
|
||||
|
||||
Enhancements:
|
||||
* [#508][]: Make log level configurable when redirecting the standard
|
||||
library's logger.
|
||||
* [#518][]: Add a logger that writes to a `*testing.TB`.
|
||||
* [#577][]: Add a top-level alias for `zapcore.Field` to clean up GoDoc.
|
||||
|
||||
Bugfixes:
|
||||
* [#574][]: Add a missing import comment to `go.uber.org/zap/buffer`.
|
||||
|
||||
Thanks to @DiSiqueira and @djui for their contributions to this release.
|
||||
|
||||
## v1.7.1 (25 Sep 2017)
|
||||
|
||||
Bugfixes:
|
||||
* [#504][]: Store strings when using AddByteString with the map encoder.
|
||||
|
||||
## v1.7.0 (21 Sep 2017)
|
||||
|
||||
Enhancements:
|
||||
|
||||
* [#487][]: Add `NewStdLogAt`, which extends `NewStdLog` by allowing the user
|
||||
to specify the level of the logged messages.
|
||||
|
||||
## v1.6.0 (30 Aug 2017)
|
||||
|
||||
Enhancements:
|
||||
|
||||
* [#491][]: Omit zap stack frames from stacktraces.
|
||||
* [#490][]: Add a `ContextMap` method to observer logs for simpler
|
||||
field validation in tests.
|
||||
|
||||
## v1.5.0 (22 Jul 2017)
|
||||
|
||||
Enhancements:
|
||||
|
||||
* [#460][] and [#470][]: Support errors produced by `go.uber.org/multierr`.
|
||||
* [#465][]: Support user-supplied encoders for logger names.
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* [#477][]: Fix a bug that incorrectly truncated deep stacktraces.
|
||||
|
||||
Thanks to @richard-tunein and @pavius for their contributions to this release.
|
||||
|
||||
## v1.4.1 (08 Jun 2017)
|
||||
|
||||
This release fixes two bugs.
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* [#435][]: Support a variety of case conventions when unmarshaling levels.
|
||||
* [#444][]: Fix a panic in the observer.
|
||||
|
||||
## v1.4.0 (12 May 2017)
|
||||
|
||||
This release adds a few small features and is fully backward-compatible.
|
||||
|
||||
Enhancements:
|
||||
|
||||
* [#424][]: Add a `LineEnding` field to `EncoderConfig`, allowing users to
|
||||
override the Unix-style default.
|
||||
* [#425][]: Preserve time zones when logging times.
|
||||
* [#431][]: Make `zap.AtomicLevel` implement `fmt.Stringer`, which makes a
|
||||
variety of operations a bit simpler.
|
||||
|
||||
## v1.3.0 (25 Apr 2017)
|
||||
|
||||
This release adds an enhancement to zap's testing helpers as well as the
|
||||
ability to marshal an AtomicLevel. It is fully backward-compatible.
|
||||
|
||||
Enhancements:
|
||||
|
||||
* [#415][]: Add a substring-filtering helper to zap's observer. This is
|
||||
particularly useful when testing the `SugaredLogger`.
|
||||
* [#416][]: Make `AtomicLevel` implement `encoding.TextMarshaler`.
|
||||
|
||||
## v1.2.0 (13 Apr 2017)
|
||||
|
||||
This release adds a gRPC compatibility wrapper. It is fully backward-compatible.
|
||||
|
||||
Enhancements:
|
||||
|
||||
* [#402][]: Add a `zapgrpc` package that wraps zap's Logger and implements
|
||||
`grpclog.Logger`.
|
||||
|
||||
## v1.1.0 (31 Mar 2017)
|
||||
|
||||
This release fixes two bugs and adds some enhancements to zap's testing helpers.
|
||||
It is fully backward-compatible.
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* [#385][]: Fix caller path trimming on Windows.
|
||||
* [#396][]: Fix a panic when attempting to use non-existent directories with
|
||||
zap's configuration struct.
|
||||
|
||||
Enhancements:
|
||||
|
||||
* [#386][]: Add filtering helpers to zaptest's observing logger.
|
||||
|
||||
Thanks to @moitias for contributing to this release.
|
||||
|
||||
## v1.0.0 (14 Mar 2017)
|
||||
|
||||
This is zap's first stable release. All exported APIs are now final, and no
|
||||
further breaking changes will be made in the 1.x release series. Anyone using a
|
||||
semver-aware dependency manager should now pin to `^1`.
|
||||
|
||||
Breaking changes:
|
||||
|
||||
* [#366][]: Add byte-oriented APIs to encoders to log UTF-8 encoded text without
|
||||
casting from `[]byte` to `string`.
|
||||
* [#364][]: To support buffering outputs, add `Sync` methods to `zapcore.Core`,
|
||||
`zap.Logger`, and `zap.SugaredLogger`.
|
||||
* [#371][]: Rename the `testutils` package to `zaptest`, which is less likely to
|
||||
clash with other testing helpers.
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* [#362][]: Make the ISO8601 time formatters fixed-width, which is friendlier
|
||||
for tab-separated console output.
|
||||
* [#369][]: Remove the automatic locks in `zapcore.NewCore`, which allows zap to
|
||||
work with concurrency-safe `WriteSyncer` implementations.
|
||||
* [#347][]: Stop reporting errors when trying to `fsync` standard out on Linux
|
||||
systems.
|
||||
* [#373][]: Report the correct caller from zap's standard library
|
||||
interoperability wrappers.
|
||||
|
||||
Enhancements:
|
||||
|
||||
* [#348][]: Add a registry allowing third-party encodings to work with zap's
|
||||
built-in `Config`.
|
||||
* [#327][]: Make the representation of logger callers configurable (like times,
|
||||
levels, and durations).
|
||||
* [#376][]: Allow third-party encoders to use their own buffer pools, which
|
||||
removes the last performance advantage that zap's encoders have over plugins.
|
||||
* [#346][]: Add `CombineWriteSyncers`, a convenience function to tee multiple
|
||||
`WriteSyncer`s and lock the result.
|
||||
* [#365][]: Make zap's stacktraces compatible with mid-stack inlining (coming in
|
||||
Go 1.9).
|
||||
* [#372][]: Export zap's observing logger as `zaptest/observer`. This makes it
|
||||
easier for particularly punctilious users to unit test their application's
|
||||
logging.
|
||||
|
||||
Thanks to @suyash, @htrendev, @flisky, @Ulexus, and @skipor for their
|
||||
contributions to this release.
|
||||
|
||||
## v1.0.0-rc.3 (7 Mar 2017)
|
||||
|
||||
This is the third release candidate for zap's stable release. There are no
|
||||
breaking changes.
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* [#339][]: Byte slices passed to `zap.Any` are now correctly treated as binary blobs
|
||||
rather than `[]uint8`.
|
||||
|
||||
Enhancements:
|
||||
|
||||
* [#307][]: Users can opt into colored output for log levels.
|
||||
* [#353][]: In addition to hijacking the output of the standard library's
|
||||
package-global logging functions, users can now construct a zap-backed
|
||||
`log.Logger` instance.
|
||||
* [#311][]: Frames from common runtime functions and some of zap's internal
|
||||
machinery are now omitted from stacktraces.
|
||||
|
||||
Thanks to @ansel1 and @suyash for their contributions to this release.
|
||||
|
||||
## v1.0.0-rc.2 (21 Feb 2017)
|
||||
|
||||
This is the second release candidate for zap's stable release. It includes two
|
||||
breaking changes.
|
||||
|
||||
Breaking changes:
|
||||
|
||||
* [#316][]: Zap's global loggers are now fully concurrency-safe
|
||||
(previously, users had to ensure that `ReplaceGlobals` was called before the
|
||||
loggers were in use). However, they must now be accessed via the `L()` and
|
||||
`S()` functions. Users can update their projects with
|
||||
|
||||
```
|
||||
gofmt -r "zap.L -> zap.L()" -w .
|
||||
gofmt -r "zap.S -> zap.S()" -w .
|
||||
```
|
||||
* [#309][] and [#317][]: RC1 was mistakenly shipped with invalid
|
||||
JSON and YAML struct tags on all config structs. This release fixes the tags
|
||||
and adds static analysis to prevent similar bugs in the future.
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* [#321][]: Redirecting the standard library's `log` output now
|
||||
correctly reports the logger's caller.
|
||||
|
||||
Enhancements:
|
||||
|
||||
* [#325][] and [#333][]: Zap now transparently supports non-standard, rich
|
||||
errors like those produced by `github.com/pkg/errors`.
|
||||
* [#326][]: Though `New(nil)` continues to return a no-op logger, `NewNop()` is
|
||||
now preferred. Users can update their projects with `gofmt -r 'zap.New(nil) ->
|
||||
zap.NewNop()' -w .`.
|
||||
* [#300][]: Incorrectly importing zap as `github.com/uber-go/zap` now returns a
|
||||
more informative error.
|
||||
|
||||
Thanks to @skipor and @chapsuk for their contributions to this release.
|
||||
|
||||
## v1.0.0-rc.1 (14 Feb 2017)
|
||||
|
||||
This is the first release candidate for zap's stable release. There are multiple
|
||||
breaking changes and improvements from the pre-release version. Most notably:
|
||||
|
||||
* **Zap's import path is now "go.uber.org/zap"** — all users will
|
||||
need to update their code.
|
||||
* User-facing types and functions remain in the `zap` package. Code relevant
|
||||
largely to extension authors is now in the `zapcore` package.
|
||||
* The `zapcore.Core` type makes it easy for third-party packages to use zap's
|
||||
internals but provide a different user-facing API.
|
||||
* `Logger` is now a concrete type instead of an interface.
|
||||
* A less verbose (though slower) logging API is included by default.
|
||||
* Package-global loggers `L` and `S` are included.
|
||||
* A human-friendly console encoder is included.
|
||||
* A declarative config struct allows common logger configurations to be managed
|
||||
as configuration instead of code.
|
||||
* Sampling is more accurate, and doesn't depend on the standard library's shared
|
||||
timer heap.
|
||||
|
||||
## v0.1.0-beta.1 (6 Feb 2017)
|
||||
|
||||
This is a minor version, tagged to allow users to pin to the pre-1.0 APIs and
|
||||
upgrade at their leisure. Since this is the first tagged release, there are no
|
||||
backward compatibility concerns and all functionality is new.
|
||||
|
||||
Early zap adopters should pin to the 0.1.x minor version until they're ready to
|
||||
upgrade to the upcoming stable release.
|
||||
|
||||
[#316]: https://github.com/uber-go/zap/pull/316
|
||||
[#309]: https://github.com/uber-go/zap/pull/309
|
||||
[#317]: https://github.com/uber-go/zap/pull/317
|
||||
[#321]: https://github.com/uber-go/zap/pull/321
|
||||
[#325]: https://github.com/uber-go/zap/pull/325
|
||||
[#333]: https://github.com/uber-go/zap/pull/333
|
||||
[#326]: https://github.com/uber-go/zap/pull/326
|
||||
[#300]: https://github.com/uber-go/zap/pull/300
|
||||
[#339]: https://github.com/uber-go/zap/pull/339
|
||||
[#307]: https://github.com/uber-go/zap/pull/307
|
||||
[#353]: https://github.com/uber-go/zap/pull/353
|
||||
[#311]: https://github.com/uber-go/zap/pull/311
|
||||
[#366]: https://github.com/uber-go/zap/pull/366
|
||||
[#364]: https://github.com/uber-go/zap/pull/364
|
||||
[#371]: https://github.com/uber-go/zap/pull/371
|
||||
[#362]: https://github.com/uber-go/zap/pull/362
|
||||
[#369]: https://github.com/uber-go/zap/pull/369
|
||||
[#347]: https://github.com/uber-go/zap/pull/347
|
||||
[#373]: https://github.com/uber-go/zap/pull/373
|
||||
[#348]: https://github.com/uber-go/zap/pull/348
|
||||
[#327]: https://github.com/uber-go/zap/pull/327
|
||||
[#376]: https://github.com/uber-go/zap/pull/376
|
||||
[#346]: https://github.com/uber-go/zap/pull/346
|
||||
[#365]: https://github.com/uber-go/zap/pull/365
|
||||
[#372]: https://github.com/uber-go/zap/pull/372
|
||||
[#385]: https://github.com/uber-go/zap/pull/385
|
||||
[#396]: https://github.com/uber-go/zap/pull/396
|
||||
[#386]: https://github.com/uber-go/zap/pull/386
|
||||
[#402]: https://github.com/uber-go/zap/pull/402
|
||||
[#415]: https://github.com/uber-go/zap/pull/415
|
||||
[#416]: https://github.com/uber-go/zap/pull/416
|
||||
[#424]: https://github.com/uber-go/zap/pull/424
|
||||
[#425]: https://github.com/uber-go/zap/pull/425
|
||||
[#431]: https://github.com/uber-go/zap/pull/431
|
||||
[#435]: https://github.com/uber-go/zap/pull/435
|
||||
[#444]: https://github.com/uber-go/zap/pull/444
|
||||
[#477]: https://github.com/uber-go/zap/pull/477
|
||||
[#465]: https://github.com/uber-go/zap/pull/465
|
||||
[#460]: https://github.com/uber-go/zap/pull/460
|
||||
[#470]: https://github.com/uber-go/zap/pull/470
|
||||
[#487]: https://github.com/uber-go/zap/pull/487
|
||||
[#490]: https://github.com/uber-go/zap/pull/490
|
||||
[#491]: https://github.com/uber-go/zap/pull/491
|
||||
[#504]: https://github.com/uber-go/zap/pull/504
|
||||
[#508]: https://github.com/uber-go/zap/pull/508
|
||||
[#518]: https://github.com/uber-go/zap/pull/518
|
||||
[#577]: https://github.com/uber-go/zap/pull/577
|
||||
[#574]: https://github.com/uber-go/zap/pull/574
|
||||
[#602]: https://github.com/uber-go/zap/pull/602
|
||||
[#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
|
||||
[#725]: https://github.com/uber-go/zap/pull/725
|
||||
[#736]: https://github.com/uber-go/zap/pull/736
|
||||
[#751]: https://github.com/uber-go/zap/pull/751
|
||||
[#758]: https://github.com/uber-go/zap/pull/758
|
||||
[#771]: https://github.com/uber-go/zap/pull/771
|
||||
[#773]: https://github.com/uber-go/zap/pull/773
|
||||
[#775]: https://github.com/uber-go/zap/pull/775
|
||||
[#786]: https://github.com/uber-go/zap/pull/786
|
||||
[#791]: https://github.com/uber-go/zap/pull/791
|
||||
[#795]: https://github.com/uber-go/zap/pull/795
|
||||
[#799]: https://github.com/uber-go/zap/pull/799
|
||||
[#804]: https://github.com/uber-go/zap/pull/804
|
||||
[#812]: https://github.com/uber-go/zap/pull/812
|
||||
[#806]: https://github.com/uber-go/zap/pull/806
|
||||
[#813]: https://github.com/uber-go/zap/pull/813
|
||||
[#629]: https://github.com/uber-go/zap/pull/629
|
||||
[#697]: https://github.com/uber-go/zap/pull/697
|
||||
[#828]: https://github.com/uber-go/zap/pull/828
|
||||
[#835]: https://github.com/uber-go/zap/pull/835
|
||||
[#843]: https://github.com/uber-go/zap/pull/843
|
||||
[#844]: https://github.com/uber-go/zap/pull/844
|
||||
[#852]: https://github.com/uber-go/zap/pull/852
|
||||
[#854]: https://github.com/uber-go/zap/pull/854
|
||||
[#861]: https://github.com/uber-go/zap/pull/861
|
||||
[#862]: https://github.com/uber-go/zap/pull/862
|
||||
[#865]: https://github.com/uber-go/zap/pull/865
|
||||
[#867]: https://github.com/uber-go/zap/pull/867
|
||||
[#881]: https://github.com/uber-go/zap/pull/881
|
||||
[#903]: https://github.com/uber-go/zap/pull/903
|
||||
[#912]: https://github.com/uber-go/zap/pull/912
|
||||
[#913]: https://github.com/uber-go/zap/pull/913
|
||||
[#928]: https://github.com/uber-go/zap/pull/928
|
||||
[#931]: https://github.com/uber-go/zap/pull/931
|
||||
[#936]: https://github.com/uber-go/zap/pull/936
|
75
vendor/go.uber.org/zap/CODE_OF_CONDUCT.md
generated
vendored
Normal file
75
vendor/go.uber.org/zap/CODE_OF_CONDUCT.md
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age,
|
||||
body size, disability, ethnicity, gender identity and expression, level of
|
||||
experience, nationality, personal appearance, race, religion, or sexual
|
||||
identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an
|
||||
appointed representative at an online or offline event. Representation of a
|
||||
project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at oss-conduct@uber.com. The project
|
||||
team will review and investigate all complaints, and will respond in a way
|
||||
that it deems appropriate to the circumstances. The project team is obligated
|
||||
to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 1.4, available at
|
||||
[http://contributor-covenant.org/version/1/4][version].
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
75
vendor/go.uber.org/zap/CONTRIBUTING.md
generated
vendored
Normal file
75
vendor/go.uber.org/zap/CONTRIBUTING.md
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
# Contributing
|
||||
|
||||
We'd love your help making zap the very best structured logging library in Go!
|
||||
|
||||
If you'd like to add new exported APIs, please [open an issue][open-issue]
|
||||
describing your proposal — discussing API changes ahead of time makes
|
||||
pull request review much smoother. In your issue, pull request, and any other
|
||||
communications, please remember to treat your fellow contributors with
|
||||
respect! We take our [code of conduct](CODE_OF_CONDUCT.md) seriously.
|
||||
|
||||
Note that you'll need to sign [Uber's Contributor License Agreement][cla]
|
||||
before we can accept any of your contributions. If necessary, a bot will remind
|
||||
you to accept the CLA when you open your pull request.
|
||||
|
||||
## Setup
|
||||
|
||||
[Fork][fork], then clone the repository:
|
||||
|
||||
```
|
||||
mkdir -p $GOPATH/src/go.uber.org
|
||||
cd $GOPATH/src/go.uber.org
|
||||
git clone git@github.com:your_github_username/zap.git
|
||||
cd zap
|
||||
git remote add upstream https://github.com/uber-go/zap.git
|
||||
git fetch upstream
|
||||
```
|
||||
|
||||
Make sure that the tests and the linters pass:
|
||||
|
||||
```
|
||||
make test
|
||||
make lint
|
||||
```
|
||||
|
||||
If you're not using the minor version of Go specified in the Makefile's
|
||||
`LINTABLE_MINOR_VERSIONS` variable, `make lint` doesn't do anything. This is
|
||||
fine, but it means that you'll only discover lint failures after you open your
|
||||
pull request.
|
||||
|
||||
## Making Changes
|
||||
|
||||
Start by creating a new branch for your changes:
|
||||
|
||||
```
|
||||
cd $GOPATH/src/go.uber.org/zap
|
||||
git checkout master
|
||||
git fetch upstream
|
||||
git rebase upstream/master
|
||||
git checkout -b cool_new_feature
|
||||
```
|
||||
|
||||
Make your changes, then ensure that `make lint` and `make test` still pass. If
|
||||
you're satisfied with your changes, push them to your fork.
|
||||
|
||||
```
|
||||
git push origin cool_new_feature
|
||||
```
|
||||
|
||||
Then use the GitHub UI to open a pull request.
|
||||
|
||||
At this point, you're waiting on us to review your changes. We *try* to respond
|
||||
to issues and pull requests within a few business days, and we may suggest some
|
||||
improvements or alternatives. Once your changes are approved, one of the
|
||||
project maintainers will merge them.
|
||||
|
||||
We're much more likely to approve your changes if you:
|
||||
|
||||
* Add tests for new functionality.
|
||||
* Write a [good commit message][commit-message].
|
||||
* Maintain backward compatibility.
|
||||
|
||||
[fork]: https://github.com/uber-go/zap/fork
|
||||
[open-issue]: https://github.com/uber-go/zap/issues/new
|
||||
[cla]: https://cla-assistant.io/uber-go/zap
|
||||
[commit-message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
164
vendor/go.uber.org/zap/FAQ.md
generated
vendored
Normal file
164
vendor/go.uber.org/zap/FAQ.md
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
# Frequently Asked Questions
|
||||
|
||||
## Design
|
||||
|
||||
### Why spend so much effort on logger performance?
|
||||
|
||||
Of course, most applications won't notice the impact of a slow logger: they
|
||||
already take tens or hundreds of milliseconds for each operation, so an extra
|
||||
millisecond doesn't matter.
|
||||
|
||||
On the other hand, why *not* make structured logging fast? The `SugaredLogger`
|
||||
isn't any harder to use than other logging packages, and the `Logger` makes
|
||||
structured logging possible in performance-sensitive contexts. Across a fleet
|
||||
of Go microservices, making each application even slightly more efficient adds
|
||||
up quickly.
|
||||
|
||||
### Why aren't `Logger` and `SugaredLogger` interfaces?
|
||||
|
||||
Unlike the familiar `io.Writer` and `http.Handler`, `Logger` and
|
||||
`SugaredLogger` interfaces would include *many* methods. As [Rob Pike points
|
||||
out][go-proverbs], "The bigger the interface, the weaker the abstraction."
|
||||
Interfaces are also rigid — *any* change requires releasing a new major
|
||||
version, since it breaks all third-party implementations.
|
||||
|
||||
Making the `Logger` and `SugaredLogger` concrete types doesn't sacrifice much
|
||||
abstraction, and it lets us add methods without introducing breaking changes.
|
||||
Your applications should define and depend upon an interface that includes
|
||||
just the methods you use.
|
||||
|
||||
### Why are some of my logs missing?
|
||||
|
||||
Logs are dropped intentionally by zap when sampling is enabled. The production
|
||||
configuration (as returned by `NewProductionConfig()` enables sampling which will
|
||||
cause repeated logs within a second to be sampled. See more details on why sampling
|
||||
is enabled in [Why sample application logs](https://github.com/uber-go/zap/blob/master/FAQ.md#why-sample-application-logs).
|
||||
|
||||
### Why sample application logs?
|
||||
|
||||
Applications often experience runs of errors, either because of a bug or
|
||||
because of a misbehaving user. Logging errors is usually a good idea, but it
|
||||
can easily make this bad situation worse: not only is your application coping
|
||||
with a flood of errors, it's also spending extra CPU cycles and I/O logging
|
||||
those errors. Since writes are typically serialized, logging limits throughput
|
||||
when you need it most.
|
||||
|
||||
Sampling fixes this problem by dropping repetitive log entries. Under normal
|
||||
conditions, your application writes out every entry. When similar entries are
|
||||
logged hundreds or thousands of times each second, though, zap begins dropping
|
||||
duplicates to preserve throughput.
|
||||
|
||||
### Why do the structured logging APIs take a message in addition to fields?
|
||||
|
||||
Subjectively, we find it helpful to accompany structured context with a brief
|
||||
description. This isn't critical during development, but it makes debugging
|
||||
and operating unfamiliar systems much easier.
|
||||
|
||||
More concretely, zap's sampling algorithm uses the message to identify
|
||||
duplicate entries. In our experience, this is a practical middle ground
|
||||
between random sampling (which often drops the exact entry that you need while
|
||||
debugging) and hashing the complete entry (which is prohibitively expensive).
|
||||
|
||||
### Why include package-global loggers?
|
||||
|
||||
Since so many other logging packages include a global logger, many
|
||||
applications aren't designed to accept loggers as explicit parameters.
|
||||
Changing function signatures is often a breaking change, so zap includes
|
||||
global loggers to simplify migration.
|
||||
|
||||
Avoid them where possible.
|
||||
|
||||
### Why include dedicated Panic and Fatal log levels?
|
||||
|
||||
In general, application code should handle errors gracefully instead of using
|
||||
`panic` or `os.Exit`. However, every rule has exceptions, and it's common to
|
||||
crash when an error is truly unrecoverable. To avoid losing any information
|
||||
— especially the reason for the crash — the logger must flush any
|
||||
buffered entries before the process exits.
|
||||
|
||||
Zap makes this easy by offering `Panic` and `Fatal` logging methods that
|
||||
automatically flush before exiting. Of course, this doesn't guarantee that
|
||||
logs will never be lost, but it eliminates a common error.
|
||||
|
||||
See the discussion in uber-go/zap#207 for more details.
|
||||
|
||||
### What's `DPanic`?
|
||||
|
||||
`DPanic` stands for "panic in development." In development, it logs at
|
||||
`PanicLevel`; otherwise, it logs at `ErrorLevel`. `DPanic` makes it easier to
|
||||
catch errors that are theoretically possible, but shouldn't actually happen,
|
||||
*without* crashing in production.
|
||||
|
||||
If you've ever written code like this, you need `DPanic`:
|
||||
|
||||
```go
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("shouldn't ever get here: %v", err))
|
||||
}
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
### What does the error `expects import "go.uber.org/zap"` mean?
|
||||
|
||||
Either zap was installed incorrectly or you're referencing the wrong package
|
||||
name in your code.
|
||||
|
||||
Zap's source code happens to be hosted on GitHub, but the [import
|
||||
path][import-path] is `go.uber.org/zap`. This gives us, the project
|
||||
maintainers, the freedom to move the source code if necessary. However, it
|
||||
means that you need to take a little care when installing and using the
|
||||
package.
|
||||
|
||||
If you follow two simple rules, everything should work: install zap with `go
|
||||
get -u go.uber.org/zap`, and always import it in your code with `import
|
||||
"go.uber.org/zap"`. Your code shouldn't contain *any* references to
|
||||
`github.com/uber-go/zap`.
|
||||
|
||||
## Usage
|
||||
|
||||
### Does zap support log rotation?
|
||||
|
||||
Zap doesn't natively support rotating log files, since we prefer to leave this
|
||||
to an external program like `logrotate`.
|
||||
|
||||
However, it's easy to integrate a log rotation package like
|
||||
[`gopkg.in/natefinch/lumberjack.v2`][lumberjack] as a `zapcore.WriteSyncer`.
|
||||
|
||||
```go
|
||||
// lumberjack.Logger is already safe for concurrent use, so we don't need to
|
||||
// lock it.
|
||||
w := zapcore.AddSync(&lumberjack.Logger{
|
||||
Filename: "/var/log/myapp/foo.log",
|
||||
MaxSize: 500, // megabytes
|
||||
MaxBackups: 3,
|
||||
MaxAge: 28, // days
|
||||
})
|
||||
core := zapcore.NewCore(
|
||||
zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
|
||||
w,
|
||||
zap.InfoLevel,
|
||||
)
|
||||
logger := zap.New(core)
|
||||
```
|
||||
|
||||
## Extensions
|
||||
|
||||
We'd love to support every logging need within zap itself, but we're only
|
||||
familiar with a handful of log ingestion systems, flag-parsing packages, and
|
||||
the like. Rather than merging code that we can't effectively debug and
|
||||
support, we'd rather grow an ecosystem of zap extensions.
|
||||
|
||||
We're aware of the following extensions, but haven't used them ourselves:
|
||||
|
||||
| Package | Integration |
|
||||
| --- | --- |
|
||||
| `github.com/tchap/zapext` | Sentry, syslog |
|
||||
| `github.com/fgrosse/zaptest` | Ginkgo |
|
||||
| `github.com/blendle/zapdriver` | Stackdriver |
|
||||
| `github.com/moul/zapgorm` | Gorm |
|
||||
| `github.com/moul/zapfilter` | Advanced filtering rules |
|
||||
|
||||
[go-proverbs]: https://go-proverbs.github.io/
|
||||
[import-path]: https://golang.org/cmd/go/#hdr-Remote_import_paths
|
||||
[lumberjack]: https://godoc.org/gopkg.in/natefinch/lumberjack.v2
|
19
vendor/go.uber.org/zap/LICENSE.txt
generated
vendored
Normal file
19
vendor/go.uber.org/zap/LICENSE.txt
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2016-2017 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.
|
73
vendor/go.uber.org/zap/Makefile
generated
vendored
Normal file
73
vendor/go.uber.org/zap/Makefile
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
export GOBIN ?= $(shell pwd)/bin
|
||||
|
||||
GOLINT = $(GOBIN)/golint
|
||||
STATICCHECK = $(GOBIN)/staticcheck
|
||||
BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem
|
||||
|
||||
# Directories containing independent Go modules.
|
||||
#
|
||||
# We track coverage only for the main module.
|
||||
MODULE_DIRS = . ./benchmarks ./zapgrpc/internal/test
|
||||
|
||||
# Many Go tools take file globs or directories as arguments instead of packages.
|
||||
GO_FILES := $(shell \
|
||||
find . '(' -path '*/.*' -o -path './vendor' ')' -prune \
|
||||
-o -name '*.go' -print | cut -b3-)
|
||||
|
||||
.PHONY: all
|
||||
all: lint test
|
||||
|
||||
.PHONY: lint
|
||||
lint: $(GOLINT) $(STATICCHECK)
|
||||
@rm -rf lint.log
|
||||
@echo "Checking formatting..."
|
||||
@gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log
|
||||
@echo "Checking vet..."
|
||||
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go vet ./... 2>&1) &&) true | tee -a lint.log
|
||||
@echo "Checking lint..."
|
||||
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(GOLINT) ./... 2>&1) &&) true | tee -a lint.log
|
||||
@echo "Checking staticcheck..."
|
||||
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(STATICCHECK) ./... 2>&1) &&) true | tee -a lint.log
|
||||
@echo "Checking for unresolved FIXMEs..."
|
||||
@git grep -i fixme | grep -v -e Makefile | tee -a lint.log
|
||||
@echo "Checking for license headers..."
|
||||
@./checklicense.sh | tee -a lint.log
|
||||
@[ ! -s lint.log ]
|
||||
@echo "Checking 'go mod tidy'..."
|
||||
@make tidy
|
||||
@if ! git diff --quiet; then \
|
||||
echo "'go mod tidy' resulted in changes or working tree is dirty:"; \
|
||||
git --no-pager diff; \
|
||||
fi
|
||||
|
||||
$(GOLINT):
|
||||
cd tools && go install golang.org/x/lint/golint
|
||||
|
||||
$(STATICCHECK):
|
||||
cd tools && go install honnef.co/go/tools/cmd/staticcheck
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go test -race ./...) &&) true
|
||||
|
||||
.PHONY: cover
|
||||
cover:
|
||||
go test -race -coverprofile=cover.out -coverpkg=./... ./...
|
||||
go tool cover -html=cover.out -o cover.html
|
||||
|
||||
.PHONY: bench
|
||||
BENCH ?= .
|
||||
bench:
|
||||
@$(foreach dir,$(MODULE_DIRS), ( \
|
||||
cd $(dir) && \
|
||||
go list ./... | xargs -n1 go test -bench=$(BENCH) -run="^$$" $(BENCH_FLAGS) \
|
||||
) &&) true
|
||||
|
||||
.PHONY: updatereadme
|
||||
updatereadme:
|
||||
rm -f README.md
|
||||
cat .readme.tmpl | go run internal/readme/readme.go > README.md
|
||||
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go mod tidy) &&) true
|
134
vendor/go.uber.org/zap/README.md
generated
vendored
Normal file
134
vendor/go.uber.org/zap/README.md
generated
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
# :zap: zap [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
|
||||
|
||||
Blazing fast, structured, leveled logging in Go.
|
||||
|
||||
## Installation
|
||||
|
||||
`go get -u go.uber.org/zap`
|
||||
|
||||
Note that zap only supports the two most recent minor versions of Go.
|
||||
|
||||
## Quick Start
|
||||
|
||||
In contexts where performance is nice, but not critical, use the
|
||||
`SugaredLogger`. It's 4-10x faster than other structured logging
|
||||
packages and includes both structured and `printf`-style APIs.
|
||||
|
||||
```go
|
||||
logger, _ := zap.NewProduction()
|
||||
defer logger.Sync() // flushes buffer, if any
|
||||
sugar := logger.Sugar()
|
||||
sugar.Infow("failed to fetch URL",
|
||||
// Structured context as loosely typed key-value pairs.
|
||||
"url", url,
|
||||
"attempt", 3,
|
||||
"backoff", time.Second,
|
||||
)
|
||||
sugar.Infof("Failed to fetch URL: %s", url)
|
||||
```
|
||||
|
||||
When performance and type safety are critical, use the `Logger`. It's even
|
||||
faster than the `SugaredLogger` and allocates far less, but it only supports
|
||||
structured logging.
|
||||
|
||||
```go
|
||||
logger, _ := zap.NewProduction()
|
||||
defer logger.Sync()
|
||||
logger.Info("failed to fetch URL",
|
||||
// Structured context as strongly typed Field values.
|
||||
zap.String("url", url),
|
||||
zap.Int("attempt", 3),
|
||||
zap.Duration("backoff", time.Second),
|
||||
)
|
||||
```
|
||||
|
||||
See the [documentation][doc] and [FAQ](FAQ.md) for more details.
|
||||
|
||||
## Performance
|
||||
|
||||
For applications that log in the hot path, reflection-based serialization and
|
||||
string formatting are prohibitively expensive — they're CPU-intensive
|
||||
and make many small allocations. Put differently, using `encoding/json` and
|
||||
`fmt.Fprintf` to log tons of `interface{}`s makes your application slow.
|
||||
|
||||
Zap takes a different approach. It includes a reflection-free, zero-allocation
|
||||
JSON encoder, and the base `Logger` strives to avoid serialization overhead
|
||||
and allocations wherever possible. By building the high-level `SugaredLogger`
|
||||
on that foundation, zap lets users *choose* when they need to count every
|
||||
allocation and when they'd prefer a more familiar, loosely typed API.
|
||||
|
||||
As measured by its own [benchmarking suite][], not only is zap more performant
|
||||
than comparable structured logging packages — it's also faster than the
|
||||
standard library. Like all benchmarks, take these with a grain of salt.<sup
|
||||
id="anchor-versions">[1](#footnote-versions)</sup>
|
||||
|
||||
Log a message and 10 fields:
|
||||
|
||||
| Package | Time | Time % to zap | Objects Allocated |
|
||||
| :------ | :--: | :-----------: | :---------------: |
|
||||
| :zap: zap | 862 ns/op | +0% | 5 allocs/op
|
||||
| :zap: zap (sugared) | 1250 ns/op | +45% | 11 allocs/op
|
||||
| zerolog | 4021 ns/op | +366% | 76 allocs/op
|
||||
| go-kit | 4542 ns/op | +427% | 105 allocs/op
|
||||
| apex/log | 26785 ns/op | +3007% | 115 allocs/op
|
||||
| logrus | 29501 ns/op | +3322% | 125 allocs/op
|
||||
| log15 | 29906 ns/op | +3369% | 122 allocs/op
|
||||
|
||||
Log a message with a logger that already has 10 fields of context:
|
||||
|
||||
| Package | Time | Time % to zap | Objects Allocated |
|
||||
| :------ | :--: | :-----------: | :---------------: |
|
||||
| :zap: zap | 126 ns/op | +0% | 0 allocs/op
|
||||
| :zap: zap (sugared) | 187 ns/op | +48% | 2 allocs/op
|
||||
| zerolog | 88 ns/op | -30% | 0 allocs/op
|
||||
| go-kit | 5087 ns/op | +3937% | 103 allocs/op
|
||||
| log15 | 18548 ns/op | +14621% | 73 allocs/op
|
||||
| apex/log | 26012 ns/op | +20544% | 104 allocs/op
|
||||
| logrus | 27236 ns/op | +21516% | 113 allocs/op
|
||||
|
||||
Log a static string, without any context or `printf`-style templating:
|
||||
|
||||
| Package | Time | Time % to zap | Objects Allocated |
|
||||
| :------ | :--: | :-----------: | :---------------: |
|
||||
| :zap: zap | 118 ns/op | +0% | 0 allocs/op
|
||||
| :zap: zap (sugared) | 191 ns/op | +62% | 2 allocs/op
|
||||
| zerolog | 93 ns/op | -21% | 0 allocs/op
|
||||
| go-kit | 280 ns/op | +137% | 11 allocs/op
|
||||
| standard library | 499 ns/op | +323% | 2 allocs/op
|
||||
| apex/log | 1990 ns/op | +1586% | 10 allocs/op
|
||||
| logrus | 3129 ns/op | +2552% | 24 allocs/op
|
||||
| log15 | 3887 ns/op | +3194% | 23 allocs/op
|
||||
|
||||
## Development Status: Stable
|
||||
|
||||
All APIs are finalized, and no breaking changes will be made in the 1.x series
|
||||
of releases. Users of semver-aware dependency management systems should pin
|
||||
zap to `^1`.
|
||||
|
||||
## Contributing
|
||||
|
||||
We encourage and support an active, healthy community of contributors —
|
||||
including you! Details are in the [contribution guide](CONTRIBUTING.md) and
|
||||
the [code of conduct](CODE_OF_CONDUCT.md). The zap maintainers keep an eye on
|
||||
issues and pull requests, but you can also report any negative conduct to
|
||||
oss-conduct@uber.com. That email list is a private, safe space; even the zap
|
||||
maintainers don't have access, so don't hesitate to hold us to a high
|
||||
standard.
|
||||
|
||||
<hr>
|
||||
|
||||
Released under the [MIT License](LICENSE.txt).
|
||||
|
||||
<sup id="footnote-versions">1</sup> In particular, keep in mind that we may be
|
||||
benchmarking against slightly older versions of other packages. Versions are
|
||||
pinned in the [benchmarks/go.mod][] file. [↩](#anchor-versions)
|
||||
|
||||
[doc-img]: https://pkg.go.dev/badge/go.uber.org/zap
|
||||
[doc]: https://pkg.go.dev/go.uber.org/zap
|
||||
[ci-img]: https://github.com/uber-go/zap/actions/workflows/go.yml/badge.svg
|
||||
[ci]: https://github.com/uber-go/zap/actions/workflows/go.yml
|
||||
[cov-img]: https://codecov.io/gh/uber-go/zap/branch/master/graph/badge.svg
|
||||
[cov]: https://codecov.io/gh/uber-go/zap
|
||||
[benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks
|
||||
[benchmarks/go.mod]: https://github.com/uber-go/zap/blob/master/benchmarks/go.mod
|
||||
|
320
vendor/go.uber.org/zap/array.go
generated
vendored
Normal file
320
vendor/go.uber.org/zap/array.go
generated
vendored
Normal file
@ -0,0 +1,320 @@
|
||||
// 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 zap
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// Array constructs a field with the given key and ArrayMarshaler. It provides
|
||||
// a flexible, but still type-safe and efficient, way to add array-like types
|
||||
// to the logging context. The struct's MarshalLogArray method is called lazily.
|
||||
func Array(key string, val zapcore.ArrayMarshaler) Field {
|
||||
return Field{Key: key, Type: zapcore.ArrayMarshalerType, Interface: val}
|
||||
}
|
||||
|
||||
// Bools constructs a field that carries a slice of bools.
|
||||
func Bools(key string, bs []bool) Field {
|
||||
return Array(key, bools(bs))
|
||||
}
|
||||
|
||||
// ByteStrings constructs a field that carries a slice of []byte, each of which
|
||||
// must be UTF-8 encoded text.
|
||||
func ByteStrings(key string, bss [][]byte) Field {
|
||||
return Array(key, byteStringsArray(bss))
|
||||
}
|
||||
|
||||
// Complex128s constructs a field that carries a slice of complex numbers.
|
||||
func Complex128s(key string, nums []complex128) Field {
|
||||
return Array(key, complex128s(nums))
|
||||
}
|
||||
|
||||
// Complex64s constructs a field that carries a slice of complex numbers.
|
||||
func Complex64s(key string, nums []complex64) Field {
|
||||
return Array(key, complex64s(nums))
|
||||
}
|
||||
|
||||
// Durations constructs a field that carries a slice of time.Durations.
|
||||
func Durations(key string, ds []time.Duration) Field {
|
||||
return Array(key, durations(ds))
|
||||
}
|
||||
|
||||
// Float64s constructs a field that carries a slice of floats.
|
||||
func Float64s(key string, nums []float64) Field {
|
||||
return Array(key, float64s(nums))
|
||||
}
|
||||
|
||||
// Float32s constructs a field that carries a slice of floats.
|
||||
func Float32s(key string, nums []float32) Field {
|
||||
return Array(key, float32s(nums))
|
||||
}
|
||||
|
||||
// Ints constructs a field that carries a slice of integers.
|
||||
func Ints(key string, nums []int) Field {
|
||||
return Array(key, ints(nums))
|
||||
}
|
||||
|
||||
// Int64s constructs a field that carries a slice of integers.
|
||||
func Int64s(key string, nums []int64) Field {
|
||||
return Array(key, int64s(nums))
|
||||
}
|
||||
|
||||
// Int32s constructs a field that carries a slice of integers.
|
||||
func Int32s(key string, nums []int32) Field {
|
||||
return Array(key, int32s(nums))
|
||||
}
|
||||
|
||||
// Int16s constructs a field that carries a slice of integers.
|
||||
func Int16s(key string, nums []int16) Field {
|
||||
return Array(key, int16s(nums))
|
||||
}
|
||||
|
||||
// Int8s constructs a field that carries a slice of integers.
|
||||
func Int8s(key string, nums []int8) Field {
|
||||
return Array(key, int8s(nums))
|
||||
}
|
||||
|
||||
// Strings constructs a field that carries a slice of strings.
|
||||
func Strings(key string, ss []string) Field {
|
||||
return Array(key, stringArray(ss))
|
||||
}
|
||||
|
||||
// Times constructs a field that carries a slice of time.Times.
|
||||
func Times(key string, ts []time.Time) Field {
|
||||
return Array(key, times(ts))
|
||||
}
|
||||
|
||||
// Uints constructs a field that carries a slice of unsigned integers.
|
||||
func Uints(key string, nums []uint) Field {
|
||||
return Array(key, uints(nums))
|
||||
}
|
||||
|
||||
// Uint64s constructs a field that carries a slice of unsigned integers.
|
||||
func Uint64s(key string, nums []uint64) Field {
|
||||
return Array(key, uint64s(nums))
|
||||
}
|
||||
|
||||
// Uint32s constructs a field that carries a slice of unsigned integers.
|
||||
func Uint32s(key string, nums []uint32) Field {
|
||||
return Array(key, uint32s(nums))
|
||||
}
|
||||
|
||||
// Uint16s constructs a field that carries a slice of unsigned integers.
|
||||
func Uint16s(key string, nums []uint16) Field {
|
||||
return Array(key, uint16s(nums))
|
||||
}
|
||||
|
||||
// Uint8s constructs a field that carries a slice of unsigned integers.
|
||||
func Uint8s(key string, nums []uint8) Field {
|
||||
return Array(key, uint8s(nums))
|
||||
}
|
||||
|
||||
// Uintptrs constructs a field that carries a slice of pointer addresses.
|
||||
func Uintptrs(key string, us []uintptr) Field {
|
||||
return Array(key, uintptrs(us))
|
||||
}
|
||||
|
||||
// Errors constructs a field that carries a slice of errors.
|
||||
func Errors(key string, errs []error) Field {
|
||||
return Array(key, errArray(errs))
|
||||
}
|
||||
|
||||
type bools []bool
|
||||
|
||||
func (bs bools) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range bs {
|
||||
arr.AppendBool(bs[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type byteStringsArray [][]byte
|
||||
|
||||
func (bss byteStringsArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range bss {
|
||||
arr.AppendByteString(bss[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type complex128s []complex128
|
||||
|
||||
func (nums complex128s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendComplex128(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type complex64s []complex64
|
||||
|
||||
func (nums complex64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendComplex64(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type durations []time.Duration
|
||||
|
||||
func (ds durations) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range ds {
|
||||
arr.AppendDuration(ds[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type float64s []float64
|
||||
|
||||
func (nums float64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendFloat64(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type float32s []float32
|
||||
|
||||
func (nums float32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendFloat32(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ints []int
|
||||
|
||||
func (nums ints) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendInt(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type int64s []int64
|
||||
|
||||
func (nums int64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendInt64(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type int32s []int32
|
||||
|
||||
func (nums int32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendInt32(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type int16s []int16
|
||||
|
||||
func (nums int16s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendInt16(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type int8s []int8
|
||||
|
||||
func (nums int8s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendInt8(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type stringArray []string
|
||||
|
||||
func (ss stringArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range ss {
|
||||
arr.AppendString(ss[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type times []time.Time
|
||||
|
||||
func (ts times) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range ts {
|
||||
arr.AppendTime(ts[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type uints []uint
|
||||
|
||||
func (nums uints) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendUint(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type uint64s []uint64
|
||||
|
||||
func (nums uint64s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendUint64(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type uint32s []uint32
|
||||
|
||||
func (nums uint32s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendUint32(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type uint16s []uint16
|
||||
|
||||
func (nums uint16s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendUint16(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type uint8s []uint8
|
||||
|
||||
func (nums uint8s) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendUint8(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type uintptrs []uintptr
|
||||
|
||||
func (nums uintptrs) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range nums {
|
||||
arr.AppendUintptr(nums[i])
|
||||
}
|
||||
return nil
|
||||
}
|
141
vendor/go.uber.org/zap/buffer/buffer.go
generated
vendored
Normal file
141
vendor/go.uber.org/zap/buffer/buffer.go
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
// 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 buffer provides a thin wrapper around a byte slice. Unlike the
|
||||
// standard library's bytes.Buffer, it supports a portion of the strconv
|
||||
// package's zero-allocation formatters.
|
||||
package buffer // import "go.uber.org/zap/buffer"
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
const _size = 1024 // by default, create 1 KiB buffers
|
||||
|
||||
// Buffer is a thin wrapper around a byte slice. It's intended to be pooled, so
|
||||
// the only way to construct one is via a Pool.
|
||||
type Buffer struct {
|
||||
bs []byte
|
||||
pool Pool
|
||||
}
|
||||
|
||||
// AppendByte writes a single byte to the Buffer.
|
||||
func (b *Buffer) AppendByte(v byte) {
|
||||
b.bs = append(b.bs, v)
|
||||
}
|
||||
|
||||
// AppendString writes a string to the Buffer.
|
||||
func (b *Buffer) AppendString(s string) {
|
||||
b.bs = append(b.bs, s...)
|
||||
}
|
||||
|
||||
// AppendInt appends an integer to the underlying buffer (assuming base 10).
|
||||
func (b *Buffer) AppendInt(i int64) {
|
||||
b.bs = strconv.AppendInt(b.bs, i, 10)
|
||||
}
|
||||
|
||||
// AppendTime appends the time formatted using the specified layout.
|
||||
func (b *Buffer) AppendTime(t time.Time, layout string) {
|
||||
b.bs = t.AppendFormat(b.bs, layout)
|
||||
}
|
||||
|
||||
// AppendUint appends an unsigned integer to the underlying buffer (assuming
|
||||
// base 10).
|
||||
func (b *Buffer) AppendUint(i uint64) {
|
||||
b.bs = strconv.AppendUint(b.bs, i, 10)
|
||||
}
|
||||
|
||||
// AppendBool appends a bool to the underlying buffer.
|
||||
func (b *Buffer) AppendBool(v bool) {
|
||||
b.bs = strconv.AppendBool(b.bs, v)
|
||||
}
|
||||
|
||||
// AppendFloat appends a float to the underlying buffer. It doesn't quote NaN
|
||||
// or +/- Inf.
|
||||
func (b *Buffer) AppendFloat(f float64, bitSize int) {
|
||||
b.bs = strconv.AppendFloat(b.bs, f, 'f', -1, bitSize)
|
||||
}
|
||||
|
||||
// Len returns the length of the underlying byte slice.
|
||||
func (b *Buffer) Len() int {
|
||||
return len(b.bs)
|
||||
}
|
||||
|
||||
// Cap returns the capacity of the underlying byte slice.
|
||||
func (b *Buffer) Cap() int {
|
||||
return cap(b.bs)
|
||||
}
|
||||
|
||||
// Bytes returns a mutable reference to the underlying byte slice.
|
||||
func (b *Buffer) Bytes() []byte {
|
||||
return b.bs
|
||||
}
|
||||
|
||||
// String returns a string copy of the underlying byte slice.
|
||||
func (b *Buffer) String() string {
|
||||
return string(b.bs)
|
||||
}
|
||||
|
||||
// Reset resets the underlying byte slice. Subsequent writes re-use the slice's
|
||||
// backing array.
|
||||
func (b *Buffer) Reset() {
|
||||
b.bs = b.bs[:0]
|
||||
}
|
||||
|
||||
// Write implements io.Writer.
|
||||
func (b *Buffer) Write(bs []byte) (int, error) {
|
||||
b.bs = append(b.bs, bs...)
|
||||
return len(bs), nil
|
||||
}
|
||||
|
||||
// WriteByte writes a single byte to the Buffer.
|
||||
//
|
||||
// Error returned is always nil, function signature is compatible
|
||||
// with bytes.Buffer and bufio.Writer
|
||||
func (b *Buffer) WriteByte(v byte) error {
|
||||
b.AppendByte(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteString writes a string to the Buffer.
|
||||
//
|
||||
// Error returned is always nil, function signature is compatible
|
||||
// with bytes.Buffer and bufio.Writer
|
||||
func (b *Buffer) WriteString(s string) (int, error) {
|
||||
b.AppendString(s)
|
||||
return len(s), nil
|
||||
}
|
||||
|
||||
// TrimNewline trims any final "\n" byte from the end of the buffer.
|
||||
func (b *Buffer) TrimNewline() {
|
||||
if i := len(b.bs) - 1; i >= 0 {
|
||||
if b.bs[i] == '\n' {
|
||||
b.bs = b.bs[:i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Free returns the Buffer to its Pool.
|
||||
//
|
||||
// Callers must not retain references to the Buffer after calling Free.
|
||||
func (b *Buffer) Free() {
|
||||
b.pool.put(b)
|
||||
}
|
49
vendor/go.uber.org/zap/buffer/pool.go
generated
vendored
Normal file
49
vendor/go.uber.org/zap/buffer/pool.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
// 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 buffer
|
||||
|
||||
import "sync"
|
||||
|
||||
// A Pool is a type-safe wrapper around a sync.Pool.
|
||||
type Pool struct {
|
||||
p *sync.Pool
|
||||
}
|
||||
|
||||
// NewPool constructs a new Pool.
|
||||
func NewPool() Pool {
|
||||
return Pool{p: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Buffer{bs: make([]byte, 0, _size)}
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
// Get retrieves a Buffer from the pool, creating one if necessary.
|
||||
func (p Pool) Get() *Buffer {
|
||||
buf := p.p.Get().(*Buffer)
|
||||
buf.Reset()
|
||||
buf.pool = p
|
||||
return buf
|
||||
}
|
||||
|
||||
func (p Pool) put(buf *Buffer) {
|
||||
p.p.Put(buf)
|
||||
}
|
17
vendor/go.uber.org/zap/checklicense.sh
generated
vendored
Normal file
17
vendor/go.uber.org/zap/checklicense.sh
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
ERROR_COUNT=0
|
||||
while read -r file
|
||||
do
|
||||
case "$(head -1 "${file}")" in
|
||||
*"Copyright (c) "*" Uber Technologies, Inc.")
|
||||
# everything's cool
|
||||
;;
|
||||
*)
|
||||
echo "$file is missing license header."
|
||||
(( ERROR_COUNT++ ))
|
||||
;;
|
||||
esac
|
||||
done < <(git ls-files "*\.go")
|
||||
|
||||
exit $ERROR_COUNT
|
264
vendor/go.uber.org/zap/config.go
generated
vendored
Normal file
264
vendor/go.uber.org/zap/config.go
generated
vendored
Normal file
@ -0,0 +1,264 @@
|
||||
// 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 zap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// SamplingConfig sets a sampling strategy for the logger. Sampling caps the
|
||||
// global CPU and I/O load that logging puts on your process while attempting
|
||||
// to preserve a representative subset of your logs.
|
||||
//
|
||||
// If specified, the Sampler will invoke the Hook after each decision.
|
||||
//
|
||||
// Values configured here are per-second. See zapcore.NewSamplerWithOptions for
|
||||
// details.
|
||||
type SamplingConfig struct {
|
||||
Initial int `json:"initial" yaml:"initial"`
|
||||
Thereafter int `json:"thereafter" yaml:"thereafter"`
|
||||
Hook func(zapcore.Entry, zapcore.SamplingDecision) `json:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
// Config offers a declarative way to construct a logger. It doesn't do
|
||||
// anything that can't be done with New, Options, and the various
|
||||
// zapcore.WriteSyncer and zapcore.Core wrappers, but it's a simpler way to
|
||||
// toggle common options.
|
||||
//
|
||||
// Note that Config intentionally supports only the most common options. More
|
||||
// unusual logging setups (logging to network connections or message queues,
|
||||
// splitting output between multiple files, etc.) are possible, but require
|
||||
// direct use of the zapcore package. For sample code, see the package-level
|
||||
// BasicConfiguration and AdvancedConfiguration examples.
|
||||
//
|
||||
// For an example showing runtime log level changes, see the documentation for
|
||||
// AtomicLevel.
|
||||
type Config struct {
|
||||
// Level is the minimum enabled logging level. Note that this is a dynamic
|
||||
// level, so calling Config.Level.SetLevel will atomically change the log
|
||||
// level of all loggers descended from this config.
|
||||
Level AtomicLevel `json:"level" yaml:"level"`
|
||||
// Development puts the logger in development mode, which changes the
|
||||
// behavior of DPanicLevel and takes stacktraces more liberally.
|
||||
Development bool `json:"development" yaml:"development"`
|
||||
// DisableCaller stops annotating logs with the calling function's file
|
||||
// name and line number. By default, all logs are annotated.
|
||||
DisableCaller bool `json:"disableCaller" yaml:"disableCaller"`
|
||||
// DisableStacktrace completely disables automatic stacktrace capturing. By
|
||||
// default, stacktraces are captured for WarnLevel and above logs in
|
||||
// development and ErrorLevel and above in production.
|
||||
DisableStacktrace bool `json:"disableStacktrace" yaml:"disableStacktrace"`
|
||||
// Sampling sets a sampling policy. A nil SamplingConfig disables sampling.
|
||||
Sampling *SamplingConfig `json:"sampling" yaml:"sampling"`
|
||||
// Encoding sets the logger's encoding. Valid values are "json" and
|
||||
// "console", as well as any third-party encodings registered via
|
||||
// RegisterEncoder.
|
||||
Encoding string `json:"encoding" yaml:"encoding"`
|
||||
// EncoderConfig sets options for the chosen encoder. See
|
||||
// zapcore.EncoderConfig for details.
|
||||
EncoderConfig zapcore.EncoderConfig `json:"encoderConfig" yaml:"encoderConfig"`
|
||||
// OutputPaths is a list of URLs or file paths to write logging output to.
|
||||
// See Open for details.
|
||||
OutputPaths []string `json:"outputPaths" yaml:"outputPaths"`
|
||||
// ErrorOutputPaths is a list of URLs to write internal logger errors to.
|
||||
// The default is standard error.
|
||||
//
|
||||
// Note that this setting only affects internal errors; for sample code that
|
||||
// sends error-level logs to a different location from info- and debug-level
|
||||
// logs, see the package-level AdvancedConfiguration example.
|
||||
ErrorOutputPaths []string `json:"errorOutputPaths" yaml:"errorOutputPaths"`
|
||||
// InitialFields is a collection of fields to add to the root logger.
|
||||
InitialFields map[string]interface{} `json:"initialFields" yaml:"initialFields"`
|
||||
}
|
||||
|
||||
// NewProductionEncoderConfig returns an opinionated EncoderConfig for
|
||||
// production environments.
|
||||
func NewProductionEncoderConfig() zapcore.EncoderConfig {
|
||||
return zapcore.EncoderConfig{
|
||||
TimeKey: "ts",
|
||||
LevelKey: "level",
|
||||
NameKey: "logger",
|
||||
CallerKey: "caller",
|
||||
FunctionKey: zapcore.OmitKey,
|
||||
MessageKey: "msg",
|
||||
StacktraceKey: "stacktrace",
|
||||
LineEnding: zapcore.DefaultLineEnding,
|
||||
EncodeLevel: zapcore.LowercaseLevelEncoder,
|
||||
EncodeTime: zapcore.EpochTimeEncoder,
|
||||
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||||
EncodeCaller: zapcore.ShortCallerEncoder,
|
||||
}
|
||||
}
|
||||
|
||||
// NewProductionConfig is a reasonable production logging configuration.
|
||||
// Logging is enabled at InfoLevel and above.
|
||||
//
|
||||
// It uses a JSON encoder, writes to standard error, and enables sampling.
|
||||
// Stacktraces are automatically included on logs of ErrorLevel and above.
|
||||
func NewProductionConfig() Config {
|
||||
return Config{
|
||||
Level: NewAtomicLevelAt(InfoLevel),
|
||||
Development: false,
|
||||
Sampling: &SamplingConfig{
|
||||
Initial: 100,
|
||||
Thereafter: 100,
|
||||
},
|
||||
Encoding: "json",
|
||||
EncoderConfig: NewProductionEncoderConfig(),
|
||||
OutputPaths: []string{"stderr"},
|
||||
ErrorOutputPaths: []string{"stderr"},
|
||||
}
|
||||
}
|
||||
|
||||
// NewDevelopmentEncoderConfig returns an opinionated EncoderConfig for
|
||||
// development environments.
|
||||
func NewDevelopmentEncoderConfig() zapcore.EncoderConfig {
|
||||
return zapcore.EncoderConfig{
|
||||
// Keys can be anything except the empty string.
|
||||
TimeKey: "T",
|
||||
LevelKey: "L",
|
||||
NameKey: "N",
|
||||
CallerKey: "C",
|
||||
FunctionKey: zapcore.OmitKey,
|
||||
MessageKey: "M",
|
||||
StacktraceKey: "S",
|
||||
LineEnding: zapcore.DefaultLineEnding,
|
||||
EncodeLevel: zapcore.CapitalLevelEncoder,
|
||||
EncodeTime: zapcore.ISO8601TimeEncoder,
|
||||
EncodeDuration: zapcore.StringDurationEncoder,
|
||||
EncodeCaller: zapcore.ShortCallerEncoder,
|
||||
}
|
||||
}
|
||||
|
||||
// NewDevelopmentConfig is a reasonable development logging configuration.
|
||||
// Logging is enabled at DebugLevel and above.
|
||||
//
|
||||
// It enables development mode (which makes DPanicLevel logs panic), uses a
|
||||
// console encoder, writes to standard error, and disables sampling.
|
||||
// Stacktraces are automatically included on logs of WarnLevel and above.
|
||||
func NewDevelopmentConfig() Config {
|
||||
return Config{
|
||||
Level: NewAtomicLevelAt(DebugLevel),
|
||||
Development: true,
|
||||
Encoding: "console",
|
||||
EncoderConfig: NewDevelopmentEncoderConfig(),
|
||||
OutputPaths: []string{"stderr"},
|
||||
ErrorOutputPaths: []string{"stderr"},
|
||||
}
|
||||
}
|
||||
|
||||
// Build constructs a logger from the Config and Options.
|
||||
func (cfg Config) Build(opts ...Option) (*Logger, error) {
|
||||
enc, err := cfg.buildEncoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sink, errSink, err := cfg.openSinks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg.Level == (AtomicLevel{}) {
|
||||
return nil, fmt.Errorf("missing Level")
|
||||
}
|
||||
|
||||
log := New(
|
||||
zapcore.NewCore(enc, sink, cfg.Level),
|
||||
cfg.buildOptions(errSink)...,
|
||||
)
|
||||
if len(opts) > 0 {
|
||||
log = log.WithOptions(opts...)
|
||||
}
|
||||
return log, nil
|
||||
}
|
||||
|
||||
func (cfg Config) buildOptions(errSink zapcore.WriteSyncer) []Option {
|
||||
opts := []Option{ErrorOutput(errSink)}
|
||||
|
||||
if cfg.Development {
|
||||
opts = append(opts, Development())
|
||||
}
|
||||
|
||||
if !cfg.DisableCaller {
|
||||
opts = append(opts, AddCaller())
|
||||
}
|
||||
|
||||
stackLevel := ErrorLevel
|
||||
if cfg.Development {
|
||||
stackLevel = WarnLevel
|
||||
}
|
||||
if !cfg.DisableStacktrace {
|
||||
opts = append(opts, AddStacktrace(stackLevel))
|
||||
}
|
||||
|
||||
if scfg := cfg.Sampling; scfg != nil {
|
||||
opts = append(opts, WrapCore(func(core zapcore.Core) zapcore.Core {
|
||||
var samplerOpts []zapcore.SamplerOption
|
||||
if scfg.Hook != nil {
|
||||
samplerOpts = append(samplerOpts, zapcore.SamplerHook(scfg.Hook))
|
||||
}
|
||||
return zapcore.NewSamplerWithOptions(
|
||||
core,
|
||||
time.Second,
|
||||
cfg.Sampling.Initial,
|
||||
cfg.Sampling.Thereafter,
|
||||
samplerOpts...,
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
if len(cfg.InitialFields) > 0 {
|
||||
fs := make([]Field, 0, len(cfg.InitialFields))
|
||||
keys := make([]string, 0, len(cfg.InitialFields))
|
||||
for k := range cfg.InitialFields {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
fs = append(fs, Any(k, cfg.InitialFields[k]))
|
||||
}
|
||||
opts = append(opts, Fields(fs...))
|
||||
}
|
||||
|
||||
return opts
|
||||
}
|
||||
|
||||
func (cfg Config) openSinks() (zapcore.WriteSyncer, zapcore.WriteSyncer, error) {
|
||||
sink, closeOut, err := Open(cfg.OutputPaths...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
errSink, _, err := Open(cfg.ErrorOutputPaths...)
|
||||
if err != nil {
|
||||
closeOut()
|
||||
return nil, nil, err
|
||||
}
|
||||
return sink, errSink, nil
|
||||
}
|
||||
|
||||
func (cfg Config) buildEncoder() (zapcore.Encoder, error) {
|
||||
return newEncoder(cfg.Encoding, cfg.EncoderConfig)
|
||||
}
|
113
vendor/go.uber.org/zap/doc.go
generated
vendored
Normal file
113
vendor/go.uber.org/zap/doc.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
// 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 zap provides fast, structured, leveled logging.
|
||||
//
|
||||
// For applications that log in the hot path, reflection-based serialization
|
||||
// and string formatting are prohibitively expensive - they're CPU-intensive
|
||||
// and make many small allocations. Put differently, using json.Marshal and
|
||||
// fmt.Fprintf to log tons of interface{} makes your application slow.
|
||||
//
|
||||
// Zap takes a different approach. It includes a reflection-free,
|
||||
// zero-allocation JSON encoder, and the base Logger strives to avoid
|
||||
// serialization overhead and allocations wherever possible. By building the
|
||||
// high-level SugaredLogger on that foundation, zap lets users choose when
|
||||
// they need to count every allocation and when they'd prefer a more familiar,
|
||||
// loosely typed API.
|
||||
//
|
||||
// Choosing a Logger
|
||||
//
|
||||
// In contexts where performance is nice, but not critical, use the
|
||||
// SugaredLogger. It's 4-10x faster than other structured logging packages and
|
||||
// supports both structured and printf-style logging. Like log15 and go-kit,
|
||||
// the SugaredLogger's structured logging APIs are loosely typed and accept a
|
||||
// variadic number of key-value pairs. (For more advanced use cases, they also
|
||||
// accept strongly typed fields - see the SugaredLogger.With documentation for
|
||||
// details.)
|
||||
// sugar := zap.NewExample().Sugar()
|
||||
// defer sugar.Sync()
|
||||
// sugar.Infow("failed to fetch URL",
|
||||
// "url", "http://example.com",
|
||||
// "attempt", 3,
|
||||
// "backoff", time.Second,
|
||||
// )
|
||||
// sugar.Infof("failed to fetch URL: %s", "http://example.com")
|
||||
//
|
||||
// By default, loggers are unbuffered. However, since zap's low-level APIs
|
||||
// allow buffering, calling Sync before letting your process exit is a good
|
||||
// habit.
|
||||
//
|
||||
// In the rare contexts where every microsecond and every allocation matter,
|
||||
// use the Logger. It's even faster than the SugaredLogger and allocates far
|
||||
// less, but it only supports strongly-typed, structured logging.
|
||||
// logger := zap.NewExample()
|
||||
// defer logger.Sync()
|
||||
// logger.Info("failed to fetch URL",
|
||||
// zap.String("url", "http://example.com"),
|
||||
// zap.Int("attempt", 3),
|
||||
// zap.Duration("backoff", time.Second),
|
||||
// )
|
||||
//
|
||||
// Choosing between the Logger and SugaredLogger doesn't need to be an
|
||||
// application-wide decision: converting between the two is simple and
|
||||
// inexpensive.
|
||||
// logger := zap.NewExample()
|
||||
// defer logger.Sync()
|
||||
// sugar := logger.Sugar()
|
||||
// plain := sugar.Desugar()
|
||||
//
|
||||
// Configuring Zap
|
||||
//
|
||||
// The simplest way to build a Logger is to use zap's opinionated presets:
|
||||
// NewExample, NewProduction, and NewDevelopment. These presets build a logger
|
||||
// with a single function call:
|
||||
// logger, err := zap.NewProduction()
|
||||
// if err != nil {
|
||||
// log.Fatalf("can't initialize zap logger: %v", err)
|
||||
// }
|
||||
// defer logger.Sync()
|
||||
//
|
||||
// Presets are fine for small projects, but larger projects and organizations
|
||||
// naturally require a bit more customization. For most users, zap's Config
|
||||
// struct strikes the right balance between flexibility and convenience. See
|
||||
// the package-level BasicConfiguration example for sample code.
|
||||
//
|
||||
// More unusual configurations (splitting output between files, sending logs
|
||||
// to a message queue, etc.) are possible, but require direct use of
|
||||
// go.uber.org/zap/zapcore. See the package-level AdvancedConfiguration
|
||||
// example for sample code.
|
||||
//
|
||||
// Extending Zap
|
||||
//
|
||||
// The zap package itself is a relatively thin wrapper around the interfaces
|
||||
// in go.uber.org/zap/zapcore. Extending zap to support a new encoding (e.g.,
|
||||
// BSON), a new log sink (e.g., Kafka), or something more exotic (perhaps an
|
||||
// exception aggregation service, like Sentry or Rollbar) typically requires
|
||||
// implementing the zapcore.Encoder, zapcore.WriteSyncer, or zapcore.Core
|
||||
// interfaces. See the zapcore documentation for details.
|
||||
//
|
||||
// Similarly, package authors can use the high-performance Encoder and Core
|
||||
// implementations in the zapcore package to build their own loggers.
|
||||
//
|
||||
// Frequently Asked Questions
|
||||
//
|
||||
// An FAQ covering everything from installation errors to design decisions is
|
||||
// available at https://github.com/uber-go/zap/blob/master/FAQ.md.
|
||||
package zap // import "go.uber.org/zap"
|
79
vendor/go.uber.org/zap/encoder.go
generated
vendored
Normal file
79
vendor/go.uber.org/zap/encoder.go
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
// 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 zap
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
var (
|
||||
errNoEncoderNameSpecified = errors.New("no encoder name specified")
|
||||
|
||||
_encoderNameToConstructor = map[string]func(zapcore.EncoderConfig) (zapcore.Encoder, error){
|
||||
"console": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {
|
||||
return zapcore.NewConsoleEncoder(encoderConfig), nil
|
||||
},
|
||||
"json": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {
|
||||
return zapcore.NewJSONEncoder(encoderConfig), nil
|
||||
},
|
||||
}
|
||||
_encoderMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// RegisterEncoder registers an encoder constructor, which the Config struct
|
||||
// can then reference. By default, the "json" and "console" encoders are
|
||||
// registered.
|
||||
//
|
||||
// Attempting to register an encoder whose name is already taken returns an
|
||||
// error.
|
||||
func RegisterEncoder(name string, constructor func(zapcore.EncoderConfig) (zapcore.Encoder, error)) error {
|
||||
_encoderMutex.Lock()
|
||||
defer _encoderMutex.Unlock()
|
||||
if name == "" {
|
||||
return errNoEncoderNameSpecified
|
||||
}
|
||||
if _, ok := _encoderNameToConstructor[name]; ok {
|
||||
return fmt.Errorf("encoder already registered for name %q", name)
|
||||
}
|
||||
_encoderNameToConstructor[name] = constructor
|
||||
return nil
|
||||
}
|
||||
|
||||
func newEncoder(name string, encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {
|
||||
if encoderConfig.TimeKey != "" && encoderConfig.EncodeTime == nil {
|
||||
return nil, fmt.Errorf("missing EncodeTime in EncoderConfig")
|
||||
}
|
||||
|
||||
_encoderMutex.RLock()
|
||||
defer _encoderMutex.RUnlock()
|
||||
if name == "" {
|
||||
return nil, errNoEncoderNameSpecified
|
||||
}
|
||||
constructor, ok := _encoderNameToConstructor[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no encoder registered for name %q", name)
|
||||
}
|
||||
return constructor(encoderConfig)
|
||||
}
|
80
vendor/go.uber.org/zap/error.go
generated
vendored
Normal file
80
vendor/go.uber.org/zap/error.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2017 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 zap
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
var _errArrayElemPool = sync.Pool{New: func() interface{} {
|
||||
return &errArrayElem{}
|
||||
}}
|
||||
|
||||
// Error is shorthand for the common idiom NamedError("error", err).
|
||||
func Error(err error) Field {
|
||||
return NamedError("error", err)
|
||||
}
|
||||
|
||||
// NamedError constructs a field that lazily stores err.Error() under the
|
||||
// provided key. Errors which also implement fmt.Formatter (like those produced
|
||||
// by github.com/pkg/errors) will also have their verbose representation stored
|
||||
// under key+"Verbose". If passed a nil error, the field is a no-op.
|
||||
//
|
||||
// For the common case in which the key is simply "error", the Error function
|
||||
// is shorter and less repetitive.
|
||||
func NamedError(key string, err error) Field {
|
||||
if err == nil {
|
||||
return Skip()
|
||||
}
|
||||
return Field{Key: key, Type: zapcore.ErrorType, Interface: err}
|
||||
}
|
||||
|
||||
type errArray []error
|
||||
|
||||
func (errs errArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||
for i := range errs {
|
||||
if errs[i] == nil {
|
||||
continue
|
||||
}
|
||||
// To represent each error as an object with an "error" attribute and
|
||||
// potentially an "errorVerbose" attribute, we need to wrap it in a
|
||||
// type that implements LogObjectMarshaler. To prevent this from
|
||||
// allocating, pool the wrapper type.
|
||||
elem := _errArrayElemPool.Get().(*errArrayElem)
|
||||
elem.error = errs[i]
|
||||
arr.AppendObject(elem)
|
||||
elem.error = nil
|
||||
_errArrayElemPool.Put(elem)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type errArrayElem struct {
|
||||
error
|
||||
}
|
||||
|
||||
func (e *errArrayElem) MarshalLogObject(enc zapcore.ObjectEncoder) error {
|
||||
// Re-use the error field's logic, which supports non-standard error types.
|
||||
Error(e.error).AddTo(enc)
|
||||
return nil
|
||||
}
|
549
vendor/go.uber.org/zap/field.go
generated
vendored
Normal file
549
vendor/go.uber.org/zap/field.go
generated
vendored
Normal file
@ -0,0 +1,549 @@
|
||||
// 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 zap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// Field is an alias for Field. Aliasing this type dramatically
|
||||
// improves the navigability of this package's API documentation.
|
||||
type Field = zapcore.Field
|
||||
|
||||
var (
|
||||
_minTimeInt64 = time.Unix(0, math.MinInt64)
|
||||
_maxTimeInt64 = time.Unix(0, math.MaxInt64)
|
||||
)
|
||||
|
||||
// Skip constructs a no-op field, which is often useful when handling invalid
|
||||
// inputs in other Field constructors.
|
||||
func Skip() Field {
|
||||
return Field{Type: zapcore.SkipType}
|
||||
}
|
||||
|
||||
// nilField returns a field which will marshal explicitly as nil. See motivation
|
||||
// in https://github.com/uber-go/zap/issues/753 . If we ever make breaking
|
||||
// changes and add zapcore.NilType and zapcore.ObjectEncoder.AddNil, the
|
||||
// implementation here should be changed to reflect that.
|
||||
func nilField(key string) Field { return Reflect(key, nil) }
|
||||
|
||||
// Binary constructs a field that carries an opaque binary blob.
|
||||
//
|
||||
// Binary data is serialized in an encoding-appropriate format. For example,
|
||||
// zap's JSON encoder base64-encodes binary blobs. To log UTF-8 encoded text,
|
||||
// use ByteString.
|
||||
func Binary(key string, val []byte) Field {
|
||||
return Field{Key: key, Type: zapcore.BinaryType, Interface: val}
|
||||
}
|
||||
|
||||
// Bool constructs a field that carries a bool.
|
||||
func Bool(key string, val bool) Field {
|
||||
var ival int64
|
||||
if val {
|
||||
ival = 1
|
||||
}
|
||||
return Field{Key: key, Type: zapcore.BoolType, Integer: ival}
|
||||
}
|
||||
|
||||
// Boolp constructs a field that carries a *bool. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Boolp(key string, val *bool) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Bool(key, *val)
|
||||
}
|
||||
|
||||
// ByteString constructs a field that carries UTF-8 encoded text as a []byte.
|
||||
// To log opaque binary blobs (which aren't necessarily valid UTF-8), use
|
||||
// Binary.
|
||||
func ByteString(key string, val []byte) Field {
|
||||
return Field{Key: key, Type: zapcore.ByteStringType, Interface: val}
|
||||
}
|
||||
|
||||
// Complex128 constructs a field that carries a complex number. Unlike most
|
||||
// numeric fields, this costs an allocation (to convert the complex128 to
|
||||
// interface{}).
|
||||
func Complex128(key string, val complex128) Field {
|
||||
return Field{Key: key, Type: zapcore.Complex128Type, Interface: val}
|
||||
}
|
||||
|
||||
// Complex128p constructs a field that carries a *complex128. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Complex128p(key string, val *complex128) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Complex128(key, *val)
|
||||
}
|
||||
|
||||
// Complex64 constructs a field that carries a complex number. Unlike most
|
||||
// numeric fields, this costs an allocation (to convert the complex64 to
|
||||
// interface{}).
|
||||
func Complex64(key string, val complex64) Field {
|
||||
return Field{Key: key, Type: zapcore.Complex64Type, Interface: val}
|
||||
}
|
||||
|
||||
// Complex64p constructs a field that carries a *complex64. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Complex64p(key string, val *complex64) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Complex64(key, *val)
|
||||
}
|
||||
|
||||
// Float64 constructs a field that carries a float64. The way the
|
||||
// floating-point value is represented is encoder-dependent, so marshaling is
|
||||
// necessarily lazy.
|
||||
func Float64(key string, val float64) Field {
|
||||
return Field{Key: key, Type: zapcore.Float64Type, Integer: int64(math.Float64bits(val))}
|
||||
}
|
||||
|
||||
// Float64p constructs a field that carries a *float64. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Float64p(key string, val *float64) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Float64(key, *val)
|
||||
}
|
||||
|
||||
// Float32 constructs a field that carries a float32. The way the
|
||||
// floating-point value is represented is encoder-dependent, so marshaling is
|
||||
// necessarily lazy.
|
||||
func Float32(key string, val float32) Field {
|
||||
return Field{Key: key, Type: zapcore.Float32Type, Integer: int64(math.Float32bits(val))}
|
||||
}
|
||||
|
||||
// Float32p constructs a field that carries a *float32. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Float32p(key string, val *float32) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Float32(key, *val)
|
||||
}
|
||||
|
||||
// Int constructs a field with the given key and value.
|
||||
func Int(key string, val int) Field {
|
||||
return Int64(key, int64(val))
|
||||
}
|
||||
|
||||
// Intp constructs a field that carries a *int. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Intp(key string, val *int) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Int(key, *val)
|
||||
}
|
||||
|
||||
// Int64 constructs a field with the given key and value.
|
||||
func Int64(key string, val int64) Field {
|
||||
return Field{Key: key, Type: zapcore.Int64Type, Integer: val}
|
||||
}
|
||||
|
||||
// Int64p constructs a field that carries a *int64. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Int64p(key string, val *int64) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Int64(key, *val)
|
||||
}
|
||||
|
||||
// Int32 constructs a field with the given key and value.
|
||||
func Int32(key string, val int32) Field {
|
||||
return Field{Key: key, Type: zapcore.Int32Type, Integer: int64(val)}
|
||||
}
|
||||
|
||||
// Int32p constructs a field that carries a *int32. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Int32p(key string, val *int32) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Int32(key, *val)
|
||||
}
|
||||
|
||||
// Int16 constructs a field with the given key and value.
|
||||
func Int16(key string, val int16) Field {
|
||||
return Field{Key: key, Type: zapcore.Int16Type, Integer: int64(val)}
|
||||
}
|
||||
|
||||
// Int16p constructs a field that carries a *int16. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Int16p(key string, val *int16) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Int16(key, *val)
|
||||
}
|
||||
|
||||
// Int8 constructs a field with the given key and value.
|
||||
func Int8(key string, val int8) Field {
|
||||
return Field{Key: key, Type: zapcore.Int8Type, Integer: int64(val)}
|
||||
}
|
||||
|
||||
// Int8p constructs a field that carries a *int8. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Int8p(key string, val *int8) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Int8(key, *val)
|
||||
}
|
||||
|
||||
// String constructs a field with the given key and value.
|
||||
func String(key string, val string) Field {
|
||||
return Field{Key: key, Type: zapcore.StringType, String: val}
|
||||
}
|
||||
|
||||
// Stringp constructs a field that carries a *string. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Stringp(key string, val *string) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return String(key, *val)
|
||||
}
|
||||
|
||||
// Uint constructs a field with the given key and value.
|
||||
func Uint(key string, val uint) Field {
|
||||
return Uint64(key, uint64(val))
|
||||
}
|
||||
|
||||
// Uintp constructs a field that carries a *uint. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Uintp(key string, val *uint) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Uint(key, *val)
|
||||
}
|
||||
|
||||
// Uint64 constructs a field with the given key and value.
|
||||
func Uint64(key string, val uint64) Field {
|
||||
return Field{Key: key, Type: zapcore.Uint64Type, Integer: int64(val)}
|
||||
}
|
||||
|
||||
// Uint64p constructs a field that carries a *uint64. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Uint64p(key string, val *uint64) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Uint64(key, *val)
|
||||
}
|
||||
|
||||
// Uint32 constructs a field with the given key and value.
|
||||
func Uint32(key string, val uint32) Field {
|
||||
return Field{Key: key, Type: zapcore.Uint32Type, Integer: int64(val)}
|
||||
}
|
||||
|
||||
// Uint32p constructs a field that carries a *uint32. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Uint32p(key string, val *uint32) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Uint32(key, *val)
|
||||
}
|
||||
|
||||
// Uint16 constructs a field with the given key and value.
|
||||
func Uint16(key string, val uint16) Field {
|
||||
return Field{Key: key, Type: zapcore.Uint16Type, Integer: int64(val)}
|
||||
}
|
||||
|
||||
// Uint16p constructs a field that carries a *uint16. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Uint16p(key string, val *uint16) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Uint16(key, *val)
|
||||
}
|
||||
|
||||
// Uint8 constructs a field with the given key and value.
|
||||
func Uint8(key string, val uint8) Field {
|
||||
return Field{Key: key, Type: zapcore.Uint8Type, Integer: int64(val)}
|
||||
}
|
||||
|
||||
// Uint8p constructs a field that carries a *uint8. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Uint8p(key string, val *uint8) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Uint8(key, *val)
|
||||
}
|
||||
|
||||
// Uintptr constructs a field with the given key and value.
|
||||
func Uintptr(key string, val uintptr) Field {
|
||||
return Field{Key: key, Type: zapcore.UintptrType, Integer: int64(val)}
|
||||
}
|
||||
|
||||
// Uintptrp constructs a field that carries a *uintptr. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Uintptrp(key string, val *uintptr) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Uintptr(key, *val)
|
||||
}
|
||||
|
||||
// Reflect constructs a field with the given key and an arbitrary object. It uses
|
||||
// an encoding-appropriate, reflection-based function to lazily serialize nearly
|
||||
// any object into the logging context, but it's relatively slow and
|
||||
// allocation-heavy. Outside tests, Any is always a better choice.
|
||||
//
|
||||
// If encoding fails (e.g., trying to serialize a map[int]string to JSON), Reflect
|
||||
// includes the error message in the final log output.
|
||||
func Reflect(key string, val interface{}) Field {
|
||||
return Field{Key: key, Type: zapcore.ReflectType, Interface: val}
|
||||
}
|
||||
|
||||
// Namespace creates a named, isolated scope within the logger's context. All
|
||||
// subsequent fields will be added to the new namespace.
|
||||
//
|
||||
// This helps prevent key collisions when injecting loggers into sub-components
|
||||
// or third-party libraries.
|
||||
func Namespace(key string) Field {
|
||||
return Field{Key: key, Type: zapcore.NamespaceType}
|
||||
}
|
||||
|
||||
// Stringer constructs a field with the given key and the output of the value's
|
||||
// String method. The Stringer's String method is called lazily.
|
||||
func Stringer(key string, val fmt.Stringer) Field {
|
||||
return Field{Key: key, Type: zapcore.StringerType, Interface: val}
|
||||
}
|
||||
|
||||
// Time constructs a Field with the given key and value. The encoder
|
||||
// controls how the time is serialized.
|
||||
func Time(key string, val time.Time) Field {
|
||||
if val.Before(_minTimeInt64) || val.After(_maxTimeInt64) {
|
||||
return Field{Key: key, Type: zapcore.TimeFullType, Interface: val}
|
||||
}
|
||||
return Field{Key: key, Type: zapcore.TimeType, Integer: val.UnixNano(), Interface: val.Location()}
|
||||
}
|
||||
|
||||
// Timep constructs a field that carries a *time.Time. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Timep(key string, val *time.Time) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Time(key, *val)
|
||||
}
|
||||
|
||||
// Stack constructs a field that stores a stacktrace of the current goroutine
|
||||
// under provided key. Keep in mind that taking a stacktrace is eager and
|
||||
// expensive (relatively speaking); this function both makes an allocation and
|
||||
// takes about two microseconds.
|
||||
func Stack(key string) Field {
|
||||
return StackSkip(key, 1) // skip Stack
|
||||
}
|
||||
|
||||
// StackSkip constructs a field similarly to Stack, but also skips the given
|
||||
// number of frames from the top of the stacktrace.
|
||||
func StackSkip(key string, skip int) Field {
|
||||
// Returning the stacktrace as a string costs an allocation, but saves us
|
||||
// from expanding the zapcore.Field union struct to include a byte slice. Since
|
||||
// taking a stacktrace is already so expensive (~10us), the extra allocation
|
||||
// is okay.
|
||||
return String(key, takeStacktrace(skip+1)) // skip StackSkip
|
||||
}
|
||||
|
||||
// Duration constructs a field with the given key and value. The encoder
|
||||
// controls how the duration is serialized.
|
||||
func Duration(key string, val time.Duration) Field {
|
||||
return Field{Key: key, Type: zapcore.DurationType, Integer: int64(val)}
|
||||
}
|
||||
|
||||
// Durationp constructs a field that carries a *time.Duration. The returned Field will safely
|
||||
// and explicitly represent `nil` when appropriate.
|
||||
func Durationp(key string, val *time.Duration) Field {
|
||||
if val == nil {
|
||||
return nilField(key)
|
||||
}
|
||||
return Duration(key, *val)
|
||||
}
|
||||
|
||||
// Object constructs a field with the given key and ObjectMarshaler. It
|
||||
// provides a flexible, but still type-safe and efficient, way to add map- or
|
||||
// struct-like user-defined types to the logging context. The struct's
|
||||
// MarshalLogObject method is called lazily.
|
||||
func Object(key string, val zapcore.ObjectMarshaler) Field {
|
||||
return Field{Key: key, Type: zapcore.ObjectMarshalerType, Interface: val}
|
||||
}
|
||||
|
||||
// Inline constructs a Field that is similar to Object, but it
|
||||
// will add the elements of the provided ObjectMarshaler to the
|
||||
// current namespace.
|
||||
func Inline(val zapcore.ObjectMarshaler) Field {
|
||||
return zapcore.Field{
|
||||
Type: zapcore.InlineMarshalerType,
|
||||
Interface: val,
|
||||
}
|
||||
}
|
||||
|
||||
// Any takes a key and an arbitrary value and chooses the best way to represent
|
||||
// them as a field, falling back to a reflection-based approach only if
|
||||
// necessary.
|
||||
//
|
||||
// Since byte/uint8 and rune/int32 are aliases, Any can't differentiate between
|
||||
// them. To minimize surprises, []byte values are treated as binary blobs, byte
|
||||
// values are treated as uint8, and runes are always treated as integers.
|
||||
func Any(key string, value interface{}) Field {
|
||||
switch val := value.(type) {
|
||||
case zapcore.ObjectMarshaler:
|
||||
return Object(key, val)
|
||||
case zapcore.ArrayMarshaler:
|
||||
return Array(key, val)
|
||||
case bool:
|
||||
return Bool(key, val)
|
||||
case *bool:
|
||||
return Boolp(key, val)
|
||||
case []bool:
|
||||
return Bools(key, val)
|
||||
case complex128:
|
||||
return Complex128(key, val)
|
||||
case *complex128:
|
||||
return Complex128p(key, val)
|
||||
case []complex128:
|
||||
return Complex128s(key, val)
|
||||
case complex64:
|
||||
return Complex64(key, val)
|
||||
case *complex64:
|
||||
return Complex64p(key, val)
|
||||
case []complex64:
|
||||
return Complex64s(key, val)
|
||||
case float64:
|
||||
return Float64(key, val)
|
||||
case *float64:
|
||||
return Float64p(key, val)
|
||||
case []float64:
|
||||
return Float64s(key, val)
|
||||
case float32:
|
||||
return Float32(key, val)
|
||||
case *float32:
|
||||
return Float32p(key, val)
|
||||
case []float32:
|
||||
return Float32s(key, val)
|
||||
case int:
|
||||
return Int(key, val)
|
||||
case *int:
|
||||
return Intp(key, val)
|
||||
case []int:
|
||||
return Ints(key, val)
|
||||
case int64:
|
||||
return Int64(key, val)
|
||||
case *int64:
|
||||
return Int64p(key, val)
|
||||
case []int64:
|
||||
return Int64s(key, val)
|
||||
case int32:
|
||||
return Int32(key, val)
|
||||
case *int32:
|
||||
return Int32p(key, val)
|
||||
case []int32:
|
||||
return Int32s(key, val)
|
||||
case int16:
|
||||
return Int16(key, val)
|
||||
case *int16:
|
||||
return Int16p(key, val)
|
||||
case []int16:
|
||||
return Int16s(key, val)
|
||||
case int8:
|
||||
return Int8(key, val)
|
||||
case *int8:
|
||||
return Int8p(key, val)
|
||||
case []int8:
|
||||
return Int8s(key, val)
|
||||
case string:
|
||||
return String(key, val)
|
||||
case *string:
|
||||
return Stringp(key, val)
|
||||
case []string:
|
||||
return Strings(key, val)
|
||||
case uint:
|
||||
return Uint(key, val)
|
||||
case *uint:
|
||||
return Uintp(key, val)
|
||||
case []uint:
|
||||
return Uints(key, val)
|
||||
case uint64:
|
||||
return Uint64(key, val)
|
||||
case *uint64:
|
||||
return Uint64p(key, val)
|
||||
case []uint64:
|
||||
return Uint64s(key, val)
|
||||
case uint32:
|
||||
return Uint32(key, val)
|
||||
case *uint32:
|
||||
return Uint32p(key, val)
|
||||
case []uint32:
|
||||
return Uint32s(key, val)
|
||||
case uint16:
|
||||
return Uint16(key, val)
|
||||
case *uint16:
|
||||
return Uint16p(key, val)
|
||||
case []uint16:
|
||||
return Uint16s(key, val)
|
||||
case uint8:
|
||||
return Uint8(key, val)
|
||||
case *uint8:
|
||||
return Uint8p(key, val)
|
||||
case []byte:
|
||||
return Binary(key, val)
|
||||
case uintptr:
|
||||
return Uintptr(key, val)
|
||||
case *uintptr:
|
||||
return Uintptrp(key, val)
|
||||
case []uintptr:
|
||||
return Uintptrs(key, val)
|
||||
case time.Time:
|
||||
return Time(key, val)
|
||||
case *time.Time:
|
||||
return Timep(key, val)
|
||||
case []time.Time:
|
||||
return Times(key, val)
|
||||
case time.Duration:
|
||||
return Duration(key, val)
|
||||
case *time.Duration:
|
||||
return Durationp(key, val)
|
||||
case []time.Duration:
|
||||
return Durations(key, val)
|
||||
case error:
|
||||
return NamedError(key, val)
|
||||
case []error:
|
||||
return Errors(key, val)
|
||||
case fmt.Stringer:
|
||||
return Stringer(key, val)
|
||||
default:
|
||||
return Reflect(key, val)
|
||||
}
|
||||
}
|
39
vendor/go.uber.org/zap/flag.go
generated
vendored
Normal file
39
vendor/go.uber.org/zap/flag.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// 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 zap
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// LevelFlag uses the standard library's flag.Var to declare a global flag
|
||||
// with the specified name, default, and usage guidance. The returned value is
|
||||
// a pointer to the value of the flag.
|
||||
//
|
||||
// If you don't want to use the flag package's global state, you can use any
|
||||
// non-nil *Level as a flag.Value with your own *flag.FlagSet.
|
||||
func LevelFlag(name string, defaultLevel zapcore.Level, usage string) *zapcore.Level {
|
||||
lvl := defaultLevel
|
||||
flag.Var(&lvl, name, usage)
|
||||
return &lvl
|
||||
}
|
34
vendor/go.uber.org/zap/glide.yaml
generated
vendored
Normal file
34
vendor/go.uber.org/zap/glide.yaml
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
package: go.uber.org/zap
|
||||
license: MIT
|
||||
import:
|
||||
- package: go.uber.org/atomic
|
||||
version: ^1
|
||||
- package: go.uber.org/multierr
|
||||
version: ^1
|
||||
testImport:
|
||||
- package: github.com/satori/go.uuid
|
||||
- package: github.com/sirupsen/logrus
|
||||
- package: github.com/apex/log
|
||||
subpackages:
|
||||
- handlers/json
|
||||
- package: github.com/go-kit/kit
|
||||
subpackages:
|
||||
- log
|
||||
- package: github.com/stretchr/testify
|
||||
subpackages:
|
||||
- assert
|
||||
- require
|
||||
- package: gopkg.in/inconshreveable/log15.v2
|
||||
- package: github.com/mattn/goveralls
|
||||
- package: github.com/pborman/uuid
|
||||
- package: github.com/pkg/errors
|
||||
- package: github.com/rs/zerolog
|
||||
- package: golang.org/x/tools
|
||||
subpackages:
|
||||
- cover
|
||||
- package: golang.org/x/lint
|
||||
subpackages:
|
||||
- golint
|
||||
- package: github.com/axw/gocov
|
||||
subpackages:
|
||||
- gocov
|
168
vendor/go.uber.org/zap/global.go
generated
vendored
Normal file
168
vendor/go.uber.org/zap/global.go
generated
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
// 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 zap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
const (
|
||||
_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"
|
||||
)
|
||||
|
||||
var (
|
||||
_globalMu sync.RWMutex
|
||||
_globalL = NewNop()
|
||||
_globalS = _globalL.Sugar()
|
||||
)
|
||||
|
||||
// L returns the global Logger, which can be reconfigured with ReplaceGlobals.
|
||||
// It's safe for concurrent use.
|
||||
func L() *Logger {
|
||||
_globalMu.RLock()
|
||||
l := _globalL
|
||||
_globalMu.RUnlock()
|
||||
return l
|
||||
}
|
||||
|
||||
// S returns the global SugaredLogger, which can be reconfigured with
|
||||
// ReplaceGlobals. It's safe for concurrent use.
|
||||
func S() *SugaredLogger {
|
||||
_globalMu.RLock()
|
||||
s := _globalS
|
||||
_globalMu.RUnlock()
|
||||
return s
|
||||
}
|
||||
|
||||
// ReplaceGlobals replaces the global Logger and SugaredLogger, and returns a
|
||||
// function to restore the original values. It's safe for concurrent use.
|
||||
func ReplaceGlobals(logger *Logger) func() {
|
||||
_globalMu.Lock()
|
||||
prev := _globalL
|
||||
_globalL = logger
|
||||
_globalS = logger.Sugar()
|
||||
_globalMu.Unlock()
|
||||
return func() { ReplaceGlobals(prev) }
|
||||
}
|
||||
|
||||
// NewStdLog returns a *log.Logger which writes to the supplied zap Logger at
|
||||
// InfoLevel. To redirect the standard library's package-global logging
|
||||
// functions, use RedirectStdLog instead.
|
||||
func NewStdLog(l *Logger) *log.Logger {
|
||||
logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth))
|
||||
f := logger.Info
|
||||
return log.New(&loggerWriter{f}, "" /* prefix */, 0 /* flags */)
|
||||
}
|
||||
|
||||
// NewStdLogAt returns *log.Logger which writes to supplied zap logger at
|
||||
// required level.
|
||||
func NewStdLogAt(l *Logger, level zapcore.Level) (*log.Logger, error) {
|
||||
logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth))
|
||||
logFunc, err := levelToFunc(logger, level)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return log.New(&loggerWriter{logFunc}, "" /* prefix */, 0 /* flags */), nil
|
||||
}
|
||||
|
||||
// RedirectStdLog redirects output from the standard library's package-global
|
||||
// logger to the supplied logger at InfoLevel. Since zap already handles caller
|
||||
// annotations, timestamps, etc., it automatically disables the standard
|
||||
// library's annotations and prefixing.
|
||||
//
|
||||
// It returns a function to restore the original prefix and flags and reset the
|
||||
// standard library's output to os.Stderr.
|
||||
func RedirectStdLog(l *Logger) func() {
|
||||
f, err := redirectStdLogAt(l, InfoLevel)
|
||||
if err != nil {
|
||||
// Can't get here, since passing InfoLevel to redirectStdLogAt always
|
||||
// works.
|
||||
panic(fmt.Sprintf(_programmerErrorTemplate, err))
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// RedirectStdLogAt redirects output from the standard library's package-global
|
||||
// logger to the supplied logger at the specified level. Since zap already
|
||||
// handles caller annotations, timestamps, etc., it automatically disables the
|
||||
// standard library's annotations and prefixing.
|
||||
//
|
||||
// It returns a function to restore the original prefix and flags and reset the
|
||||
// standard library's output to os.Stderr.
|
||||
func RedirectStdLogAt(l *Logger, level zapcore.Level) (func(), error) {
|
||||
return redirectStdLogAt(l, level)
|
||||
}
|
||||
|
||||
func redirectStdLogAt(l *Logger, level zapcore.Level) (func(), error) {
|
||||
flags := log.Flags()
|
||||
prefix := log.Prefix()
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("")
|
||||
logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth))
|
||||
logFunc, err := levelToFunc(logger, level)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.SetOutput(&loggerWriter{logFunc})
|
||||
return func() {
|
||||
log.SetFlags(flags)
|
||||
log.SetPrefix(prefix)
|
||||
log.SetOutput(os.Stderr)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func levelToFunc(logger *Logger, lvl zapcore.Level) (func(string, ...Field), error) {
|
||||
switch lvl {
|
||||
case DebugLevel:
|
||||
return logger.Debug, nil
|
||||
case InfoLevel:
|
||||
return logger.Info, nil
|
||||
case WarnLevel:
|
||||
return logger.Warn, nil
|
||||
case ErrorLevel:
|
||||
return logger.Error, nil
|
||||
case DPanicLevel:
|
||||
return logger.DPanic, nil
|
||||
case PanicLevel:
|
||||
return logger.Panic, nil
|
||||
case FatalLevel:
|
||||
return logger.Fatal, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unrecognized level: %q", lvl)
|
||||
}
|
||||
|
||||
type loggerWriter struct {
|
||||
logFunc func(msg string, fields ...Field)
|
||||
}
|
||||
|
||||
func (l *loggerWriter) Write(p []byte) (int, error) {
|
||||
p = bytes.TrimSpace(p)
|
||||
l.logFunc(string(p))
|
||||
return len(p), nil
|
||||
}
|
26
vendor/go.uber.org/zap/global_go112.go
generated
vendored
Normal file
26
vendor/go.uber.org/zap/global_go112.go
generated
vendored
Normal 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
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user