mirror of https://github.com/k3s-io/k3s
Update vendor package github.com/coreos/...
parent
c0974d7399
commit
d462e1e8d7
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/kubernetes",
|
"ImportPath": "k8s.io/kubernetes",
|
||||||
"GoVersion": "go1.10",
|
"GoVersion": "go1.11",
|
||||||
"GodepVersion": "v80",
|
"GodepVersion": "v80",
|
||||||
"Packages": [
|
"Packages": [
|
||||||
"github.com/onsi/ginkgo/ginkgo",
|
"github.com/onsi/ginkgo/ginkgo",
|
||||||
|
@ -26,12 +26,12 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "cloud.google.com/go/compute/metadata",
|
"ImportPath": "cloud.google.com/go/compute/metadata",
|
||||||
"Comment": "v0.1.0-115-g3b1ae453",
|
"Comment": "v0.1.0-115-g3b1ae45",
|
||||||
"Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821"
|
"Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "cloud.google.com/go/internal",
|
"ImportPath": "cloud.google.com/go/internal",
|
||||||
"Comment": "v0.1.0-115-g3b1ae453",
|
"Comment": "v0.1.0-115-g3b1ae45",
|
||||||
"Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821"
|
"Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -897,368 +897,368 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/alarm",
|
"ImportPath": "github.com/coreos/etcd/alarm",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/auth",
|
"ImportPath": "github.com/coreos/etcd/auth",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/client",
|
"ImportPath": "github.com/coreos/etcd/client",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3",
|
"ImportPath": "github.com/coreos/etcd/clientv3",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3/concurrency",
|
"ImportPath": "github.com/coreos/etcd/clientv3/concurrency",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3/namespace",
|
"ImportPath": "github.com/coreos/etcd/clientv3/namespace",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3/naming",
|
"ImportPath": "github.com/coreos/etcd/clientv3/naming",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/compactor",
|
"ImportPath": "github.com/coreos/etcd/compactor",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/discovery",
|
"ImportPath": "github.com/coreos/etcd/discovery",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/embed",
|
"ImportPath": "github.com/coreos/etcd/embed",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/error",
|
"ImportPath": "github.com/coreos/etcd/error",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver",
|
"ImportPath": "github.com/coreos/etcd/etcdserver",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/etcdhttp",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/etcdhttp",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http/httptypes",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http/httptypes",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2v3",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2v3",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3client",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3client",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb/gw",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb/gw",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb/gw",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb/gw",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/auth",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/auth",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb/gw",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb/gw",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/membership",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/membership",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/stats",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/stats",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/integration",
|
"ImportPath": "github.com/coreos/etcd/integration",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/lease",
|
"ImportPath": "github.com/coreos/etcd/lease",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/lease/leasehttp",
|
"ImportPath": "github.com/coreos/etcd/lease/leasehttp",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/lease/leasepb",
|
"ImportPath": "github.com/coreos/etcd/lease/leasepb",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/mvcc",
|
"ImportPath": "github.com/coreos/etcd/mvcc",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/mvcc/backend",
|
"ImportPath": "github.com/coreos/etcd/mvcc/backend",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/adt",
|
"ImportPath": "github.com/coreos/etcd/pkg/adt",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/contention",
|
"ImportPath": "github.com/coreos/etcd/pkg/contention",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/cors",
|
"ImportPath": "github.com/coreos/etcd/pkg/cors",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/cpuutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/cpuutil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/crc",
|
"ImportPath": "github.com/coreos/etcd/pkg/crc",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/debugutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/debugutil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/fileutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/fileutil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/httputil",
|
"ImportPath": "github.com/coreos/etcd/pkg/httputil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/idutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/idutil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/ioutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/ioutil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/logutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/logutil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/netutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/netutil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/pbutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/pbutil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/runtime",
|
"ImportPath": "github.com/coreos/etcd/pkg/runtime",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/schedule",
|
"ImportPath": "github.com/coreos/etcd/pkg/schedule",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/srv",
|
"ImportPath": "github.com/coreos/etcd/pkg/srv",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/testutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/testutil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/wait",
|
"ImportPath": "github.com/coreos/etcd/pkg/wait",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy",
|
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/adapter",
|
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/adapter",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/cache",
|
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/cache",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/raft",
|
"ImportPath": "github.com/coreos/etcd/raft",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/raft/raftpb",
|
"ImportPath": "github.com/coreos/etcd/raft/raftpb",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/rafthttp",
|
"ImportPath": "github.com/coreos/etcd/rafthttp",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/snap",
|
"ImportPath": "github.com/coreos/etcd/snap",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/snap/snappb",
|
"ImportPath": "github.com/coreos/etcd/snap/snappb",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/store",
|
"ImportPath": "github.com/coreos/etcd/store",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/version",
|
"ImportPath": "github.com/coreos/etcd/version",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/wal",
|
"ImportPath": "github.com/coreos/etcd/wal",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/wal/walpb",
|
"ImportPath": "github.com/coreos/etcd/wal/walpb",
|
||||||
"Comment": "v3.3.9",
|
"Comment": "v3.3.10",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-oidc",
|
"ImportPath": "github.com/coreos/go-oidc",
|
||||||
|
@ -1266,37 +1266,38 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-semver/semver",
|
"ImportPath": "github.com/coreos/go-semver/semver",
|
||||||
"Rev": "568e959cd89871e61434c1143528d9162da89ef2"
|
"Comment": "v0.2.0-9-ge214231",
|
||||||
|
"Rev": "e214231b295a8ea9479f11b70b35d5acf3556d9b"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-systemd/daemon",
|
"ImportPath": "github.com/coreos/go-systemd/daemon",
|
||||||
"Comment": "v14",
|
"Comment": "v17",
|
||||||
"Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6"
|
"Rev": "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-systemd/dbus",
|
"ImportPath": "github.com/coreos/go-systemd/dbus",
|
||||||
"Comment": "v14",
|
"Comment": "v17",
|
||||||
"Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6"
|
"Rev": "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-systemd/journal",
|
"ImportPath": "github.com/coreos/go-systemd/journal",
|
||||||
"Comment": "v14",
|
"Comment": "v17",
|
||||||
"Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6"
|
"Rev": "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-systemd/util",
|
"ImportPath": "github.com/coreos/go-systemd/util",
|
||||||
"Comment": "v14",
|
"Comment": "v17",
|
||||||
"Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6"
|
"Rev": "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/pkg/capnslog",
|
"ImportPath": "github.com/coreos/pkg/capnslog",
|
||||||
"Comment": "v2-8-gfa29b1d",
|
"Comment": "v4",
|
||||||
"Rev": "fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8"
|
"Rev": "97fdf19511ea361ae1c100dd393cc47f8dcfa1e1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/pkg/dlopen",
|
"ImportPath": "github.com/coreos/pkg/dlopen",
|
||||||
"Comment": "v2-8-gfa29b1d",
|
"Comment": "v4",
|
||||||
"Rev": "fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8"
|
"Rev": "97fdf19511ea361ae1c100dd393cc47f8dcfa1e1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/rkt/api/v1alpha",
|
"ImportPath": "github.com/coreos/rkt/api/v1alpha",
|
||||||
|
@ -1341,142 +1342,142 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/distribution/digestset",
|
"ImportPath": "github.com/docker/distribution/digestset",
|
||||||
"Comment": "v2.6.0-rc.1-209-gedc3ab29",
|
"Comment": "v2.6.0-rc.1-209-gedc3ab2",
|
||||||
"Rev": "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c"
|
"Rev": "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/distribution/reference",
|
"ImportPath": "github.com/docker/distribution/reference",
|
||||||
"Comment": "v2.6.0-rc.1-209-gedc3ab29",
|
"Comment": "v2.6.0-rc.1-209-gedc3ab2",
|
||||||
"Rev": "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c"
|
"Rev": "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api",
|
"ImportPath": "github.com/docker/docker/api",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types",
|
"ImportPath": "github.com/docker/docker/api/types",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/blkiodev",
|
"ImportPath": "github.com/docker/docker/api/types/blkiodev",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/container",
|
"ImportPath": "github.com/docker/docker/api/types/container",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/events",
|
"ImportPath": "github.com/docker/docker/api/types/events",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/filters",
|
"ImportPath": "github.com/docker/docker/api/types/filters",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/image",
|
"ImportPath": "github.com/docker/docker/api/types/image",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/mount",
|
"ImportPath": "github.com/docker/docker/api/types/mount",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/network",
|
"ImportPath": "github.com/docker/docker/api/types/network",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/registry",
|
"ImportPath": "github.com/docker/docker/api/types/registry",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/strslice",
|
"ImportPath": "github.com/docker/docker/api/types/strslice",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/swarm",
|
"ImportPath": "github.com/docker/docker/api/types/swarm",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/swarm/runtime",
|
"ImportPath": "github.com/docker/docker/api/types/swarm/runtime",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/time",
|
"ImportPath": "github.com/docker/docker/api/types/time",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/versions",
|
"ImportPath": "github.com/docker/docker/api/types/versions",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/api/types/volume",
|
"ImportPath": "github.com/docker/docker/api/types/volume",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/client",
|
"ImportPath": "github.com/docker/docker/client",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog",
|
"ImportPath": "github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/pkg/jsonmessage",
|
"ImportPath": "github.com/docker/docker/pkg/jsonmessage",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/pkg/mount",
|
"ImportPath": "github.com/docker/docker/pkg/mount",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/pkg/parsers",
|
"ImportPath": "github.com/docker/docker/pkg/parsers",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/pkg/parsers/operatingsystem",
|
"ImportPath": "github.com/docker/docker/pkg/parsers/operatingsystem",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/pkg/stdcopy",
|
"ImportPath": "github.com/docker/docker/pkg/stdcopy",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/pkg/sysinfo",
|
"ImportPath": "github.com/docker/docker/pkg/sysinfo",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/pkg/term",
|
"ImportPath": "github.com/docker/docker/pkg/term",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/pkg/term/windows",
|
"ImportPath": "github.com/docker/docker/pkg/term/windows",
|
||||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
|
"Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc",
|
||||||
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
"Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1501,7 +1502,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/libnetwork/ipvs",
|
"ImportPath": "github.com/docker/libnetwork/ipvs",
|
||||||
"Comment": "v0.8.0-dev.2-1265-ga9cd636e",
|
"Comment": "v0.8.0-dev.2-1265-ga9cd636",
|
||||||
"Rev": "a9cd636e37898226332c439363e2ed0ea185ae92"
|
"Rev": "a9cd636e37898226332c439363e2ed0ea185ae92"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1561,6 +1562,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/ghodss/yaml",
|
"ImportPath": "github.com/ghodss/yaml",
|
||||||
|
"Comment": "v1.0.0-4-gc7ce166",
|
||||||
"Rev": "c7ce16629ff4cd059ed96ed06419dd3856fd3577"
|
"Rev": "c7ce16629ff4cd059ed96ed06419dd3856fd3577"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2183,6 +2185,11 @@
|
||||||
"ImportPath": "github.com/gregjones/httpcache/diskcache",
|
"ImportPath": "github.com/gregjones/httpcache/diskcache",
|
||||||
"Rev": "787624de3eb7bd915c329cba748687a3b22666a6"
|
"Rev": "787624de3eb7bd915c329cba748687a3b22666a6"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/grpc-ecosystem/go-grpc-middleware",
|
||||||
|
"Comment": "v1.0.0-4-g498ae20",
|
||||||
|
"Rev": "498ae206fc3cfe81cd82e48c1d4354026fa5f9ec"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus",
|
"ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus",
|
||||||
"Comment": "v1.1-4-g2500245",
|
"Comment": "v1.1-4-g2500245",
|
||||||
|
@ -2748,82 +2755,82 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/apparmor",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/apparmor",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/fs",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/fs",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/systemd",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/systemd",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/configs",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/configs",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/configs/validate",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/configs/validate",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/criurpc",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/criurpc",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/intelrdt",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/intelrdt",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/keys",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/keys",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/mount",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/mount",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/seccomp",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/seccomp",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/stacktrace",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/stacktrace",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/system",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/system",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/user",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/user",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/opencontainers/runc/libcontainer/utils",
|
"ImportPath": "github.com/opencontainers/runc/libcontainer/utils",
|
||||||
"Comment": "v1.0.0-rc5-46-g871ba2e5",
|
"Comment": "v1.0.0-rc5-46-g871ba2e",
|
||||||
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
"Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -3268,6 +3275,46 @@
|
||||||
"Comment": "0.0.1",
|
"Comment": "0.0.1",
|
||||||
"Rev": "07dd2e8dfe18522e9c447ba95f2fe95262f63bb2"
|
"Rev": "07dd2e8dfe18522e9c447ba95f2fe95262f63bb2"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/atomic",
|
||||||
|
"Comment": "v1.3.2-3-g8dc6146",
|
||||||
|
"Rev": "8dc6146f7569370a472715e178d8ae31172ee6da"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/multierr",
|
||||||
|
"Comment": "v1.1.0-2-gddea229",
|
||||||
|
"Rev": "ddea229ff1dff9e6fe8a6c0344ac73b09e81fce5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap",
|
||||||
|
"Comment": "v1.9.1-1-g67bc79d",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/buffer",
|
||||||
|
"Comment": "v1.9.1-1-g67bc79d",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/internal/bufferpool",
|
||||||
|
"Comment": "v1.9.1-1-g67bc79d",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/internal/color",
|
||||||
|
"Comment": "v1.9.1-1-g67bc79d",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/internal/exit",
|
||||||
|
"Comment": "v1.9.1-1-g67bc79d",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/zapcore",
|
||||||
|
"Comment": "v1.9.1-1-g67bc79d",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/bcrypt",
|
"ImportPath": "golang.org/x/crypto/bcrypt",
|
||||||
"Rev": "de0752318171da717af4ce24d0a2e8626afaeb11"
|
"Rev": "de0752318171da717af4ce24d0a2e8626afaeb11"
|
||||||
|
@ -3816,6 +3863,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "gopkg.in/yaml.v2",
|
"ImportPath": "gopkg.in/yaml.v2",
|
||||||
|
"Comment": "v2.2.1",
|
||||||
"Rev": "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
"Rev": "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -66894,6 +66894,214 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/github.com/grpc-ecosystem/go-grpc-middleware licensed under: =
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
= vendor/github.com/grpc-ecosystem/go-grpc-middleware/LICENSE 7ab5c73bb7e4679b16dd7c11b3559acf
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
= vendor/github.com/grpc-ecosystem/go-grpc-prometheus licensed under: =
|
= vendor/github.com/grpc-ecosystem/go-grpc-prometheus licensed under: =
|
||||||
|
|
||||||
|
@ -97074,6 +97282,222 @@ SOFTWARE.
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/go.uber.org/atomic licensed under: =
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
= vendor/go.uber.org/atomic/LICENSE.txt 1caee86519456feda989f8a838102b50
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/go.uber.org/multierr licensed under: =
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
= vendor/go.uber.org/multierr/LICENSE.txt f65b21a547112d1bc7b11b90f9b31997
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/go.uber.org/zap licensed under: =
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
= vendor/go.uber.org/zap/LICENSE.txt 5e8153e456a82529ea845e0d511abb69
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/go.uber.org/zap/buffer licensed under: =
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
= vendor/go.uber.org/zap/LICENSE.txt 5e8153e456a82529ea845e0d511abb69
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/go.uber.org/zap/internal/bufferpool licensed under: =
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
= vendor/go.uber.org/zap/LICENSE.txt 5e8153e456a82529ea845e0d511abb69
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/go.uber.org/zap/internal/color licensed under: =
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
= vendor/go.uber.org/zap/LICENSE.txt 5e8153e456a82529ea845e0d511abb69
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/go.uber.org/zap/internal/exit licensed under: =
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
= vendor/go.uber.org/zap/LICENSE.txt 5e8153e456a82529ea845e0d511abb69
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/go.uber.org/zap/zapcore licensed under: =
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
= vendor/go.uber.org/zap/LICENSE.txt 5e8153e456a82529ea845e0d511abb69
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
= vendor/golang.org/x/crypto/bcrypt licensed under: =
|
= vendor/golang.org/x/crypto/bcrypt licensed under: =
|
||||||
|
|
||||||
|
|
|
@ -44,311 +44,311 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/alarm",
|
"ImportPath": "github.com/coreos/etcd/alarm",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/auth",
|
"ImportPath": "github.com/coreos/etcd/auth",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/client",
|
"ImportPath": "github.com/coreos/etcd/client",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3",
|
"ImportPath": "github.com/coreos/etcd/clientv3",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3/concurrency",
|
"ImportPath": "github.com/coreos/etcd/clientv3/concurrency",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3/namespace",
|
"ImportPath": "github.com/coreos/etcd/clientv3/namespace",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3/naming",
|
"ImportPath": "github.com/coreos/etcd/clientv3/naming",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/compactor",
|
"ImportPath": "github.com/coreos/etcd/compactor",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/discovery",
|
"ImportPath": "github.com/coreos/etcd/discovery",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/embed",
|
"ImportPath": "github.com/coreos/etcd/embed",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/error",
|
"ImportPath": "github.com/coreos/etcd/error",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver",
|
"ImportPath": "github.com/coreos/etcd/etcdserver",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/etcdhttp",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/etcdhttp",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http/httptypes",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http/httptypes",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2v3",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2v3",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3client",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3client",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb/gw",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb/gw",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb/gw",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb/gw",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/auth",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/auth",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb/gw",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb/gw",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/membership",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/membership",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/stats",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/stats",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/integration",
|
"ImportPath": "github.com/coreos/etcd/integration",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/lease",
|
"ImportPath": "github.com/coreos/etcd/lease",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/lease/leasehttp",
|
"ImportPath": "github.com/coreos/etcd/lease/leasehttp",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/lease/leasepb",
|
"ImportPath": "github.com/coreos/etcd/lease/leasepb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/mvcc",
|
"ImportPath": "github.com/coreos/etcd/mvcc",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/mvcc/backend",
|
"ImportPath": "github.com/coreos/etcd/mvcc/backend",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/adt",
|
"ImportPath": "github.com/coreos/etcd/pkg/adt",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/contention",
|
"ImportPath": "github.com/coreos/etcd/pkg/contention",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/cors",
|
"ImportPath": "github.com/coreos/etcd/pkg/cors",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/cpuutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/cpuutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/crc",
|
"ImportPath": "github.com/coreos/etcd/pkg/crc",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/debugutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/debugutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/fileutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/fileutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/httputil",
|
"ImportPath": "github.com/coreos/etcd/pkg/httputil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/idutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/idutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/ioutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/ioutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/logutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/logutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/netutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/netutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/pbutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/pbutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/runtime",
|
"ImportPath": "github.com/coreos/etcd/pkg/runtime",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/schedule",
|
"ImportPath": "github.com/coreos/etcd/pkg/schedule",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/srv",
|
"ImportPath": "github.com/coreos/etcd/pkg/srv",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/testutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/testutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/wait",
|
"ImportPath": "github.com/coreos/etcd/pkg/wait",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy",
|
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/adapter",
|
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/adapter",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/cache",
|
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/cache",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/raft",
|
"ImportPath": "github.com/coreos/etcd/raft",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/raft/raftpb",
|
"ImportPath": "github.com/coreos/etcd/raft/raftpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/rafthttp",
|
"ImportPath": "github.com/coreos/etcd/rafthttp",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/snap",
|
"ImportPath": "github.com/coreos/etcd/snap",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/snap/snappb",
|
"ImportPath": "github.com/coreos/etcd/snap/snappb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/store",
|
"ImportPath": "github.com/coreos/etcd/store",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/version",
|
"ImportPath": "github.com/coreos/etcd/version",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/wal",
|
"ImportPath": "github.com/coreos/etcd/wal",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/wal/walpb",
|
"ImportPath": "github.com/coreos/etcd/wal/walpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-semver/semver",
|
"ImportPath": "github.com/coreos/go-semver/semver",
|
||||||
"Rev": "568e959cd89871e61434c1143528d9162da89ef2"
|
"Rev": "e214231b295a8ea9479f11b70b35d5acf3556d9b"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-systemd/daemon",
|
"ImportPath": "github.com/coreos/go-systemd/daemon",
|
||||||
"Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6"
|
"Rev": "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-systemd/journal",
|
"ImportPath": "github.com/coreos/go-systemd/journal",
|
||||||
"Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6"
|
"Rev": "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/pkg/capnslog",
|
"ImportPath": "github.com/coreos/pkg/capnslog",
|
||||||
"Rev": "fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8"
|
"Rev": "97fdf19511ea361ae1c100dd393cc47f8dcfa1e1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/davecgh/go-spew/spew",
|
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||||
|
@ -514,6 +514,10 @@
|
||||||
"ImportPath": "github.com/gregjones/httpcache/diskcache",
|
"ImportPath": "github.com/gregjones/httpcache/diskcache",
|
||||||
"Rev": "787624de3eb7bd915c329cba748687a3b22666a6"
|
"Rev": "787624de3eb7bd915c329cba748687a3b22666a6"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/grpc-ecosystem/go-grpc-middleware",
|
||||||
|
"Rev": "498ae206fc3cfe81cd82e48c1d4354026fa5f9ec"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus",
|
"ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus",
|
||||||
"Rev": "2500245aa6110c562d17020fb31a2c133d737799"
|
"Rev": "2500245aa6110c562d17020fb31a2c133d737799"
|
||||||
|
@ -658,6 +662,38 @@
|
||||||
"ImportPath": "github.com/xiang90/probing",
|
"ImportPath": "github.com/xiang90/probing",
|
||||||
"Rev": "07dd2e8dfe18522e9c447ba95f2fe95262f63bb2"
|
"Rev": "07dd2e8dfe18522e9c447ba95f2fe95262f63bb2"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/atomic",
|
||||||
|
"Rev": "8dc6146f7569370a472715e178d8ae31172ee6da"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/multierr",
|
||||||
|
"Rev": "ddea229ff1dff9e6fe8a6c0344ac73b09e81fce5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/buffer",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/internal/bufferpool",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/internal/color",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/internal/exit",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/zapcore",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/bcrypt",
|
"ImportPath": "golang.org/x/crypto/bcrypt",
|
||||||
"Rev": "de0752318171da717af4ce24d0a2e8626afaeb11"
|
"Rev": "de0752318171da717af4ce24d0a2e8626afaeb11"
|
||||||
|
|
|
@ -40,295 +40,295 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/alarm",
|
"ImportPath": "github.com/coreos/etcd/alarm",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/auth",
|
"ImportPath": "github.com/coreos/etcd/auth",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/client",
|
"ImportPath": "github.com/coreos/etcd/client",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3",
|
"ImportPath": "github.com/coreos/etcd/clientv3",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3/concurrency",
|
"ImportPath": "github.com/coreos/etcd/clientv3/concurrency",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3/namespace",
|
"ImportPath": "github.com/coreos/etcd/clientv3/namespace",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3/naming",
|
"ImportPath": "github.com/coreos/etcd/clientv3/naming",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/compactor",
|
"ImportPath": "github.com/coreos/etcd/compactor",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/discovery",
|
"ImportPath": "github.com/coreos/etcd/discovery",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/embed",
|
"ImportPath": "github.com/coreos/etcd/embed",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/error",
|
"ImportPath": "github.com/coreos/etcd/error",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver",
|
"ImportPath": "github.com/coreos/etcd/etcdserver",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/etcdhttp",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/etcdhttp",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http/httptypes",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http/httptypes",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2v3",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2v3",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3client",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3client",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb/gw",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb/gw",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb/gw",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3lock/v3lockpb/gw",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/auth",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/auth",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb/gw",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb/gw",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/membership",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/membership",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/stats",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/stats",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/integration",
|
"ImportPath": "github.com/coreos/etcd/integration",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/lease",
|
"ImportPath": "github.com/coreos/etcd/lease",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/lease/leasehttp",
|
"ImportPath": "github.com/coreos/etcd/lease/leasehttp",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/lease/leasepb",
|
"ImportPath": "github.com/coreos/etcd/lease/leasepb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/mvcc",
|
"ImportPath": "github.com/coreos/etcd/mvcc",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/mvcc/backend",
|
"ImportPath": "github.com/coreos/etcd/mvcc/backend",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/adt",
|
"ImportPath": "github.com/coreos/etcd/pkg/adt",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/contention",
|
"ImportPath": "github.com/coreos/etcd/pkg/contention",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/cors",
|
"ImportPath": "github.com/coreos/etcd/pkg/cors",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/cpuutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/cpuutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/crc",
|
"ImportPath": "github.com/coreos/etcd/pkg/crc",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/debugutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/debugutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/fileutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/fileutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/httputil",
|
"ImportPath": "github.com/coreos/etcd/pkg/httputil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/idutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/idutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/ioutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/ioutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/logutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/logutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/netutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/netutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/pbutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/pbutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/runtime",
|
"ImportPath": "github.com/coreos/etcd/pkg/runtime",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/schedule",
|
"ImportPath": "github.com/coreos/etcd/pkg/schedule",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/srv",
|
"ImportPath": "github.com/coreos/etcd/pkg/srv",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/testutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/testutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/wait",
|
"ImportPath": "github.com/coreos/etcd/pkg/wait",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy",
|
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/adapter",
|
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/adapter",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/cache",
|
"ImportPath": "github.com/coreos/etcd/proxy/grpcproxy/cache",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/raft",
|
"ImportPath": "github.com/coreos/etcd/raft",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/raft/raftpb",
|
"ImportPath": "github.com/coreos/etcd/raft/raftpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/rafthttp",
|
"ImportPath": "github.com/coreos/etcd/rafthttp",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/snap",
|
"ImportPath": "github.com/coreos/etcd/snap",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/snap/snappb",
|
"ImportPath": "github.com/coreos/etcd/snap/snappb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/store",
|
"ImportPath": "github.com/coreos/etcd/store",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/version",
|
"ImportPath": "github.com/coreos/etcd/version",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/wal",
|
"ImportPath": "github.com/coreos/etcd/wal",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/wal/walpb",
|
"ImportPath": "github.com/coreos/etcd/wal/walpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-oidc",
|
"ImportPath": "github.com/coreos/go-oidc",
|
||||||
|
@ -336,19 +336,19 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-semver/semver",
|
"ImportPath": "github.com/coreos/go-semver/semver",
|
||||||
"Rev": "568e959cd89871e61434c1143528d9162da89ef2"
|
"Rev": "e214231b295a8ea9479f11b70b35d5acf3556d9b"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-systemd/daemon",
|
"ImportPath": "github.com/coreos/go-systemd/daemon",
|
||||||
"Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6"
|
"Rev": "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-systemd/journal",
|
"ImportPath": "github.com/coreos/go-systemd/journal",
|
||||||
"Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6"
|
"Rev": "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/pkg/capnslog",
|
"ImportPath": "github.com/coreos/pkg/capnslog",
|
||||||
"Rev": "fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8"
|
"Rev": "97fdf19511ea361ae1c100dd393cc47f8dcfa1e1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/davecgh/go-spew/spew",
|
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||||
|
@ -490,6 +490,10 @@
|
||||||
"ImportPath": "github.com/gregjones/httpcache/diskcache",
|
"ImportPath": "github.com/gregjones/httpcache/diskcache",
|
||||||
"Rev": "787624de3eb7bd915c329cba748687a3b22666a6"
|
"Rev": "787624de3eb7bd915c329cba748687a3b22666a6"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/grpc-ecosystem/go-grpc-middleware",
|
||||||
|
"Rev": "498ae206fc3cfe81cd82e48c1d4354026fa5f9ec"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus",
|
"ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus",
|
||||||
"Rev": "2500245aa6110c562d17020fb31a2c133d737799"
|
"Rev": "2500245aa6110c562d17020fb31a2c133d737799"
|
||||||
|
@ -634,6 +638,38 @@
|
||||||
"ImportPath": "github.com/xiang90/probing",
|
"ImportPath": "github.com/xiang90/probing",
|
||||||
"Rev": "07dd2e8dfe18522e9c447ba95f2fe95262f63bb2"
|
"Rev": "07dd2e8dfe18522e9c447ba95f2fe95262f63bb2"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/atomic",
|
||||||
|
"Rev": "8dc6146f7569370a472715e178d8ae31172ee6da"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/multierr",
|
||||||
|
"Rev": "ddea229ff1dff9e6fe8a6c0344ac73b09e81fce5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/buffer",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/internal/bufferpool",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/internal/color",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/internal/exit",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "go.uber.org/zap/zapcore",
|
||||||
|
"Rev": "67bc79d13d155c02fd008f721863ff8cc5f30659"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/bcrypt",
|
"ImportPath": "golang.org/x/crypto/bcrypt",
|
||||||
"Rev": "de0752318171da717af4ce24d0a2e8626afaeb11"
|
"Rev": "de0752318171da717af4ce24d0a2e8626afaeb11"
|
||||||
|
|
|
@ -36,39 +36,39 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3",
|
"ImportPath": "github.com/coreos/etcd/clientv3",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-systemd/daemon",
|
"ImportPath": "github.com/coreos/go-systemd/daemon",
|
||||||
"Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6"
|
"Rev": "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/davecgh/go-spew/spew",
|
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||||
|
|
|
@ -36,39 +36,39 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
"ImportPath": "github.com/coreos/etcd/auth/authpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/clientv3",
|
"ImportPath": "github.com/coreos/etcd/clientv3",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/tlsutil",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
||||||
"Rev": "fca8add78a9d926166eb739b8e4a124434025ba3"
|
"Rev": "27fc7e2296f506182f58ce846e48f36b34fe6842"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-systemd/daemon",
|
"ImportPath": "github.com/coreos/go-systemd/daemon",
|
||||||
"Rev": "48702e0da86bd25e76cfef347e2adeb434a0d0a6"
|
"Rev": "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/davecgh/go-spew/spew",
|
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||||
|
|
|
@ -265,6 +265,7 @@ filegroup(
|
||||||
"//vendor/github.com/gophercloud/gophercloud:all-srcs",
|
"//vendor/github.com/gophercloud/gophercloud:all-srcs",
|
||||||
"//vendor/github.com/gorilla/websocket:all-srcs",
|
"//vendor/github.com/gorilla/websocket:all-srcs",
|
||||||
"//vendor/github.com/gregjones/httpcache:all-srcs",
|
"//vendor/github.com/gregjones/httpcache:all-srcs",
|
||||||
|
"//vendor/github.com/grpc-ecosystem/go-grpc-middleware:all-srcs",
|
||||||
"//vendor/github.com/grpc-ecosystem/go-grpc-prometheus:all-srcs",
|
"//vendor/github.com/grpc-ecosystem/go-grpc-prometheus:all-srcs",
|
||||||
"//vendor/github.com/grpc-ecosystem/grpc-gateway/runtime:all-srcs",
|
"//vendor/github.com/grpc-ecosystem/grpc-gateway/runtime:all-srcs",
|
||||||
"//vendor/github.com/grpc-ecosystem/grpc-gateway/utilities:all-srcs",
|
"//vendor/github.com/grpc-ecosystem/grpc-gateway/utilities:all-srcs",
|
||||||
|
@ -368,6 +369,9 @@ filegroup(
|
||||||
"//vendor/github.com/vmware/photon-controller-go-sdk/photon:all-srcs",
|
"//vendor/github.com/vmware/photon-controller-go-sdk/photon:all-srcs",
|
||||||
"//vendor/github.com/xanzy/go-cloudstack/cloudstack:all-srcs",
|
"//vendor/github.com/xanzy/go-cloudstack/cloudstack:all-srcs",
|
||||||
"//vendor/github.com/xiang90/probing:all-srcs",
|
"//vendor/github.com/xiang90/probing:all-srcs",
|
||||||
|
"//vendor/go.uber.org/atomic:all-srcs",
|
||||||
|
"//vendor/go.uber.org/multierr:all-srcs",
|
||||||
|
"//vendor/go.uber.org/zap:all-srcs",
|
||||||
"//vendor/golang.org/x/crypto/bcrypt:all-srcs",
|
"//vendor/golang.org/x/crypto/bcrypt:all-srcs",
|
||||||
"//vendor/golang.org/x/crypto/blowfish:all-srcs",
|
"//vendor/golang.org/x/crypto/blowfish:all-srcs",
|
||||||
"//vendor/golang.org/x/crypto/cryptobyte:all-srcs",
|
"//vendor/golang.org/x/crypto/cryptobyte:all-srcs",
|
||||||
|
|
|
@ -68,11 +68,10 @@ func (m *Mutex) Lock(ctx context.Context) error {
|
||||||
|
|
||||||
// wait for deletion revisions prior to myKey
|
// wait for deletion revisions prior to myKey
|
||||||
hdr, werr := waitDeletes(ctx, client, m.pfx, m.myRev-1)
|
hdr, werr := waitDeletes(ctx, client, m.pfx, m.myRev-1)
|
||||||
// release lock key if cancelled
|
// release lock key if wait failed
|
||||||
select {
|
if werr != nil {
|
||||||
case <-ctx.Done():
|
|
||||||
m.Unlock(client.Ctx())
|
m.Unlock(client.Ctx())
|
||||||
default:
|
} else {
|
||||||
m.hdr = hdr
|
m.hdr = hdr
|
||||||
}
|
}
|
||||||
return werr
|
return werr
|
||||||
|
|
|
@ -23,6 +23,7 @@ go_library(
|
||||||
"//vendor/github.com/coreos/etcd/rafthttp:go_default_library",
|
"//vendor/github.com/coreos/etcd/rafthttp:go_default_library",
|
||||||
"//vendor/github.com/coreos/etcd/version:go_default_library",
|
"//vendor/github.com/coreos/etcd/version:go_default_library",
|
||||||
"//vendor/github.com/coreos/pkg/capnslog:go_default_library",
|
"//vendor/github.com/coreos/pkg/capnslog:go_default_library",
|
||||||
|
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||||
"//vendor/github.com/prometheus/client_golang/prometheus/promhttp:go_default_library",
|
"//vendor/github.com/prometheus/client_golang/prometheus/promhttp:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/coreos/etcd/etcdserver/etcdserverpb"
|
"github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||||
"github.com/coreos/etcd/raft"
|
"github.com/coreos/etcd/raft"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,11 +44,6 @@ func HandlePrometheus(mux *http.ServeMux) {
|
||||||
mux.Handle(pathMetrics, promhttp.Handler())
|
mux.Handle(pathMetrics, promhttp.Handler())
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleHealth registers health handler on '/health'.
|
|
||||||
func HandleHealth(mux *http.ServeMux, srv etcdserver.ServerV2) {
|
|
||||||
mux.Handle(PathHealth, NewHealthHandler(func() Health { return checkHealth(srv) }))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewHealthHandler handles '/health' requests.
|
// NewHealthHandler handles '/health' requests.
|
||||||
func NewHealthHandler(hfunc func() Health) http.HandlerFunc {
|
func NewHealthHandler(hfunc func() Health) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -67,6 +63,26 @@ func NewHealthHandler(hfunc func() Health) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
healthSuccess = prometheus.NewCounter(prometheus.CounterOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "server",
|
||||||
|
Name: "health_success",
|
||||||
|
Help: "The total number of successful health checks",
|
||||||
|
})
|
||||||
|
healthFailed = prometheus.NewCounter(prometheus.CounterOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "server",
|
||||||
|
Name: "health_failures",
|
||||||
|
Help: "The total number of failed health checks",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
prometheus.MustRegister(healthSuccess)
|
||||||
|
prometheus.MustRegister(healthFailed)
|
||||||
|
}
|
||||||
|
|
||||||
// Health defines etcd server health status.
|
// Health defines etcd server health status.
|
||||||
// TODO: remove manual parsing in etcdctl cluster-health
|
// TODO: remove manual parsing in etcdctl cluster-health
|
||||||
type Health struct {
|
type Health struct {
|
||||||
|
@ -97,5 +113,11 @@ func checkHealth(srv etcdserver.ServerV2) Health {
|
||||||
h.Health = "false"
|
h.Health = "false"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if h.Health == "true" {
|
||||||
|
healthSuccess.Inc()
|
||||||
|
} else {
|
||||||
|
healthFailed.Inc()
|
||||||
|
}
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,15 +37,17 @@ go_library(
|
||||||
"//vendor/github.com/coreos/etcd/version:go_default_library",
|
"//vendor/github.com/coreos/etcd/version:go_default_library",
|
||||||
"//vendor/github.com/coreos/pkg/capnslog:go_default_library",
|
"//vendor/github.com/coreos/pkg/capnslog:go_default_library",
|
||||||
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
|
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
|
||||||
|
"//vendor/github.com/grpc-ecosystem/go-grpc-middleware:go_default_library",
|
||||||
"//vendor/github.com/grpc-ecosystem/go-grpc-prometheus:go_default_library",
|
"//vendor/github.com/grpc-ecosystem/go-grpc-prometheus:go_default_library",
|
||||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||||
|
"//vendor/go.uber.org/zap:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc:go_default_library",
|
"//vendor/google.golang.org/grpc:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc/codes:go_default_library",
|
"//vendor/google.golang.org/grpc/codes:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc/credentials:go_default_library",
|
"//vendor/google.golang.org/grpc/credentials:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc/grpclog:go_default_library",
|
|
||||||
"//vendor/google.golang.org/grpc/health:go_default_library",
|
"//vendor/google.golang.org/grpc/health:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc/health/grpc_health_v1:go_default_library",
|
"//vendor/google.golang.org/grpc/health/grpc_health_v1:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc/metadata:go_default_library",
|
"//vendor/google.golang.org/grpc/metadata:go_default_library",
|
||||||
|
"//vendor/google.golang.org/grpc/peer:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc/status:go_default_library",
|
"//vendor/google.golang.org/grpc/status:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,18 +16,15 @@ package v3rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"io/ioutil"
|
|
||||||
"math"
|
"math"
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/coreos/etcd/etcdserver"
|
"github.com/coreos/etcd/etcdserver"
|
||||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||||
|
|
||||||
|
"github.com/grpc-ecosystem/go-grpc-middleware"
|
||||||
"github.com/grpc-ecosystem/go-grpc-prometheus"
|
"github.com/grpc-ecosystem/go-grpc-prometheus"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
"google.golang.org/grpc/grpclog"
|
|
||||||
"google.golang.org/grpc/health"
|
"google.golang.org/grpc/health"
|
||||||
healthpb "google.golang.org/grpc/health/grpc_health_v1"
|
healthpb "google.golang.org/grpc/health/grpc_health_v1"
|
||||||
)
|
)
|
||||||
|
@ -38,17 +35,21 @@ const (
|
||||||
maxSendBytes = math.MaxInt32
|
maxSendBytes = math.MaxInt32
|
||||||
)
|
)
|
||||||
|
|
||||||
// integration tests call this multiple times, which is racey in gRPC side
|
|
||||||
var grpclogOnce sync.Once
|
|
||||||
|
|
||||||
func Server(s *etcdserver.EtcdServer, tls *tls.Config, gopts ...grpc.ServerOption) *grpc.Server {
|
func Server(s *etcdserver.EtcdServer, tls *tls.Config, gopts ...grpc.ServerOption) *grpc.Server {
|
||||||
var opts []grpc.ServerOption
|
var opts []grpc.ServerOption
|
||||||
opts = append(opts, grpc.CustomCodec(&codec{}))
|
opts = append(opts, grpc.CustomCodec(&codec{}))
|
||||||
if tls != nil {
|
if tls != nil {
|
||||||
opts = append(opts, grpc.Creds(credentials.NewTLS(tls)))
|
opts = append(opts, grpc.Creds(credentials.NewTLS(tls)))
|
||||||
}
|
}
|
||||||
opts = append(opts, grpc.UnaryInterceptor(newUnaryInterceptor(s)))
|
opts = append(opts, grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
|
||||||
opts = append(opts, grpc.StreamInterceptor(newStreamInterceptor(s)))
|
newLogUnaryInterceptor(s),
|
||||||
|
newUnaryInterceptor(s),
|
||||||
|
grpc_prometheus.UnaryServerInterceptor,
|
||||||
|
)))
|
||||||
|
opts = append(opts, grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
|
||||||
|
newStreamInterceptor(s),
|
||||||
|
grpc_prometheus.StreamServerInterceptor,
|
||||||
|
)))
|
||||||
opts = append(opts, grpc.MaxRecvMsgSize(int(s.Cfg.MaxRequestBytes+grpcOverheadBytes)))
|
opts = append(opts, grpc.MaxRecvMsgSize(int(s.Cfg.MaxRequestBytes+grpcOverheadBytes)))
|
||||||
opts = append(opts, grpc.MaxSendMsgSize(maxSendBytes))
|
opts = append(opts, grpc.MaxSendMsgSize(maxSendBytes))
|
||||||
opts = append(opts, grpc.MaxConcurrentStreams(maxStreams))
|
opts = append(opts, grpc.MaxConcurrentStreams(maxStreams))
|
||||||
|
@ -71,16 +72,5 @@ func Server(s *etcdserver.EtcdServer, tls *tls.Config, gopts ...grpc.ServerOptio
|
||||||
// set zero values for metrics registered for this grpc server
|
// set zero values for metrics registered for this grpc server
|
||||||
grpc_prometheus.Register(grpcServer)
|
grpc_prometheus.Register(grpcServer)
|
||||||
|
|
||||||
grpclogOnce.Do(func() {
|
|
||||||
if s.Cfg.Debug {
|
|
||||||
grpc.EnableTracing = true
|
|
||||||
// enable info, warning, error
|
|
||||||
grpclog.SetLoggerV2(grpclog.NewLoggerV2(os.Stderr, os.Stderr, os.Stderr))
|
|
||||||
} else {
|
|
||||||
// only discard info
|
|
||||||
grpclog.SetLoggerV2(grpclog.NewLoggerV2(ioutil.Discard, os.Stderr, os.Stderr))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return grpcServer
|
return grpcServer
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,11 @@ import (
|
||||||
"github.com/coreos/etcd/pkg/types"
|
"github.com/coreos/etcd/pkg/types"
|
||||||
"github.com/coreos/etcd/raft"
|
"github.com/coreos/etcd/raft"
|
||||||
|
|
||||||
prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
|
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||||
|
"go.uber.org/zap"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
|
"google.golang.org/grpc/peer"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -40,7 +42,7 @@ type streamsMap struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor {
|
func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor {
|
||||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||||
if !api.IsCapabilityEnabled(api.V3rpcCapability) {
|
if !api.IsCapabilityEnabled(api.V3rpcCapability) {
|
||||||
return nil, rpctypes.ErrGRPCNotCapable
|
return nil, rpctypes.ErrGRPCNotCapable
|
||||||
}
|
}
|
||||||
|
@ -54,7 +56,124 @@ func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return prometheus.UnaryServerInterceptor(ctx, req, info, handler)
|
return handler(ctx, req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLogUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor {
|
||||||
|
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||||
|
startTime := time.Now()
|
||||||
|
resp, err := handler(ctx, req)
|
||||||
|
defer logUnaryRequestStats(ctx, nil, info, startTime, req, resp)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func logUnaryRequestStats(ctx context.Context, lg *zap.Logger, info *grpc.UnaryServerInfo, startTime time.Time, req interface{}, resp interface{}) {
|
||||||
|
duration := time.Since(startTime)
|
||||||
|
remote := "No remote client info."
|
||||||
|
peerInfo, ok := peer.FromContext(ctx)
|
||||||
|
if ok {
|
||||||
|
remote = peerInfo.Addr.String()
|
||||||
|
}
|
||||||
|
var responseType string = info.FullMethod
|
||||||
|
var reqCount, respCount int64
|
||||||
|
var reqSize, respSize int
|
||||||
|
var reqContent string
|
||||||
|
switch _resp := resp.(type) {
|
||||||
|
case *pb.RangeResponse:
|
||||||
|
_req, ok := req.(*pb.RangeRequest)
|
||||||
|
if ok {
|
||||||
|
reqCount = 0
|
||||||
|
reqSize = _req.Size()
|
||||||
|
reqContent = _req.String()
|
||||||
|
}
|
||||||
|
if _resp != nil {
|
||||||
|
respCount = _resp.GetCount()
|
||||||
|
respSize = _resp.Size()
|
||||||
|
}
|
||||||
|
case *pb.PutResponse:
|
||||||
|
_req, ok := req.(*pb.PutRequest)
|
||||||
|
if ok {
|
||||||
|
reqCount = 1
|
||||||
|
reqSize = _req.Size()
|
||||||
|
reqContent = pb.NewLoggablePutRequest(_req).String()
|
||||||
|
// redact value field from request content, see PR #9821
|
||||||
|
}
|
||||||
|
if _resp != nil {
|
||||||
|
respCount = 0
|
||||||
|
respSize = _resp.Size()
|
||||||
|
}
|
||||||
|
case *pb.DeleteRangeResponse:
|
||||||
|
_req, ok := req.(*pb.DeleteRangeRequest)
|
||||||
|
if ok {
|
||||||
|
reqCount = 0
|
||||||
|
reqSize = _req.Size()
|
||||||
|
reqContent = _req.String()
|
||||||
|
}
|
||||||
|
if _resp != nil {
|
||||||
|
respCount = _resp.GetDeleted()
|
||||||
|
respSize = _resp.Size()
|
||||||
|
}
|
||||||
|
case *pb.TxnResponse:
|
||||||
|
_req, ok := req.(*pb.TxnRequest)
|
||||||
|
if ok && _resp != nil {
|
||||||
|
if _resp.GetSucceeded() { // determine the 'actual' count and size of request based on success or failure
|
||||||
|
reqCount = int64(len(_req.GetSuccess()))
|
||||||
|
reqSize = 0
|
||||||
|
for _, r := range _req.GetSuccess() {
|
||||||
|
reqSize += r.Size()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reqCount = int64(len(_req.GetFailure()))
|
||||||
|
reqSize = 0
|
||||||
|
for _, r := range _req.GetFailure() {
|
||||||
|
reqSize += r.Size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reqContent = pb.NewLoggableTxnRequest(_req).String()
|
||||||
|
// redact value field from request content, see PR #9821
|
||||||
|
}
|
||||||
|
if _resp != nil {
|
||||||
|
respCount = 0
|
||||||
|
respSize = _resp.Size()
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
reqCount = -1
|
||||||
|
reqSize = -1
|
||||||
|
respCount = -1
|
||||||
|
respSize = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
logGenericRequestStats(lg, startTime, duration, remote, responseType, reqCount, reqSize, respCount, respSize, reqContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
func logGenericRequestStats(lg *zap.Logger, startTime time.Time, duration time.Duration, remote string, responseType string,
|
||||||
|
reqCount int64, reqSize int, respCount int64, respSize int, reqContent string) {
|
||||||
|
if lg == nil {
|
||||||
|
plog.Debugf("start time = %v, "+
|
||||||
|
"time spent = %v, "+
|
||||||
|
"remote = %s, "+
|
||||||
|
"response type = %s, "+
|
||||||
|
"request count = %d, "+
|
||||||
|
"request size = %d, "+
|
||||||
|
"response count = %d, "+
|
||||||
|
"response size = %d, "+
|
||||||
|
"request content = %s",
|
||||||
|
startTime, duration, remote, responseType, reqCount, reqSize, respCount, respSize, reqContent,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
lg.Debug("request stats",
|
||||||
|
zap.Time("start time", startTime),
|
||||||
|
zap.Duration("time spent", duration),
|
||||||
|
zap.String("remote", remote),
|
||||||
|
zap.String("response type", responseType),
|
||||||
|
zap.Int64("request count", reqCount),
|
||||||
|
zap.Int("request size", reqSize),
|
||||||
|
zap.Int64("response count", respCount),
|
||||||
|
zap.Int("response size", respSize),
|
||||||
|
zap.String("request content", reqContent),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +209,7 @@ func newStreamInterceptor(s *etcdserver.EtcdServer) grpc.StreamServerInterceptor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return prometheus.StreamServerInterceptor(srv, ss, info, handler)
|
return handler(srv, ss)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal_stringer.go
generated
vendored
6
vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal_stringer.go
generated
vendored
|
@ -59,7 +59,7 @@ func (as *InternalRaftStringer) String() string {
|
||||||
case as.Request.Put != nil:
|
case as.Request.Put != nil:
|
||||||
return fmt.Sprintf("header:<%s> put:<%s>",
|
return fmt.Sprintf("header:<%s> put:<%s>",
|
||||||
as.Request.Header.String(),
|
as.Request.Header.String(),
|
||||||
newLoggablePutRequest(as.Request.Put).String(),
|
NewLoggablePutRequest(as.Request.Put).String(),
|
||||||
)
|
)
|
||||||
case as.Request.Txn != nil:
|
case as.Request.Txn != nil:
|
||||||
return fmt.Sprintf("header:<%s> txn:<%s>",
|
return fmt.Sprintf("header:<%s> txn:<%s>",
|
||||||
|
@ -121,7 +121,7 @@ func newLoggableRequestOp(op *RequestOp) *requestOpStringer {
|
||||||
func (as *requestOpStringer) String() string {
|
func (as *requestOpStringer) String() string {
|
||||||
switch op := as.Op.Request.(type) {
|
switch op := as.Op.Request.(type) {
|
||||||
case *RequestOp_RequestPut:
|
case *RequestOp_RequestPut:
|
||||||
return fmt.Sprintf("request_put:<%s>", newLoggablePutRequest(op.RequestPut).String())
|
return fmt.Sprintf("request_put:<%s>", NewLoggablePutRequest(op.RequestPut).String())
|
||||||
case *RequestOp_RequestTxn:
|
case *RequestOp_RequestTxn:
|
||||||
return fmt.Sprintf("request_txn:<%s>", NewLoggableTxnRequest(op.RequestTxn).String())
|
return fmt.Sprintf("request_txn:<%s>", NewLoggableTxnRequest(op.RequestTxn).String())
|
||||||
default:
|
default:
|
||||||
|
@ -167,7 +167,7 @@ type loggablePutRequest struct {
|
||||||
IgnoreLease bool `protobuf:"varint,6,opt,name=ignore_lease,proto3"`
|
IgnoreLease bool `protobuf:"varint,6,opt,name=ignore_lease,proto3"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLoggablePutRequest(request *PutRequest) *loggablePutRequest {
|
func NewLoggablePutRequest(request *PutRequest) *loggablePutRequest {
|
||||||
return &loggablePutRequest{
|
return &loggablePutRequest{
|
||||||
request.Key,
|
request.Key,
|
||||||
len(request.Value),
|
len(request.Value),
|
||||||
|
|
|
@ -90,6 +90,12 @@ var (
|
||||||
Name: "slow_read_indexes_total",
|
Name: "slow_read_indexes_total",
|
||||||
Help: "The total number of pending read indexes not in sync with leader's or timed out read index requests.",
|
Help: "The total number of pending read indexes not in sync with leader's or timed out read index requests.",
|
||||||
})
|
})
|
||||||
|
readIndexFailed = prometheus.NewCounter(prometheus.CounterOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "server",
|
||||||
|
Name: "read_indexes_failed_total",
|
||||||
|
Help: "The total number of failed read indexes seen.",
|
||||||
|
})
|
||||||
quotaBackendBytes = prometheus.NewGauge(prometheus.GaugeOpts{
|
quotaBackendBytes = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||||
Namespace: "etcd",
|
Namespace: "etcd",
|
||||||
Subsystem: "server",
|
Subsystem: "server",
|
||||||
|
@ -110,6 +116,13 @@ var (
|
||||||
Help: "Which Go version server is running with. 1 for 'server_go_version' label with current version.",
|
Help: "Which Go version server is running with. 1 for 'server_go_version' label with current version.",
|
||||||
},
|
},
|
||||||
[]string{"server_go_version"})
|
[]string{"server_go_version"})
|
||||||
|
serverID = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "server",
|
||||||
|
Name: "id",
|
||||||
|
Help: "Server or member ID in hexadecimal format. 1 for 'server_id' label with current ID.",
|
||||||
|
},
|
||||||
|
[]string{"server_id"})
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -124,9 +137,11 @@ func init() {
|
||||||
prometheus.MustRegister(proposalsFailed)
|
prometheus.MustRegister(proposalsFailed)
|
||||||
prometheus.MustRegister(leaseExpired)
|
prometheus.MustRegister(leaseExpired)
|
||||||
prometheus.MustRegister(slowReadIndex)
|
prometheus.MustRegister(slowReadIndex)
|
||||||
|
prometheus.MustRegister(readIndexFailed)
|
||||||
prometheus.MustRegister(quotaBackendBytes)
|
prometheus.MustRegister(quotaBackendBytes)
|
||||||
prometheus.MustRegister(currentVersion)
|
prometheus.MustRegister(currentVersion)
|
||||||
prometheus.MustRegister(currentGoVersion)
|
prometheus.MustRegister(currentGoVersion)
|
||||||
|
prometheus.MustRegister(serverID)
|
||||||
|
|
||||||
currentVersion.With(prometheus.Labels{
|
currentVersion.With(prometheus.Labels{
|
||||||
"server_version": version.Version,
|
"server_version": version.Version,
|
||||||
|
|
|
@ -59,6 +59,7 @@ import (
|
||||||
|
|
||||||
"github.com/coreos/go-semver/semver"
|
"github.com/coreos/go-semver/semver"
|
||||||
"github.com/coreos/pkg/capnslog"
|
"github.com/coreos/pkg/capnslog"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -435,6 +436,7 @@ func NewServer(cfg ServerConfig) (srv *EtcdServer, err error) {
|
||||||
reqIDGen: idutil.NewGenerator(uint16(id), time.Now()),
|
reqIDGen: idutil.NewGenerator(uint16(id), time.Now()),
|
||||||
forceVersionC: make(chan struct{}),
|
forceVersionC: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
serverID.With(prometheus.Labels{"server_id": id.String()}).Set(1)
|
||||||
|
|
||||||
srv.applyV2 = &applierV2store{store: srv.store, cluster: srv.cluster}
|
srv.applyV2 = &applierV2store{store: srv.store, cluster: srv.cluster}
|
||||||
|
|
||||||
|
|
|
@ -634,6 +634,7 @@ func (s *EtcdServer) linearizableReadLoop() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
plog.Errorf("failed to get read index from raft: %v", err)
|
plog.Errorf("failed to get read index from raft: %v", err)
|
||||||
|
readIndexFailed.Inc()
|
||||||
nr.notify(err)
|
nr.notify(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -659,7 +660,7 @@ func (s *EtcdServer) linearizableReadLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-time.After(s.Cfg.ReqTimeout()):
|
case <-time.After(s.Cfg.ReqTimeout()):
|
||||||
plog.Warningf("timed out waiting for read index response")
|
plog.Warningf("timed out waiting for read index response (local node might have slow network)")
|
||||||
nr.notify(ErrTimeout)
|
nr.notify(ErrTimeout)
|
||||||
timeout = true
|
timeout = true
|
||||||
slowReadIndex.Inc()
|
slowReadIndex.Inc()
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
pioutil "github.com/coreos/etcd/pkg/ioutil"
|
pioutil "github.com/coreos/etcd/pkg/ioutil"
|
||||||
"github.com/coreos/etcd/pkg/types"
|
"github.com/coreos/etcd/pkg/types"
|
||||||
|
@ -149,6 +150,8 @@ func newSnapshotHandler(tr Transporter, r Raft, snapshotter *snap.Snapshotter, c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const unknownSnapshotSender = "UNKNOWN_SNAPSHOT_SENDER"
|
||||||
|
|
||||||
// ServeHTTP serves HTTP request to receive and process snapshot message.
|
// ServeHTTP serves HTTP request to receive and process snapshot message.
|
||||||
//
|
//
|
||||||
// If request sender dies without closing underlying TCP connection,
|
// If request sender dies without closing underlying TCP connection,
|
||||||
|
@ -159,9 +162,12 @@ func newSnapshotHandler(tr Transporter, r Raft, snapshotter *snap.Snapshotter, c
|
||||||
// received and processed.
|
// received and processed.
|
||||||
// 2. this case should happen rarely, so no further optimization is done.
|
// 2. this case should happen rarely, so no further optimization is done.
|
||||||
func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
if r.Method != "POST" {
|
if r.Method != "POST" {
|
||||||
w.Header().Set("Allow", "POST")
|
w.Header().Set("Allow", "POST")
|
||||||
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
|
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
|
||||||
|
snapshotReceiveFailures.WithLabelValues(unknownSnapshotSender).Inc()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,6 +175,7 @@ func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
if err := checkClusterCompatibilityFromHeader(r.Header, h.cid); err != nil {
|
if err := checkClusterCompatibilityFromHeader(r.Header, h.cid); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusPreconditionFailed)
|
http.Error(w, err.Error(), http.StatusPreconditionFailed)
|
||||||
|
snapshotReceiveFailures.WithLabelValues(unknownSnapshotSender).Inc()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,19 +184,22 @@ func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
dec := &messageDecoder{r: r.Body}
|
dec := &messageDecoder{r: r.Body}
|
||||||
// let snapshots be very large since they can exceed 512MB for large installations
|
// let snapshots be very large since they can exceed 512MB for large installations
|
||||||
m, err := dec.decodeLimit(uint64(1 << 63))
|
m, err := dec.decodeLimit(uint64(1 << 63))
|
||||||
|
from := types.ID(m.From).String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("failed to decode raft message (%v)", err)
|
msg := fmt.Sprintf("failed to decode raft message (%v)", err)
|
||||||
plog.Errorf(msg)
|
plog.Errorf(msg)
|
||||||
http.Error(w, msg, http.StatusBadRequest)
|
http.Error(w, msg, http.StatusBadRequest)
|
||||||
recvFailures.WithLabelValues(r.RemoteAddr).Inc()
|
recvFailures.WithLabelValues(r.RemoteAddr).Inc()
|
||||||
|
snapshotReceiveFailures.WithLabelValues(from).Inc()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(m.Size()))
|
receivedBytes.WithLabelValues(from).Add(float64(m.Size()))
|
||||||
|
|
||||||
if m.Type != raftpb.MsgSnap {
|
if m.Type != raftpb.MsgSnap {
|
||||||
plog.Errorf("unexpected raft message type %s on snapshot path", m.Type)
|
plog.Errorf("unexpected raft message type %s on snapshot path", m.Type)
|
||||||
http.Error(w, "wrong raft message type", http.StatusBadRequest)
|
http.Error(w, "wrong raft message type", http.StatusBadRequest)
|
||||||
|
snapshotReceiveFailures.WithLabelValues(from).Inc()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,9 +210,10 @@ func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
msg := fmt.Sprintf("failed to save KV snapshot (%v)", err)
|
msg := fmt.Sprintf("failed to save KV snapshot (%v)", err)
|
||||||
plog.Error(msg)
|
plog.Error(msg)
|
||||||
http.Error(w, msg, http.StatusInternalServerError)
|
http.Error(w, msg, http.StatusInternalServerError)
|
||||||
|
snapshotReceiveFailures.WithLabelValues(from).Inc()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(n))
|
receivedBytes.WithLabelValues(from).Add(float64(n))
|
||||||
plog.Infof("received and saved database snapshot [index: %d, from: %s] successfully", m.Snapshot.Metadata.Index, types.ID(m.From))
|
plog.Infof("received and saved database snapshot [index: %d, from: %s] successfully", m.Snapshot.Metadata.Index, types.ID(m.From))
|
||||||
|
|
||||||
if err := h.r.Process(context.TODO(), m); err != nil {
|
if err := h.r.Process(context.TODO(), m); err != nil {
|
||||||
|
@ -215,12 +226,16 @@ func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
msg := fmt.Sprintf("failed to process raft message (%v)", err)
|
msg := fmt.Sprintf("failed to process raft message (%v)", err)
|
||||||
plog.Warningf(msg)
|
plog.Warningf(msg)
|
||||||
http.Error(w, msg, http.StatusInternalServerError)
|
http.Error(w, msg, http.StatusInternalServerError)
|
||||||
|
snapshotReceiveFailures.WithLabelValues(from).Inc()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Write StatusNoContent header after the message has been processed by
|
// Write StatusNoContent header after the message has been processed by
|
||||||
// raft, which facilitates the client to report MsgSnap status.
|
// raft, which facilitates the client to report MsgSnap status.
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
|
||||||
|
snapshotReceive.WithLabelValues(from).Inc()
|
||||||
|
snapshotReceiveSeconds.WithLabelValues(from).Observe(time.Since(start).Seconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
type streamHandler struct {
|
type streamHandler struct {
|
||||||
|
|
|
@ -53,6 +53,68 @@ var (
|
||||||
[]string{"From"},
|
[]string{"From"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
snapshotSend = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "network",
|
||||||
|
Name: "snapshot_send_success",
|
||||||
|
Help: "Total number of successful snapshot sends",
|
||||||
|
},
|
||||||
|
[]string{"To"},
|
||||||
|
)
|
||||||
|
|
||||||
|
snapshotSendFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "network",
|
||||||
|
Name: "snapshot_send_failures",
|
||||||
|
Help: "Total number of snapshot send failures",
|
||||||
|
},
|
||||||
|
[]string{"To"},
|
||||||
|
)
|
||||||
|
|
||||||
|
snapshotSendSeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "network",
|
||||||
|
Name: "snapshot_send_total_duration_seconds",
|
||||||
|
Help: "Total latency distributions of v3 snapshot sends",
|
||||||
|
|
||||||
|
// lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2
|
||||||
|
// highest bucket start of 0.1 sec * 2^9 == 51.2 sec
|
||||||
|
Buckets: prometheus.ExponentialBuckets(0.1, 2, 10),
|
||||||
|
},
|
||||||
|
[]string{"To"},
|
||||||
|
)
|
||||||
|
|
||||||
|
snapshotReceive = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "network",
|
||||||
|
Name: "snapshot_receive_success",
|
||||||
|
Help: "Total number of successful snapshot receives",
|
||||||
|
},
|
||||||
|
[]string{"From"},
|
||||||
|
)
|
||||||
|
|
||||||
|
snapshotReceiveFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "network",
|
||||||
|
Name: "snapshot_receive_failures",
|
||||||
|
Help: "Total number of snapshot receive failures",
|
||||||
|
},
|
||||||
|
[]string{"From"},
|
||||||
|
)
|
||||||
|
|
||||||
|
snapshotReceiveSeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "network",
|
||||||
|
Name: "snapshot_receive_total_duration_seconds",
|
||||||
|
Help: "Total latency distributions of v3 snapshot receives",
|
||||||
|
|
||||||
|
// lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2
|
||||||
|
// highest bucket start of 0.1 sec * 2^9 == 51.2 sec
|
||||||
|
Buckets: prometheus.ExponentialBuckets(0.1, 2, 10),
|
||||||
|
},
|
||||||
|
[]string{"From"},
|
||||||
|
)
|
||||||
|
|
||||||
rtts = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
rtts = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||||
Namespace: "etcd",
|
Namespace: "etcd",
|
||||||
Subsystem: "network",
|
Subsystem: "network",
|
||||||
|
@ -69,5 +131,13 @@ func init() {
|
||||||
prometheus.MustRegister(receivedBytes)
|
prometheus.MustRegister(receivedBytes)
|
||||||
prometheus.MustRegister(sentFailures)
|
prometheus.MustRegister(sentFailures)
|
||||||
prometheus.MustRegister(recvFailures)
|
prometheus.MustRegister(recvFailures)
|
||||||
|
|
||||||
|
prometheus.MustRegister(snapshotSend)
|
||||||
|
prometheus.MustRegister(snapshotSendFailures)
|
||||||
|
prometheus.MustRegister(snapshotSendSeconds)
|
||||||
|
prometheus.MustRegister(snapshotReceive)
|
||||||
|
prometheus.MustRegister(snapshotReceiveFailures)
|
||||||
|
prometheus.MustRegister(snapshotReceiveSeconds)
|
||||||
|
|
||||||
prometheus.MustRegister(rtts)
|
prometheus.MustRegister(rtts)
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ func (s *peerStatus) deactivate(failure failureType, reason string) {
|
||||||
msg := fmt.Sprintf("failed to %s %s on %s (%s)", failure.action, s.id, failure.source, reason)
|
msg := fmt.Sprintf("failed to %s %s on %s (%s)", failure.action, s.id, failure.source, reason)
|
||||||
if s.active {
|
if s.active {
|
||||||
plog.Errorf(msg)
|
plog.Errorf(msg)
|
||||||
plog.Infof("peer %s became inactive", s.id)
|
plog.Infof("peer %s became inactive (message send to peer failed)", s.id)
|
||||||
s.active = false
|
s.active = false
|
||||||
s.since = time.Time{}
|
s.since = time.Time{}
|
||||||
return
|
return
|
||||||
|
|
|
@ -17,6 +17,7 @@ package rafthttp
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/xiang90/probing"
|
"github.com/xiang90/probing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,7 +29,15 @@ var (
|
||||||
statusErrorInterval = 5 * time.Second
|
statusErrorInterval = 5 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
func addPeerToProber(p probing.Prober, id string, us []string) {
|
const (
|
||||||
|
// RoundTripperNameRaftMessage is the name of round-tripper that sends
|
||||||
|
// all other Raft messages, other than "snap.Message".
|
||||||
|
RoundTripperNameRaftMessage = "ROUND_TRIPPER_RAFT_MESSAGE"
|
||||||
|
// RoundTripperNameSnapshot is the name of round-tripper that sends merged snapshot message.
|
||||||
|
RoundTripperNameSnapshot = "ROUND_TRIPPER_SNAPSHOT"
|
||||||
|
)
|
||||||
|
|
||||||
|
func addPeerToProber(p probing.Prober, id string, us []string, roundTripperName string, rttSecProm *prometheus.HistogramVec) {
|
||||||
hus := make([]string, len(us))
|
hus := make([]string, len(us))
|
||||||
for i := range us {
|
for i := range us {
|
||||||
hus[i] = us[i] + ProbingPrefix
|
hus[i] = us[i] + ProbingPrefix
|
||||||
|
@ -40,26 +49,26 @@ func addPeerToProber(p probing.Prober, id string, us []string) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
plog.Errorf("failed to add peer %s into prober", id)
|
plog.Errorf("failed to add peer %s into prober", id)
|
||||||
} else {
|
} else {
|
||||||
go monitorProbingStatus(s, id)
|
go monitorProbingStatus(s, id, roundTripperName, rttSecProm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func monitorProbingStatus(s probing.Status, id string) {
|
func monitorProbingStatus(s probing.Status, id string, roundTripperName string, rttSecProm *prometheus.HistogramVec) {
|
||||||
// set the first interval short to log error early.
|
// set the first interval short to log error early.
|
||||||
interval := statusErrorInterval
|
interval := statusErrorInterval
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-time.After(interval):
|
case <-time.After(interval):
|
||||||
if !s.Health() {
|
if !s.Health() {
|
||||||
plog.Warningf("health check for peer %s could not connect: %v", id, s.Err())
|
plog.Warningf("health check for peer %s could not connect: %v (prober %q)", id, s.Err(), roundTripperName)
|
||||||
interval = statusErrorInterval
|
interval = statusErrorInterval
|
||||||
} else {
|
} else {
|
||||||
interval = statusMonitoringInterval
|
interval = statusMonitoringInterval
|
||||||
}
|
}
|
||||||
if s.ClockDiff() > time.Second {
|
if s.ClockDiff() > time.Second {
|
||||||
plog.Warningf("the clock difference against peer %s is too high [%v > %v]", id, s.ClockDiff(), time.Second)
|
plog.Warningf("the clock difference against peer %s is too high [%v > %v] (prober %q)", id, s.ClockDiff(), time.Second, roundTripperName)
|
||||||
}
|
}
|
||||||
rtts.WithLabelValues(id).Observe(s.SRTT().Seconds())
|
rttSecProm.WithLabelValues(id).Observe(s.SRTT().Seconds())
|
||||||
case <-s.StopNotify():
|
case <-s.StopNotify():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,10 @@ func newSnapshotSender(tr *Transport, picker *urlPicker, to types.ID, status *pe
|
||||||
func (s *snapshotSender) stop() { close(s.stopc) }
|
func (s *snapshotSender) stop() { close(s.stopc) }
|
||||||
|
|
||||||
func (s *snapshotSender) send(merged snap.Message) {
|
func (s *snapshotSender) send(merged snap.Message) {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
m := merged.Message
|
m := merged.Message
|
||||||
|
to := types.ID(m.To).String()
|
||||||
|
|
||||||
body := createSnapBody(merged)
|
body := createSnapBody(merged)
|
||||||
defer body.Close()
|
defer body.Close()
|
||||||
|
@ -92,14 +95,18 @@ func (s *snapshotSender) send(merged snap.Message) {
|
||||||
// machine knows about it, it would pause a while and retry sending
|
// machine knows about it, it would pause a while and retry sending
|
||||||
// new snapshot message.
|
// new snapshot message.
|
||||||
s.r.ReportSnapshot(m.To, raft.SnapshotFailure)
|
s.r.ReportSnapshot(m.To, raft.SnapshotFailure)
|
||||||
sentFailures.WithLabelValues(types.ID(m.To).String()).Inc()
|
sentFailures.WithLabelValues(to).Inc()
|
||||||
|
snapshotSendFailures.WithLabelValues(to).Inc()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.status.activate()
|
s.status.activate()
|
||||||
s.r.ReportSnapshot(m.To, raft.SnapshotFinish)
|
s.r.ReportSnapshot(m.To, raft.SnapshotFinish)
|
||||||
plog.Infof("database snapshot [index: %d, to: %s] sent out successfully", m.Snapshot.Metadata.Index, types.ID(m.To))
|
plog.Infof("database snapshot [index: %d, to: %s] sent out successfully", m.Snapshot.Metadata.Index, types.ID(m.To))
|
||||||
|
|
||||||
sentBytes.WithLabelValues(types.ID(m.To).String()).Add(float64(merged.TotalSize))
|
sentBytes.WithLabelValues(to).Add(float64(merged.TotalSize))
|
||||||
|
|
||||||
|
snapshotSend.WithLabelValues(to).Inc()
|
||||||
|
snapshotSendSeconds.WithLabelValues(to).Observe(time.Since(start).Seconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
// post posts the given request.
|
// post posts the given request.
|
||||||
|
|
|
@ -127,7 +127,8 @@ type Transport struct {
|
||||||
remotes map[types.ID]*remote // remotes map that helps newly joined member to catch up
|
remotes map[types.ID]*remote // remotes map that helps newly joined member to catch up
|
||||||
peers map[types.ID]Peer // peers map
|
peers map[types.ID]Peer // peers map
|
||||||
|
|
||||||
prober probing.Prober
|
pipelineProber probing.Prober
|
||||||
|
streamProber probing.Prober
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) Start() error {
|
func (t *Transport) Start() error {
|
||||||
|
@ -142,7 +143,8 @@ func (t *Transport) Start() error {
|
||||||
}
|
}
|
||||||
t.remotes = make(map[types.ID]*remote)
|
t.remotes = make(map[types.ID]*remote)
|
||||||
t.peers = make(map[types.ID]Peer)
|
t.peers = make(map[types.ID]Peer)
|
||||||
t.prober = probing.NewProber(t.pipelineRt)
|
t.pipelineProber = probing.NewProber(t.pipelineRt)
|
||||||
|
t.streamProber = probing.NewProber(t.streamRt)
|
||||||
|
|
||||||
// If client didn't provide dial retry frequency, use the default
|
// If client didn't provide dial retry frequency, use the default
|
||||||
// (100ms backoff between attempts to create a new stream),
|
// (100ms backoff between attempts to create a new stream),
|
||||||
|
@ -210,7 +212,8 @@ func (t *Transport) Stop() {
|
||||||
for _, p := range t.peers {
|
for _, p := range t.peers {
|
||||||
p.stop()
|
p.stop()
|
||||||
}
|
}
|
||||||
t.prober.RemoveAll()
|
t.pipelineProber.RemoveAll()
|
||||||
|
t.streamProber.RemoveAll()
|
||||||
if tr, ok := t.streamRt.(*http.Transport); ok {
|
if tr, ok := t.streamRt.(*http.Transport); ok {
|
||||||
tr.CloseIdleConnections()
|
tr.CloseIdleConnections()
|
||||||
}
|
}
|
||||||
|
@ -289,8 +292,8 @@ func (t *Transport) AddPeer(id types.ID, us []string) {
|
||||||
}
|
}
|
||||||
fs := t.LeaderStats.Follower(id.String())
|
fs := t.LeaderStats.Follower(id.String())
|
||||||
t.peers[id] = startPeer(t, urls, id, fs)
|
t.peers[id] = startPeer(t, urls, id, fs)
|
||||||
addPeerToProber(t.prober, id.String(), us)
|
addPeerToProber(t.pipelineProber, id.String(), us, RoundTripperNameSnapshot, rtts)
|
||||||
|
addPeerToProber(t.streamProber, id.String(), us, RoundTripperNameRaftMessage, rtts)
|
||||||
plog.Infof("added peer %s", id)
|
plog.Infof("added peer %s", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +320,8 @@ func (t *Transport) removePeer(id types.ID) {
|
||||||
}
|
}
|
||||||
delete(t.peers, id)
|
delete(t.peers, id)
|
||||||
delete(t.LeaderStats.Followers, id.String())
|
delete(t.LeaderStats.Followers, id.String())
|
||||||
t.prober.Remove(id.String())
|
t.pipelineProber.Remove(id.String())
|
||||||
|
t.streamProber.Remove(id.String())
|
||||||
plog.Infof("removed peer %s", id)
|
plog.Infof("removed peer %s", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,8 +338,10 @@ func (t *Transport) UpdatePeer(id types.ID, us []string) {
|
||||||
}
|
}
|
||||||
t.peers[id].update(urls)
|
t.peers[id].update(urls)
|
||||||
|
|
||||||
t.prober.Remove(id.String())
|
t.pipelineProber.Remove(id.String())
|
||||||
addPeerToProber(t.prober, id.String(), us)
|
addPeerToProber(t.pipelineProber, id.String(), us, RoundTripperNameSnapshot, rtts)
|
||||||
|
t.streamProber.Remove(id.String())
|
||||||
|
addPeerToProber(t.streamProber, id.String(), us, RoundTripperNameRaftMessage, rtts)
|
||||||
plog.Infof("updated peer %s", id)
|
plog.Infof("updated peer %s", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/coreos/etcd/pkg/fileutil"
|
"github.com/coreos/etcd/pkg/fileutil"
|
||||||
)
|
)
|
||||||
|
@ -30,6 +31,8 @@ var ErrNoDBSnapshot = errors.New("snap: snapshot file doesn't exist")
|
||||||
// SaveDBFrom saves snapshot of the database from the given reader. It
|
// SaveDBFrom saves snapshot of the database from the given reader. It
|
||||||
// guarantees the save operation is atomic.
|
// guarantees the save operation is atomic.
|
||||||
func (s *Snapshotter) SaveDBFrom(r io.Reader, id uint64) (int64, error) {
|
func (s *Snapshotter) SaveDBFrom(r io.Reader, id uint64) (int64, error) {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
f, err := ioutil.TempFile(s.dir, "tmp")
|
f, err := ioutil.TempFile(s.dir, "tmp")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
@ -37,7 +40,9 @@ func (s *Snapshotter) SaveDBFrom(r io.Reader, id uint64) (int64, error) {
|
||||||
var n int64
|
var n int64
|
||||||
n, err = io.Copy(f, r)
|
n, err = io.Copy(f, r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
fsyncStart := time.Now()
|
||||||
err = fileutil.Fsync(f)
|
err = fileutil.Fsync(f)
|
||||||
|
snapDBFsyncSec.Observe(time.Since(fsyncStart).Seconds())
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -57,6 +62,7 @@ func (s *Snapshotter) SaveDBFrom(r io.Reader, id uint64) (int64, error) {
|
||||||
|
|
||||||
plog.Infof("saved database snapshot to disk [total bytes: %d]", n)
|
plog.Infof("saved database snapshot to disk [total bytes: %d]", n)
|
||||||
|
|
||||||
|
snapDBSaveSec.Observe(time.Since(start).Seconds())
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,9 +33,33 @@ var (
|
||||||
Help: "The marshalling cost distributions of save called by snapshot.",
|
Help: "The marshalling cost distributions of save called by snapshot.",
|
||||||
Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
|
Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
snapDBSaveSec = prometheus.NewHistogram(prometheus.HistogramOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "snap_db",
|
||||||
|
Name: "save_total_duration_seconds",
|
||||||
|
Help: "The total latency distributions of v3 snapshot save",
|
||||||
|
|
||||||
|
// lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2
|
||||||
|
// highest bucket start of 0.1 sec * 2^9 == 51.2 sec
|
||||||
|
Buckets: prometheus.ExponentialBuckets(0.1, 2, 10),
|
||||||
|
})
|
||||||
|
|
||||||
|
snapDBFsyncSec = prometheus.NewHistogram(prometheus.HistogramOpts{
|
||||||
|
Namespace: "etcd",
|
||||||
|
Subsystem: "snap_db",
|
||||||
|
Name: "fsync_duration_seconds",
|
||||||
|
Help: "The latency distributions of fsyncing .snap.db file",
|
||||||
|
|
||||||
|
// lowest bucket start of upper bound 0.001 sec (1 ms) with factor 2
|
||||||
|
// highest bucket start of 0.001 sec * 2^13 == 8.192 sec
|
||||||
|
Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
|
||||||
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
prometheus.MustRegister(saveDurations)
|
prometheus.MustRegister(saveDurations)
|
||||||
prometheus.MustRegister(marshallingDurations)
|
prometheus.MustRegister(marshallingDurations)
|
||||||
|
prometheus.MustRegister(snapDBSaveSec)
|
||||||
|
prometheus.MustRegister(snapDBFsyncSec)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
var (
|
var (
|
||||||
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
|
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
|
||||||
MinClusterVersion = "3.0.0"
|
MinClusterVersion = "3.0.0"
|
||||||
Version = "3.3.9"
|
Version = "3.3.10"
|
||||||
APIVersion = "unknown"
|
APIVersion = "unknown"
|
||||||
|
|
||||||
// Git SHA Value will be set during build
|
// Git SHA Value will be set during build
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
CoreOS Project
|
||||||
|
Copyright 2018 CoreOS, Inc
|
||||||
|
|
||||||
|
This product includes software developed at CoreOS, Inc.
|
||||||
|
(http://www.coreos.com/).
|
|
@ -1,9 +1,25 @@
|
||||||
|
// Copyright 2013-2015 CoreOS, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Semantic Versions http://semver.org
|
||||||
package semver
|
package semver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -29,35 +45,21 @@ func splitOff(input *string, delim string) (val string) {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func New(version string) *Version {
|
||||||
|
return Must(NewVersion(version))
|
||||||
|
}
|
||||||
|
|
||||||
func NewVersion(version string) (*Version, error) {
|
func NewVersion(version string) (*Version, error) {
|
||||||
v := Version{}
|
v := Version{}
|
||||||
|
|
||||||
dotParts := strings.SplitN(version, ".", 3)
|
if err := v.Set(version); err != nil {
|
||||||
|
|
||||||
if len(dotParts) != 3 {
|
|
||||||
return nil, errors.New(fmt.Sprintf("%s is not in dotted-tri format", version))
|
|
||||||
}
|
|
||||||
|
|
||||||
v.Metadata = splitOff(&dotParts[2], "+")
|
|
||||||
v.PreRelease = PreRelease(splitOff(&dotParts[2], "-"))
|
|
||||||
|
|
||||||
parsed := make([]int64, 3, 3)
|
|
||||||
|
|
||||||
for i, v := range dotParts[:3] {
|
|
||||||
val, err := strconv.ParseInt(v, 10, 64)
|
|
||||||
parsed[i] = val
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
v.Major = parsed[0]
|
|
||||||
v.Minor = parsed[1]
|
|
||||||
v.Patch = parsed[2]
|
|
||||||
|
|
||||||
return &v, nil
|
return &v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Must is a helper for wrapping NewVersion and will panic if err is not nil.
|
||||||
func Must(v *Version, err error) *Version {
|
func Must(v *Version, err error) *Version {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -65,45 +67,107 @@ func Must(v *Version, err error) *Version {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Version) String() string {
|
// Set parses and updates v from the given version string. Implements flag.Value
|
||||||
|
func (v *Version) Set(version string) error {
|
||||||
|
metadata := splitOff(&version, "+")
|
||||||
|
preRelease := PreRelease(splitOff(&version, "-"))
|
||||||
|
dotParts := strings.SplitN(version, ".", 3)
|
||||||
|
|
||||||
|
if len(dotParts) != 3 {
|
||||||
|
return fmt.Errorf("%s is not in dotted-tri format", version)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateIdentifier(string(preRelease)); err != nil {
|
||||||
|
return fmt.Errorf("failed to validate pre-release: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateIdentifier(metadata); err != nil {
|
||||||
|
return fmt.Errorf("failed to validate metadata: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed := make([]int64, 3, 3)
|
||||||
|
|
||||||
|
for i, v := range dotParts[:3] {
|
||||||
|
val, err := strconv.ParseInt(v, 10, 64)
|
||||||
|
parsed[i] = val
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v.Metadata = metadata
|
||||||
|
v.PreRelease = preRelease
|
||||||
|
v.Major = parsed[0]
|
||||||
|
v.Minor = parsed[1]
|
||||||
|
v.Patch = parsed[2]
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Version) String() string {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
|
|
||||||
base := fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
|
fmt.Fprintf(&buffer, "%d.%d.%d", v.Major, v.Minor, v.Patch)
|
||||||
buffer.WriteString(base)
|
|
||||||
|
|
||||||
if v.PreRelease != "" {
|
if v.PreRelease != "" {
|
||||||
buffer.WriteString(fmt.Sprintf("-%s", v.PreRelease))
|
fmt.Fprintf(&buffer, "-%s", v.PreRelease)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.Metadata != "" {
|
if v.Metadata != "" {
|
||||||
buffer.WriteString(fmt.Sprintf("+%s", v.Metadata))
|
fmt.Fprintf(&buffer, "+%s", v.Metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Version) LessThan(versionB Version) bool {
|
func (v *Version) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
versionA := *v
|
var data string
|
||||||
cmp := recursiveCompare(versionA.Slice(), versionB.Slice())
|
if err := unmarshal(&data); err != nil {
|
||||||
|
return err
|
||||||
if cmp == 0 {
|
}
|
||||||
cmp = preReleaseCompare(versionA, versionB)
|
return v.Set(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmp == -1 {
|
func (v Version) MarshalJSON() ([]byte, error) {
|
||||||
return true
|
return []byte(`"` + v.String() + `"`), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
func (v *Version) UnmarshalJSON(data []byte) error {
|
||||||
|
l := len(data)
|
||||||
|
if l == 0 || string(data) == `""` {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if l < 2 || data[0] != '"' || data[l-1] != '"' {
|
||||||
|
return errors.New("invalid semver string")
|
||||||
|
}
|
||||||
|
return v.Set(string(data[1 : l-1]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Slice converts the comparable parts of the semver into a slice of strings */
|
// Compare tests if v is less than, equal to, or greater than versionB,
|
||||||
func (v *Version) Slice() []int64 {
|
// returning -1, 0, or +1 respectively.
|
||||||
|
func (v Version) Compare(versionB Version) int {
|
||||||
|
if cmp := recursiveCompare(v.Slice(), versionB.Slice()); cmp != 0 {
|
||||||
|
return cmp
|
||||||
|
}
|
||||||
|
return preReleaseCompare(v, versionB)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal tests if v is equal to versionB.
|
||||||
|
func (v Version) Equal(versionB Version) bool {
|
||||||
|
return v.Compare(versionB) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessThan tests if v is less than versionB.
|
||||||
|
func (v Version) LessThan(versionB Version) bool {
|
||||||
|
return v.Compare(versionB) < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slice converts the comparable parts of the semver into a slice of integers.
|
||||||
|
func (v Version) Slice() []int64 {
|
||||||
return []int64{v.Major, v.Minor, v.Patch}
|
return []int64{v.Major, v.Minor, v.Patch}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PreRelease) Slice() []string {
|
func (p PreRelease) Slice() []string {
|
||||||
preRelease := string(*p)
|
preRelease := string(p)
|
||||||
return strings.Split(preRelease, ".")
|
return strings.Split(preRelease, ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +183,7 @@ func preReleaseCompare(versionA Version, versionB Version) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a prelease, check and compare each part.
|
// If there is a prerelease, check and compare each part.
|
||||||
return recursivePreReleaseCompare(a.Slice(), b.Slice())
|
return recursivePreReleaseCompare(a.Slice(), b.Slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,9 +205,12 @@ func recursiveCompare(versionA []int64, versionB []int64) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func recursivePreReleaseCompare(versionA []string, versionB []string) int {
|
func recursivePreReleaseCompare(versionA []string, versionB []string) int {
|
||||||
// Handle slice length disparity.
|
// A larger set of pre-release fields has a higher precedence than a smaller set,
|
||||||
|
// if all of the preceding identifiers are equal.
|
||||||
if len(versionA) == 0 {
|
if len(versionA) == 0 {
|
||||||
// Nothing to compare too, so we return 0
|
if len(versionB) > 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
return 0
|
return 0
|
||||||
} else if len(versionB) == 0 {
|
} else if len(versionB) == 0 {
|
||||||
// We're longer than versionB so return 1.
|
// We're longer than versionB so return 1.
|
||||||
|
@ -153,7 +220,8 @@ func recursivePreReleaseCompare(versionA []string, versionB []string) int {
|
||||||
a := versionA[0]
|
a := versionA[0]
|
||||||
b := versionB[0]
|
b := versionB[0]
|
||||||
|
|
||||||
aInt := false; bInt := false
|
aInt := false
|
||||||
|
bInt := false
|
||||||
|
|
||||||
aI, err := strconv.Atoi(versionA[0])
|
aI, err := strconv.Atoi(versionA[0])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -165,6 +233,13 @@ func recursivePreReleaseCompare(versionA []string, versionB []string) int {
|
||||||
bInt = true
|
bInt = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Numeric identifiers always have lower precedence than non-numeric identifiers.
|
||||||
|
if aInt && !bInt {
|
||||||
|
return -1
|
||||||
|
} else if !aInt && bInt {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
// Handle Integer Comparison
|
// Handle Integer Comparison
|
||||||
if aInt && bInt {
|
if aInt && bInt {
|
||||||
if aI > bI {
|
if aI > bI {
|
||||||
|
@ -207,3 +282,15 @@ func (v *Version) BumpPatch() {
|
||||||
v.PreRelease = PreRelease("")
|
v.PreRelease = PreRelease("")
|
||||||
v.Metadata = ""
|
v.Metadata = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateIdentifier makes sure the provided identifier satisfies semver spec
|
||||||
|
func validateIdentifier(id string) error {
|
||||||
|
if id != "" && !reIdentifier.MatchString(id) {
|
||||||
|
return fmt.Errorf("%s is not a valid semver identifier", id)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// reIdentifier is a regular expression used to check that pre-release and metadata
|
||||||
|
// identifiers satisfy the spec requirements
|
||||||
|
var reIdentifier = regexp.MustCompile(`^[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*$`)
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
|
// Copyright 2013-2015 CoreOS, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
package semver
|
package semver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
CoreOS Project
|
||||||
|
Copyright 2018 CoreOS, Inc
|
||||||
|
|
||||||
|
This product includes software developed at CoreOS, Inc.
|
||||||
|
(http://www.coreos.com/).
|
|
@ -1,4 +1,5 @@
|
||||||
// Copyright 2014 Docker, Inc.
|
// Copyright 2014 Docker, Inc.
|
||||||
|
// Copyright 2015-2018 CoreOS, Inc.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -13,7 +14,11 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
// Code forked from Docker project
|
// Package daemon provides a Go implementation of the sd_notify protocol.
|
||||||
|
// It can be used to inform systemd of service start-up completion, watchdog
|
||||||
|
// events, and other status changes.
|
||||||
|
//
|
||||||
|
// https://www.freedesktop.org/software/systemd/man/sd_notify.html#Description
|
||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -21,6 +26,25 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SdNotifyReady tells the service manager that service startup is finished
|
||||||
|
// or the service finished loading its configuration.
|
||||||
|
SdNotifyReady = "READY=1"
|
||||||
|
|
||||||
|
// SdNotifyStopping tells the service manager that the service is beginning
|
||||||
|
// its shutdown.
|
||||||
|
SdNotifyStopping = "STOPPING=1"
|
||||||
|
|
||||||
|
// SdNotifyReloading tells the service manager that this service is
|
||||||
|
// reloading its configuration. Note that you must call SdNotifyReady when
|
||||||
|
// it completed reloading.
|
||||||
|
SdNotifyReloading = "RELOADING=1"
|
||||||
|
|
||||||
|
// SdNotifyWatchdog tells the service manager to update the watchdog
|
||||||
|
// timestamp for the service.
|
||||||
|
SdNotifyWatchdog = "WATCHDOG=1"
|
||||||
|
)
|
||||||
|
|
||||||
// SdNotify sends a message to the init daemon. It is common to ignore the error.
|
// SdNotify sends a message to the init daemon. It is common to ignore the error.
|
||||||
// If `unsetEnvironment` is true, the environment variable `NOTIFY_SOCKET`
|
// If `unsetEnvironment` is true, the environment variable `NOTIFY_SOCKET`
|
||||||
// will be unconditionally unset.
|
// will be unconditionally unset.
|
||||||
|
@ -29,7 +53,7 @@ import (
|
||||||
// (false, nil) - notification not supported (i.e. NOTIFY_SOCKET is unset)
|
// (false, nil) - notification not supported (i.e. NOTIFY_SOCKET is unset)
|
||||||
// (false, err) - notification supported, but failure happened (e.g. error connecting to NOTIFY_SOCKET or while sending data)
|
// (false, err) - notification supported, but failure happened (e.g. error connecting to NOTIFY_SOCKET or while sending data)
|
||||||
// (true, nil) - notification supported, data has been sent
|
// (true, nil) - notification supported, data has been sent
|
||||||
func SdNotify(unsetEnvironment bool, state string) (sent bool, err error) {
|
func SdNotify(unsetEnvironment bool, state string) (bool, error) {
|
||||||
socketAddr := &net.UnixAddr{
|
socketAddr := &net.UnixAddr{
|
||||||
Name: os.Getenv("NOTIFY_SOCKET"),
|
Name: os.Getenv("NOTIFY_SOCKET"),
|
||||||
Net: "unixgram",
|
Net: "unixgram",
|
||||||
|
@ -41,11 +65,10 @@ func SdNotify(unsetEnvironment bool, state string) (sent bool, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if unsetEnvironment {
|
if unsetEnvironment {
|
||||||
err = os.Unsetenv("NOTIFY_SOCKET")
|
if err := os.Unsetenv("NOTIFY_SOCKET"); err != nil {
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr)
|
conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr)
|
||||||
// Error connecting to NOTIFY_SOCKET
|
// Error connecting to NOTIFY_SOCKET
|
||||||
|
@ -54,9 +77,7 @@ func SdNotify(unsetEnvironment bool, state string) (sent bool, err error) {
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
_, err = conn.Write([]byte(state))
|
if _, err = conn.Write([]byte(state)); err != nil {
|
||||||
// Error sending the message
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
|
|
|
@ -21,10 +21,11 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SdWatchdogEnabled return watchdog information for a service.
|
// SdWatchdogEnabled returns watchdog information for a service.
|
||||||
// Process should send daemon.SdNotify("WATCHDOG=1") every time / 2.
|
// Processes should call daemon.SdNotify(false, daemon.SdNotifyWatchdog) every
|
||||||
// If `unsetEnvironment` is true, the environment variables `WATCHDOG_USEC`
|
// time / 2.
|
||||||
// and `WATCHDOG_PID` will be unconditionally unset.
|
// If `unsetEnvironment` is true, the environment variables `WATCHDOG_USEC` and
|
||||||
|
// `WATCHDOG_PID` will be unconditionally unset.
|
||||||
//
|
//
|
||||||
// It returns one of the following:
|
// It returns one of the following:
|
||||||
// (0, nil) - watchdog isn't enabled or we aren't the watched PID.
|
// (0, nil) - watchdog isn't enabled or we aren't the watched PID.
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package dbus
|
package dbus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -60,6 +61,27 @@ func PathBusEscape(path string) string {
|
||||||
return string(n)
|
return string(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pathBusUnescape is the inverse of PathBusEscape.
|
||||||
|
func pathBusUnescape(path string) string {
|
||||||
|
if path == "_" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
n := []byte{}
|
||||||
|
for i := 0; i < len(path); i++ {
|
||||||
|
c := path[i]
|
||||||
|
if c == '_' && i+2 < len(path) {
|
||||||
|
res, err := hex.DecodeString(path[i+1 : i+3])
|
||||||
|
if err == nil {
|
||||||
|
n = append(n, res...)
|
||||||
|
}
|
||||||
|
i += 2
|
||||||
|
} else {
|
||||||
|
n = append(n, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(n)
|
||||||
|
}
|
||||||
|
|
||||||
// Conn is a connection to systemd's dbus endpoint.
|
// Conn is a connection to systemd's dbus endpoint.
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
// sysconn/sysobj are only used to call dbus methods
|
// sysconn/sysobj are only used to call dbus methods
|
||||||
|
@ -74,13 +96,18 @@ type Conn struct {
|
||||||
jobs map[dbus.ObjectPath]chan<- string
|
jobs map[dbus.ObjectPath]chan<- string
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
subscriber struct {
|
subStateSubscriber struct {
|
||||||
updateCh chan<- *SubStateUpdate
|
updateCh chan<- *SubStateUpdate
|
||||||
errCh chan<- error
|
errCh chan<- error
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
ignore map[dbus.ObjectPath]int64
|
ignore map[dbus.ObjectPath]int64
|
||||||
cleanIgnore int64
|
cleanIgnore int64
|
||||||
}
|
}
|
||||||
|
propertiesSubscriber struct {
|
||||||
|
updateCh chan<- *PropertiesUpdate
|
||||||
|
errCh chan<- error
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New establishes a connection to any available bus and authenticates.
|
// New establishes a connection to any available bus and authenticates.
|
||||||
|
@ -152,7 +179,7 @@ func NewConnection(dialBus func() (*dbus.Conn, error)) (*Conn, error) {
|
||||||
sigobj: systemdObject(sigconn),
|
sigobj: systemdObject(sigconn),
|
||||||
}
|
}
|
||||||
|
|
||||||
c.subscriber.ignore = make(map[dbus.ObjectPath]int64)
|
c.subStateSubscriber.ignore = make(map[dbus.ObjectPath]int64)
|
||||||
c.jobListener.jobs = make(map[dbus.ObjectPath]chan<- string)
|
c.jobListener.jobs = make(map[dbus.ObjectPath]chan<- string)
|
||||||
|
|
||||||
// Setup the listeners on jobs so that we can get completions
|
// Setup the listeners on jobs so that we can get completions
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015 CoreOS, Inc.
|
// Copyright 2015, 2018 CoreOS, Inc.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -16,6 +16,7 @@ package dbus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
@ -148,14 +149,27 @@ func (c *Conn) ResetFailedUnit(name string) error {
|
||||||
return c.sysobj.Call("org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store()
|
return c.sysobj.Call("org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store()
|
||||||
}
|
}
|
||||||
|
|
||||||
// getProperties takes the unit name and returns all of its dbus object properties, for the given dbus interface
|
// SystemState returns the systemd state. Equivalent to `systemctl is-system-running`.
|
||||||
func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]interface{}, error) {
|
func (c *Conn) SystemState() (*Property, error) {
|
||||||
|
var err error
|
||||||
|
var prop dbus.Variant
|
||||||
|
|
||||||
|
obj := c.sysconn.Object("org.freedesktop.systemd1", "/org/freedesktop/systemd1")
|
||||||
|
err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.systemd1.Manager", "SystemState").Store(&prop)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Property{Name: "SystemState", Value: prop}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getProperties takes the unit path and returns all of its dbus object properties, for the given dbus interface
|
||||||
|
func (c *Conn) getProperties(path dbus.ObjectPath, dbusInterface string) (map[string]interface{}, error) {
|
||||||
var err error
|
var err error
|
||||||
var props map[string]dbus.Variant
|
var props map[string]dbus.Variant
|
||||||
|
|
||||||
path := unitPath(unit)
|
|
||||||
if !path.IsValid() {
|
if !path.IsValid() {
|
||||||
return nil, errors.New("invalid unit name: " + unit)
|
return nil, fmt.Errorf("invalid unit name: %v", path)
|
||||||
}
|
}
|
||||||
|
|
||||||
obj := c.sysconn.Object("org.freedesktop.systemd1", path)
|
obj := c.sysconn.Object("org.freedesktop.systemd1", path)
|
||||||
|
@ -172,9 +186,15 @@ func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]inte
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUnitProperties takes the unit name and returns all of its dbus object properties.
|
// GetUnitProperties takes the (unescaped) unit name and returns all of its dbus object properties.
|
||||||
func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
|
func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
|
||||||
return c.getProperties(unit, "org.freedesktop.systemd1.Unit")
|
path := unitPath(unit)
|
||||||
|
return c.getProperties(path, "org.freedesktop.systemd1.Unit")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUnitProperties takes the (escaped) unit path and returns all of its dbus object properties.
|
||||||
|
func (c *Conn) GetUnitPathProperties(path dbus.ObjectPath) (map[string]interface{}, error) {
|
||||||
|
return c.getProperties(path, "org.freedesktop.systemd1.Unit")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) getProperty(unit string, dbusInterface string, propertyName string) (*Property, error) {
|
func (c *Conn) getProperty(unit string, dbusInterface string, propertyName string) (*Property, error) {
|
||||||
|
@ -208,7 +228,8 @@ func (c *Conn) GetServiceProperty(service string, propertyName string) (*Propert
|
||||||
// Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope
|
// Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope
|
||||||
// return "dbus.Error: Unknown interface" if the unitType is not the correct type of the unit
|
// return "dbus.Error: Unknown interface" if the unitType is not the correct type of the unit
|
||||||
func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) {
|
func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) {
|
||||||
return c.getProperties(unit, "org.freedesktop.systemd1."+unitType)
|
path := unitPath(unit)
|
||||||
|
return c.getProperties(path, "org.freedesktop.systemd1."+unitType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUnitProperties() may be used to modify certain unit properties at runtime.
|
// SetUnitProperties() may be used to modify certain unit properties at runtime.
|
||||||
|
@ -292,6 +313,7 @@ func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitSt
|
||||||
// names and returns an UnitStatus array. Comparing to ListUnitsByPatterns
|
// names and returns an UnitStatus array. Comparing to ListUnitsByPatterns
|
||||||
// method, this method returns statuses even for inactive or non-existing
|
// method, this method returns statuses even for inactive or non-existing
|
||||||
// units. Input array should contain exact unit names, but not patterns.
|
// units. Input array should contain exact unit names, but not patterns.
|
||||||
|
// Note: Requires systemd v230 or higher
|
||||||
func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) {
|
func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) {
|
||||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store)
|
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store)
|
||||||
}
|
}
|
||||||
|
@ -563,3 +585,8 @@ func (c *Conn) Reload() error {
|
||||||
func unitPath(name string) dbus.ObjectPath {
|
func unitPath(name string) dbus.ObjectPath {
|
||||||
return dbus.ObjectPath("/org/freedesktop/systemd1/unit/" + PathBusEscape(name))
|
return dbus.ObjectPath("/org/freedesktop/systemd1/unit/" + PathBusEscape(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unitName returns the unescaped base element of the supplied escaped path
|
||||||
|
func unitName(dpath dbus.ObjectPath) string {
|
||||||
|
return pathBusUnescape(path.Base(string(dpath)))
|
||||||
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ func (s *set) Length() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *set) Values() (values []string) {
|
func (s *set) Values() (values []string) {
|
||||||
for val, _ := range s.data {
|
for val := range s.data {
|
||||||
values = append(values, val)
|
values = append(values, val)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
@ -16,6 +16,7 @@ package dbus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/godbus/dbus"
|
"github.com/godbus/dbus"
|
||||||
|
@ -36,22 +37,12 @@ func (c *Conn) Subscribe() error {
|
||||||
c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
|
c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
|
||||||
"type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'")
|
"type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'")
|
||||||
|
|
||||||
err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store()
|
return c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsubscribe this connection from systemd dbus events.
|
// Unsubscribe this connection from systemd dbus events.
|
||||||
func (c *Conn) Unsubscribe() error {
|
func (c *Conn) Unsubscribe() error {
|
||||||
err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store()
|
return c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) dispatch() {
|
func (c *Conn) dispatch() {
|
||||||
|
@ -70,7 +61,8 @@ func (c *Conn) dispatch() {
|
||||||
c.jobComplete(signal)
|
c.jobComplete(signal)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.subscriber.updateCh == nil {
|
if c.subStateSubscriber.updateCh == nil &&
|
||||||
|
c.propertiesSubscriber.updateCh == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +76,12 @@ func (c *Conn) dispatch() {
|
||||||
case "org.freedesktop.DBus.Properties.PropertiesChanged":
|
case "org.freedesktop.DBus.Properties.PropertiesChanged":
|
||||||
if signal.Body[0].(string) == "org.freedesktop.systemd1.Unit" {
|
if signal.Body[0].(string) == "org.freedesktop.systemd1.Unit" {
|
||||||
unitPath = signal.Path
|
unitPath = signal.Path
|
||||||
|
|
||||||
|
if len(signal.Body) >= 2 {
|
||||||
|
if changed, ok := signal.Body[1].(map[string]dbus.Variant); ok {
|
||||||
|
c.sendPropertiesUpdate(unitPath, changed)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,42 +167,80 @@ type SubStateUpdate struct {
|
||||||
// is full, it attempts to write an error to errCh; if errCh is full, the error
|
// is full, it attempts to write an error to errCh; if errCh is full, the error
|
||||||
// passes silently.
|
// passes silently.
|
||||||
func (c *Conn) SetSubStateSubscriber(updateCh chan<- *SubStateUpdate, errCh chan<- error) {
|
func (c *Conn) SetSubStateSubscriber(updateCh chan<- *SubStateUpdate, errCh chan<- error) {
|
||||||
c.subscriber.Lock()
|
if c == nil {
|
||||||
defer c.subscriber.Unlock()
|
msg := "nil receiver"
|
||||||
c.subscriber.updateCh = updateCh
|
select {
|
||||||
c.subscriber.errCh = errCh
|
case errCh <- errors.New(msg):
|
||||||
|
default:
|
||||||
|
log.Printf("full error channel while reporting: %s\n", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) sendSubStateUpdate(path dbus.ObjectPath) {
|
|
||||||
c.subscriber.Lock()
|
|
||||||
defer c.subscriber.Unlock()
|
|
||||||
|
|
||||||
if c.shouldIgnore(path) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := c.GetUnitProperties(string(path))
|
c.subStateSubscriber.Lock()
|
||||||
if err != nil {
|
defer c.subStateSubscriber.Unlock()
|
||||||
select {
|
c.subStateSubscriber.updateCh = updateCh
|
||||||
case c.subscriber.errCh <- err:
|
c.subStateSubscriber.errCh = errCh
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
name := info["Id"].(string)
|
func (c *Conn) sendSubStateUpdate(unitPath dbus.ObjectPath) {
|
||||||
substate := info["SubState"].(string)
|
c.subStateSubscriber.Lock()
|
||||||
|
defer c.subStateSubscriber.Unlock()
|
||||||
|
|
||||||
|
if c.subStateSubscriber.updateCh == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isIgnored := c.shouldIgnore(unitPath)
|
||||||
|
defer c.cleanIgnore()
|
||||||
|
if isIgnored {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := c.GetUnitPathProperties(unitPath)
|
||||||
|
if err != nil {
|
||||||
|
select {
|
||||||
|
case c.subStateSubscriber.errCh <- err:
|
||||||
|
default:
|
||||||
|
log.Printf("full error channel while reporting: %s\n", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer c.updateIgnore(unitPath, info)
|
||||||
|
|
||||||
|
name, ok := info["Id"].(string)
|
||||||
|
if !ok {
|
||||||
|
msg := "failed to cast info.Id"
|
||||||
|
select {
|
||||||
|
case c.subStateSubscriber.errCh <- errors.New(msg):
|
||||||
|
default:
|
||||||
|
log.Printf("full error channel while reporting: %s\n", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
substate, ok := info["SubState"].(string)
|
||||||
|
if !ok {
|
||||||
|
msg := "failed to cast info.SubState"
|
||||||
|
select {
|
||||||
|
case c.subStateSubscriber.errCh <- errors.New(msg):
|
||||||
|
default:
|
||||||
|
log.Printf("full error channel while reporting: %s\n", msg)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
update := &SubStateUpdate{name, substate}
|
update := &SubStateUpdate{name, substate}
|
||||||
select {
|
select {
|
||||||
case c.subscriber.updateCh <- update:
|
case c.subStateSubscriber.updateCh <- update:
|
||||||
default:
|
default:
|
||||||
|
msg := "update channel is full"
|
||||||
select {
|
select {
|
||||||
case c.subscriber.errCh <- errors.New("update channel full!"):
|
case c.subStateSubscriber.errCh <- errors.New(msg):
|
||||||
default:
|
default:
|
||||||
|
log.Printf("full error channel while reporting: %s\n", msg)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.updateIgnore(path, info)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The ignore functions work around a wart in the systemd dbus interface.
|
// The ignore functions work around a wart in the systemd dbus interface.
|
||||||
|
@ -222,29 +258,76 @@ func (c *Conn) sendSubStateUpdate(path dbus.ObjectPath) {
|
||||||
// the properties).
|
// the properties).
|
||||||
|
|
||||||
func (c *Conn) shouldIgnore(path dbus.ObjectPath) bool {
|
func (c *Conn) shouldIgnore(path dbus.ObjectPath) bool {
|
||||||
t, ok := c.subscriber.ignore[path]
|
t, ok := c.subStateSubscriber.ignore[path]
|
||||||
return ok && t >= time.Now().UnixNano()
|
return ok && t >= time.Now().UnixNano()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) updateIgnore(path dbus.ObjectPath, info map[string]interface{}) {
|
func (c *Conn) updateIgnore(path dbus.ObjectPath, info map[string]interface{}) {
|
||||||
c.cleanIgnore()
|
loadState, ok := info["LoadState"].(string)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// unit is unloaded - it will trigger bad systemd dbus behavior
|
// unit is unloaded - it will trigger bad systemd dbus behavior
|
||||||
if info["LoadState"].(string) == "not-found" {
|
if loadState == "not-found" {
|
||||||
c.subscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval
|
c.subStateSubscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// without this, ignore would grow unboundedly over time
|
// without this, ignore would grow unboundedly over time
|
||||||
func (c *Conn) cleanIgnore() {
|
func (c *Conn) cleanIgnore() {
|
||||||
now := time.Now().UnixNano()
|
now := time.Now().UnixNano()
|
||||||
if c.subscriber.cleanIgnore < now {
|
if c.subStateSubscriber.cleanIgnore < now {
|
||||||
c.subscriber.cleanIgnore = now + cleanIgnoreInterval
|
c.subStateSubscriber.cleanIgnore = now + cleanIgnoreInterval
|
||||||
|
|
||||||
for p, t := range c.subscriber.ignore {
|
for p, t := range c.subStateSubscriber.ignore {
|
||||||
if t < now {
|
if t < now {
|
||||||
delete(c.subscriber.ignore, p)
|
delete(c.subStateSubscriber.ignore, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PropertiesUpdate holds a map of a unit's changed properties
|
||||||
|
type PropertiesUpdate struct {
|
||||||
|
UnitName string
|
||||||
|
Changed map[string]dbus.Variant
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPropertiesSubscriber writes to updateCh when any unit's properties
|
||||||
|
// change. Every property change reported by systemd will be sent; that is, no
|
||||||
|
// transitions will be "missed" (as they might be with SetSubStateSubscriber).
|
||||||
|
// However, state changes will only be written to the channel with non-blocking
|
||||||
|
// writes. If updateCh is full, it attempts to write an error to errCh; if
|
||||||
|
// errCh is full, the error passes silently.
|
||||||
|
func (c *Conn) SetPropertiesSubscriber(updateCh chan<- *PropertiesUpdate, errCh chan<- error) {
|
||||||
|
c.propertiesSubscriber.Lock()
|
||||||
|
defer c.propertiesSubscriber.Unlock()
|
||||||
|
c.propertiesSubscriber.updateCh = updateCh
|
||||||
|
c.propertiesSubscriber.errCh = errCh
|
||||||
|
}
|
||||||
|
|
||||||
|
// we don't need to worry about shouldIgnore() here because
|
||||||
|
// sendPropertiesUpdate doesn't call GetProperties()
|
||||||
|
func (c *Conn) sendPropertiesUpdate(unitPath dbus.ObjectPath, changedProps map[string]dbus.Variant) {
|
||||||
|
c.propertiesSubscriber.Lock()
|
||||||
|
defer c.propertiesSubscriber.Unlock()
|
||||||
|
|
||||||
|
if c.propertiesSubscriber.updateCh == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
update := &PropertiesUpdate{unitName(unitPath), changedProps}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case c.propertiesSubscriber.updateCh <- update:
|
||||||
|
default:
|
||||||
|
msg := "update channel is full"
|
||||||
|
select {
|
||||||
|
case c.propertiesSubscriber.errCh <- errors.New(msg):
|
||||||
|
default:
|
||||||
|
log.Printf("full error channel while reporting: %s\n", msg)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -103,7 +103,10 @@ func Send(message string, priority Priority, vars map[string]string) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
return journalError("can't send file through non-Unix connection")
|
return journalError("can't send file through non-Unix connection")
|
||||||
}
|
}
|
||||||
unixConn.WriteMsgUnix([]byte{}, rights, nil)
|
_, _, err = unixConn.WriteMsgUnix([]byte{}, rights, nil)
|
||||||
|
if err != nil {
|
||||||
|
return journalError(err.Error())
|
||||||
|
}
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return journalError(err.Error())
|
return journalError(err.Error())
|
||||||
}
|
}
|
||||||
|
@ -165,7 +168,7 @@ func tempFd() (*os.File, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
syscall.Unlink(file.Name())
|
err = syscall.Unlink(file.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,11 +122,12 @@ func runningFromSystemService() (ret bool, err error) {
|
||||||
errno := C.my_sd_pid_get_owner_uid(sd_pid_get_owner_uid, 0, &uid)
|
errno := C.my_sd_pid_get_owner_uid(sd_pid_get_owner_uid, 0, &uid)
|
||||||
serrno := syscall.Errno(-errno)
|
serrno := syscall.Errno(-errno)
|
||||||
// when we're running from a unit file, sd_pid_get_owner_uid returns
|
// when we're running from a unit file, sd_pid_get_owner_uid returns
|
||||||
// ENOENT (systemd <220) or ENXIO (systemd >=220)
|
// ENOENT (systemd <220), ENXIO (systemd 220-223), or ENODATA
|
||||||
|
// (systemd >=234)
|
||||||
switch {
|
switch {
|
||||||
case errno >= 0:
|
case errno >= 0:
|
||||||
ret = false
|
ret = false
|
||||||
case serrno == syscall.ENOENT, serrno == syscall.ENXIO:
|
case serrno == syscall.ENOENT, serrno == syscall.ENXIO, serrno == syscall.ENODATA:
|
||||||
// Since the implementation of sessions in systemd relies on
|
// Since the implementation of sessions in systemd relies on
|
||||||
// the `pam_systemd` module, using the sd_pid_get_owner_uid
|
// the `pam_systemd` module, using the sd_pid_get_owner_uid
|
||||||
// heuristic alone can result in false positives if that module
|
// heuristic alone can result in false positives if that module
|
||||||
|
|
|
@ -21,7 +21,7 @@ Still the job of `main` to expose these configurations. `main` may delegate this
|
||||||
|
|
||||||
Splitting streams is probably not the job of your program, but rather, your log aggregation framework. If you must split output streams, again, `main` configures this and you can write a very simple two-output struct that satisfies io.Writer.
|
Splitting streams is probably not the job of your program, but rather, your log aggregation framework. If you must split output streams, again, `main` configures this and you can write a very simple two-output struct that satisfies io.Writer.
|
||||||
|
|
||||||
Fancy colorful formatting and JSON output are beyond the scope of a basic logging framework -- they're application/log-collector dependant. These are, at best, provided as options, but more likely, provided by your application.
|
Fancy colorful formatting and JSON output are beyond the scope of a basic logging framework -- they're application/log-collector dependent. These are, at best, provided as options, but more likely, provided by your application.
|
||||||
|
|
||||||
##### Log objects are an interface
|
##### Log objects are an interface
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,11 @@ func (l *LogLevel) Set(s string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns an empty string, only here to fulfill the pflag.Value interface.
|
||||||
|
func (l *LogLevel) Type() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// ParseLevel translates some potential loglevel strings into their corresponding levels.
|
// ParseLevel translates some potential loglevel strings into their corresponding levels.
|
||||||
func ParseLevel(s string) (LogLevel, error) {
|
func ParseLevel(s string) (LogLevel, error) {
|
||||||
switch s {
|
switch s {
|
||||||
|
|
|
@ -37,6 +37,14 @@ func (p *PackageLogger) internalLog(depth int, inLevel LogLevel, entries ...inte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLevel allows users to change the current logging level.
|
||||||
|
func (p *PackageLogger) SetLevel(l LogLevel) {
|
||||||
|
logger.Lock()
|
||||||
|
defer logger.Unlock()
|
||||||
|
p.level = l
|
||||||
|
}
|
||||||
|
|
||||||
|
// LevelAt checks if the given log level will be outputted under current setting.
|
||||||
func (p *PackageLogger) LevelAt(l LogLevel) bool {
|
func (p *PackageLogger) LevelAt(l LogLevel) bool {
|
||||||
logger.Lock()
|
logger.Lock()
|
||||||
defer logger.Unlock()
|
defer logger.Unlock()
|
||||||
|
@ -81,6 +89,12 @@ func (p *PackageLogger) Panic(args ...interface{}) {
|
||||||
panic(s)
|
panic(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PackageLogger) Panicln(args ...interface{}) {
|
||||||
|
s := fmt.Sprintln(args...)
|
||||||
|
p.internalLog(calldepth, CRITICAL, s)
|
||||||
|
panic(s)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *PackageLogger) Fatalf(format string, args ...interface{}) {
|
func (p *PackageLogger) Fatalf(format string, args ...interface{}) {
|
||||||
p.Logf(CRITICAL, format, args...)
|
p.Logf(CRITICAL, format, args...)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### Go template
|
||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
||||||
|
### Windows template
|
||||||
|
# Windows image file caches
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
### Kate template
|
||||||
|
# Swap Files #
|
||||||
|
.*.kate-swp
|
||||||
|
.swp.*
|
||||||
|
### SublimeText template
|
||||||
|
# cache files for sublime text
|
||||||
|
*.tmlanguage.cache
|
||||||
|
*.tmPreferences.cache
|
||||||
|
*.stTheme.cache
|
||||||
|
|
||||||
|
# workspace files are user-specific
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# project files should be checked into the repository, unless a significant
|
||||||
|
# proportion of contributors will probably not be using SublimeText
|
||||||
|
# *.sublime-project
|
||||||
|
|
||||||
|
# sftp configuration file
|
||||||
|
sftp-config.json
|
||||||
|
### Linux template
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
.idea
|
||||||
|
.idea/tasks.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
.idea/vcs.xml
|
||||||
|
.idea/jsLibraryMappings.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files:
|
||||||
|
.idea/dataSources.ids
|
||||||
|
.idea/dataSources.xml
|
||||||
|
.idea/dataSources.local.xml
|
||||||
|
.idea/sqlDataSources.xml
|
||||||
|
.idea/dynamic.xml
|
||||||
|
.idea/uiDesigner.xml
|
||||||
|
|
||||||
|
# Gradle:
|
||||||
|
.idea/gradle.xml
|
||||||
|
.idea/libraries
|
||||||
|
|
||||||
|
# Mongo Explorer plugin:
|
||||||
|
.idea/mongoSettings.xml
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
### Xcode template
|
||||||
|
# Xcode
|
||||||
|
#
|
||||||
|
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||||
|
|
||||||
|
## Build generated
|
||||||
|
build/
|
||||||
|
DerivedData/
|
||||||
|
|
||||||
|
## Various settings
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata/
|
||||||
|
|
||||||
|
## Other
|
||||||
|
*.moved-aside
|
||||||
|
*.xccheckout
|
||||||
|
*.xcscmblueprint
|
||||||
|
### Eclipse template
|
||||||
|
|
||||||
|
.metadata
|
||||||
|
bin/
|
||||||
|
tmp/
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
*.swp
|
||||||
|
*~.nib
|
||||||
|
local.properties
|
||||||
|
.settings/
|
||||||
|
.loadpath
|
||||||
|
.recommenders
|
||||||
|
|
||||||
|
# Eclipse Core
|
||||||
|
.project
|
||||||
|
|
||||||
|
# External tool builders
|
||||||
|
.externalToolBuilders/
|
||||||
|
|
||||||
|
# Locally stored "Eclipse launch configurations"
|
||||||
|
*.launch
|
||||||
|
|
||||||
|
# PyDev specific (Python IDE for Eclipse)
|
||||||
|
*.pydevproject
|
||||||
|
|
||||||
|
# CDT-specific (C/C++ Development Tooling)
|
||||||
|
.cproject
|
||||||
|
|
||||||
|
# JDT-specific (Eclipse Java Development Tools)
|
||||||
|
.classpath
|
||||||
|
|
||||||
|
# Java annotation processor (APT)
|
||||||
|
.factorypath
|
||||||
|
|
||||||
|
# PDT-specific (PHP Development Tools)
|
||||||
|
.buildpath
|
||||||
|
|
||||||
|
# sbteclipse plugin
|
||||||
|
.target
|
||||||
|
|
||||||
|
# Tern plugin
|
||||||
|
.tern-project
|
||||||
|
|
||||||
|
# TeXlipse plugin
|
||||||
|
.texlipse
|
||||||
|
|
||||||
|
# STS (Spring Tool Suite)
|
||||||
|
.springBeans
|
||||||
|
|
||||||
|
# Code Recommenders
|
||||||
|
.recommenders/
|
||||||
|
|
||||||
|
|
||||||
|
coverage.txt
|
||||||
|
|
||||||
|
#vendor
|
||||||
|
vendor/
|
|
@ -0,0 +1,22 @@
|
||||||
|
sudo: false
|
||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.8.x
|
||||||
|
env:
|
||||||
|
- DEP_VERSION="0.3.2"
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
# Download the binary to bin folder in $GOPATH
|
||||||
|
- curl -L -s https://github.com/golang/dep/releases/download/v${DEP_VERSION}/dep-linux-amd64 -o $GOPATH/bin/dep
|
||||||
|
# Make the binary executable
|
||||||
|
- chmod +x $GOPATH/bin/dep
|
||||||
|
|
||||||
|
install:
|
||||||
|
- dep ensure
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make checkdocs
|
||||||
|
- make test
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
|
@ -0,0 +1,31 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"chain.go",
|
||||||
|
"doc.go",
|
||||||
|
"wrappers.go",
|
||||||
|
],
|
||||||
|
importmap = "k8s.io/kubernetes/vendor/github.com/grpc-ecosystem/go-grpc-middleware",
|
||||||
|
importpath = "github.com/grpc-ecosystem/go-grpc-middleware",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"//vendor/golang.org/x/net/context:go_default_library",
|
||||||
|
"//vendor/google.golang.org/grpc:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Changelog
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||||
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
Types of changes:
|
||||||
|
- `Added` for new features.
|
||||||
|
- `Changed` for changes in existing functionality.
|
||||||
|
- `Deprecated` for soon-to-be removed features.
|
||||||
|
- `Removed` for now removed features.
|
||||||
|
- `Fixed` for any bug fixes.
|
||||||
|
- `Security` in case of vulnerabilities.
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
### Added
|
||||||
|
- This CHANGELOG file to keep track of changes.
|
||||||
|
|
||||||
|
## 1.0.0 - 2018-05-08
|
||||||
|
### Added
|
||||||
|
- grpc_auth
|
||||||
|
- grpc_ctxtags
|
||||||
|
- grpc_zap
|
||||||
|
- grpc_logrus
|
||||||
|
- grpc_opentracing
|
||||||
|
- grpc_retry
|
||||||
|
- grpc_validator
|
||||||
|
- grpc_recovery
|
||||||
|
|
||||||
|
[Unreleased]: https://github.com/grpc-ecosystem/go-grpc-middleware/compare/v1.0.0...HEAD
|
20
vendor/github.com/grpc-ecosystem/go-grpc-middleware/CONTRIBUTING.md
generated
vendored
Normal file
20
vendor/github.com/grpc-ecosystem/go-grpc-middleware/CONTRIBUTING.md
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# Contributing
|
||||||
|
|
||||||
|
We would love to have people submit pull requests and help make `grpc-ecosystem/go-grpc-middleware` even better 👍.
|
||||||
|
|
||||||
|
Fork, then clone the repo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone git@github.com:your-username/go-grpc-middleware.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Before checking in please run the following:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make all
|
||||||
|
```
|
||||||
|
|
||||||
|
This will `vet`, `fmt`, regenerate documentation and run all tests.
|
||||||
|
|
||||||
|
|
||||||
|
Push to your fork and open a pull request.
|
|
@ -0,0 +1,166 @@
|
||||||
|
# grpc_middleware
|
||||||
|
`import "github.com/grpc-ecosystem/go-grpc-middleware"`
|
||||||
|
|
||||||
|
* [Overview](#pkg-overview)
|
||||||
|
* [Imported Packages](#pkg-imports)
|
||||||
|
* [Index](#pkg-index)
|
||||||
|
|
||||||
|
## <a name="pkg-overview">Overview</a>
|
||||||
|
`grpc_middleware` is a collection of gRPC middleware packages: interceptors, helpers and tools.
|
||||||
|
|
||||||
|
### Middleware
|
||||||
|
gRPC is a fantastic RPC middleware, which sees a lot of adoption in the Golang world. However, the
|
||||||
|
upstream gRPC codebase is relatively bare bones.
|
||||||
|
|
||||||
|
This package, and most of its child packages provides commonly needed middleware for gRPC:
|
||||||
|
client-side interceptors for retires, server-side interceptors for input validation and auth,
|
||||||
|
functions for chaining said interceptors, metadata convenience methods and more.
|
||||||
|
|
||||||
|
### Chaining
|
||||||
|
By default, gRPC doesn't allow one to have more than one interceptor either on the client nor on
|
||||||
|
the server side. `grpc_middleware` provides convenient chaining methods
|
||||||
|
|
||||||
|
Simple way of turning a multiple interceptors into a single interceptor. Here's an example for
|
||||||
|
server chaining:
|
||||||
|
|
||||||
|
myServer := grpc.NewServer(
|
||||||
|
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)),
|
||||||
|
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary),
|
||||||
|
)
|
||||||
|
|
||||||
|
These interceptors will be executed from left to right: logging, monitoring and auth.
|
||||||
|
|
||||||
|
Here's an example for client side chaining:
|
||||||
|
|
||||||
|
clientConn, err = grpc.Dial(
|
||||||
|
address,
|
||||||
|
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(monitoringClientUnary, retryUnary)),
|
||||||
|
grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(monitoringClientStream, retryStream)),
|
||||||
|
)
|
||||||
|
client = pb_testproto.NewTestServiceClient(clientConn)
|
||||||
|
resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"})
|
||||||
|
|
||||||
|
These interceptors will be executed from left to right: monitoring and then retry logic.
|
||||||
|
|
||||||
|
The retry interceptor will call every interceptor that follows it whenever when a retry happens.
|
||||||
|
|
||||||
|
### Writing Your Own
|
||||||
|
Implementing your own interceptor is pretty trivial: there are interfaces for that. But the interesting
|
||||||
|
bit exposing common data to handlers (and other middleware), similarly to HTTP Middleware design.
|
||||||
|
For example, you may want to pass the identity of the caller from the auth interceptor all the way
|
||||||
|
to the handling function.
|
||||||
|
|
||||||
|
For example, a client side interceptor example for auth looks like:
|
||||||
|
|
||||||
|
func FakeAuthUnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||||
|
newCtx := context.WithValue(ctx, "user_id", "john@example.com")
|
||||||
|
return handler(newCtx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
Unfortunately, it's not as easy for streaming RPCs. These have the `context.Context` embedded within
|
||||||
|
the `grpc.ServerStream` object. To pass values through context, a wrapper (`WrappedServerStream`) is
|
||||||
|
needed. For example:
|
||||||
|
|
||||||
|
func FakeAuthStreamingInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||||
|
newStream := grpc_middleware.WrapServerStream(stream)
|
||||||
|
newStream.WrappedContext = context.WithValue(ctx, "user_id", "john@example.com")
|
||||||
|
return handler(srv, stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
## <a name="pkg-imports">Imported Packages</a>
|
||||||
|
|
||||||
|
- [golang.org/x/net/context](https://godoc.org/golang.org/x/net/context)
|
||||||
|
- [google.golang.org/grpc](https://godoc.org/google.golang.org/grpc)
|
||||||
|
|
||||||
|
## <a name="pkg-index">Index</a>
|
||||||
|
* [func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor](#ChainStreamClient)
|
||||||
|
* [func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor](#ChainStreamServer)
|
||||||
|
* [func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor](#ChainUnaryClient)
|
||||||
|
* [func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor](#ChainUnaryServer)
|
||||||
|
* [func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption](#WithStreamServerChain)
|
||||||
|
* [func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption](#WithUnaryServerChain)
|
||||||
|
* [type WrappedServerStream](#WrappedServerStream)
|
||||||
|
* [func WrapServerStream(stream grpc.ServerStream) \*WrappedServerStream](#WrapServerStream)
|
||||||
|
* [func (w \*WrappedServerStream) Context() context.Context](#WrappedServerStream.Context)
|
||||||
|
|
||||||
|
#### <a name="pkg-files">Package files</a>
|
||||||
|
[chain.go](./chain.go) [doc.go](./doc.go) [wrappers.go](./wrappers.go)
|
||||||
|
|
||||||
|
## <a name="ChainStreamClient">func</a> [ChainStreamClient](./chain.go#L136)
|
||||||
|
``` go
|
||||||
|
func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor
|
||||||
|
```
|
||||||
|
ChainStreamClient creates a single interceptor out of a chain of many interceptors.
|
||||||
|
|
||||||
|
Execution is done in left-to-right order, including passing of context.
|
||||||
|
For example ChainStreamClient(one, two, three) will execute one before two before three.
|
||||||
|
|
||||||
|
## <a name="ChainStreamServer">func</a> [ChainStreamServer](./chain.go#L58)
|
||||||
|
``` go
|
||||||
|
func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor
|
||||||
|
```
|
||||||
|
ChainStreamServer creates a single interceptor out of a chain of many interceptors.
|
||||||
|
|
||||||
|
Execution is done in left-to-right order, including passing of context.
|
||||||
|
For example ChainUnaryServer(one, two, three) will execute one before two before three.
|
||||||
|
If you want to pass context between interceptors, use WrapServerStream.
|
||||||
|
|
||||||
|
## <a name="ChainUnaryClient">func</a> [ChainUnaryClient](./chain.go#L97)
|
||||||
|
``` go
|
||||||
|
func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor
|
||||||
|
```
|
||||||
|
ChainUnaryClient creates a single interceptor out of a chain of many interceptors.
|
||||||
|
|
||||||
|
Execution is done in left-to-right order, including passing of context.
|
||||||
|
For example ChainUnaryClient(one, two, three) will execute one before two before three.
|
||||||
|
|
||||||
|
## <a name="ChainUnaryServer">func</a> [ChainUnaryServer](./chain.go#L18)
|
||||||
|
``` go
|
||||||
|
func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor
|
||||||
|
```
|
||||||
|
ChainUnaryServer creates a single interceptor out of a chain of many interceptors.
|
||||||
|
|
||||||
|
Execution is done in left-to-right order, including passing of context.
|
||||||
|
For example ChainUnaryServer(one, two, three) will execute one before two before three, and three
|
||||||
|
will see context changes of one and two.
|
||||||
|
|
||||||
|
## <a name="WithStreamServerChain">func</a> [WithStreamServerChain](./chain.go#L181)
|
||||||
|
``` go
|
||||||
|
func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption
|
||||||
|
```
|
||||||
|
WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors.
|
||||||
|
Basically syntactic sugar.
|
||||||
|
|
||||||
|
## <a name="WithUnaryServerChain">func</a> [WithUnaryServerChain](./chain.go#L175)
|
||||||
|
``` go
|
||||||
|
func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption
|
||||||
|
```
|
||||||
|
Chain creates a single interceptor out of a chain of many interceptors.
|
||||||
|
|
||||||
|
WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors.
|
||||||
|
Basically syntactic sugar.
|
||||||
|
|
||||||
|
## <a name="WrappedServerStream">type</a> [WrappedServerStream](./wrappers.go#L12-L16)
|
||||||
|
``` go
|
||||||
|
type WrappedServerStream struct {
|
||||||
|
grpc.ServerStream
|
||||||
|
// WrappedContext is the wrapper's own Context. You can assign it.
|
||||||
|
WrappedContext context.Context
|
||||||
|
}
|
||||||
|
```
|
||||||
|
WrappedServerStream is a thin wrapper around grpc.ServerStream that allows modifying context.
|
||||||
|
|
||||||
|
### <a name="WrapServerStream">func</a> [WrapServerStream](./wrappers.go#L24)
|
||||||
|
``` go
|
||||||
|
func WrapServerStream(stream grpc.ServerStream) *WrappedServerStream
|
||||||
|
```
|
||||||
|
WrapServerStream returns a ServerStream that has the ability to overwrite context.
|
||||||
|
|
||||||
|
### <a name="WrappedServerStream.Context">func</a> (\*WrappedServerStream) [Context](./wrappers.go#L19)
|
||||||
|
``` go
|
||||||
|
func (w *WrappedServerStream) Context() context.Context
|
||||||
|
```
|
||||||
|
Context returns the wrapper's WrappedContext, overwriting the nested grpc.ServerStream.Context()
|
||||||
|
|
||||||
|
- - -
|
||||||
|
Generated by [godoc2ghmd](https://github.com/GandalfUK/godoc2ghmd)
|
|
@ -0,0 +1,123 @@
|
||||||
|
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||||
|
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "cloud.google.com/go"
|
||||||
|
packages = ["compute/metadata"]
|
||||||
|
revision = "2d3a6656c17a60b0815b7e06ab0be04eacb6e613"
|
||||||
|
version = "v0.16.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/davecgh/go-spew"
|
||||||
|
packages = ["spew"]
|
||||||
|
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||||
|
version = "v1.1.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/gogo/protobuf"
|
||||||
|
packages = ["gogoproto","proto","protoc-gen-gogo/descriptor"]
|
||||||
|
revision = "342cbe0a04158f6dcb03ca0079991a51a4248c02"
|
||||||
|
version = "v0.5"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/golang/protobuf"
|
||||||
|
packages = ["jsonpb","proto","ptypes","ptypes/any","ptypes/duration","ptypes/struct","ptypes/timestamp"]
|
||||||
|
revision = "1e59b77b52bf8e4b449a57e6f79f21226d571845"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/opentracing/opentracing-go"
|
||||||
|
packages = [".","ext","log","mocktracer"]
|
||||||
|
revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38"
|
||||||
|
version = "v1.0.2"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/pmezard/go-difflib"
|
||||||
|
packages = ["difflib"]
|
||||||
|
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/sirupsen/logrus"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "f006c2ac4710855cf0f916dd6b77acf6b048dc6e"
|
||||||
|
version = "v1.0.3"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/stretchr/testify"
|
||||||
|
packages = ["assert","require","suite"]
|
||||||
|
revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0"
|
||||||
|
version = "v1.1.4"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "go.uber.org/atomic"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "8474b86a5a6f79c443ce4b2992817ff32cf208b8"
|
||||||
|
version = "v1.3.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "go.uber.org/multierr"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "3c4937480c32f4c13a875a1829af76c98ca3d40a"
|
||||||
|
version = "v1.1.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "go.uber.org/zap"
|
||||||
|
packages = [".","buffer","internal/bufferpool","internal/color","internal/exit","zapcore"]
|
||||||
|
revision = "35aad584952c3e7020db7b839f6b102de6271f89"
|
||||||
|
version = "v1.7.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/crypto"
|
||||||
|
packages = ["ssh/terminal"]
|
||||||
|
revision = "94eea52f7b742c7cbe0b03b22f0c4c8631ece122"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/net"
|
||||||
|
packages = ["context","context/ctxhttp","http2","http2/hpack","idna","internal/timeseries","lex/httplex","trace"]
|
||||||
|
revision = "a8b9294777976932365dabb6640cf1468d95c70f"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/oauth2"
|
||||||
|
packages = [".","google","internal","jws","jwt"]
|
||||||
|
revision = "f95fa95eaa936d9d87489b15d1d18b97c1ba9c28"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/sys"
|
||||||
|
packages = ["unix","windows"]
|
||||||
|
revision = "13fcbd661c8ececa8807a29b48407d674b1d8ed8"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/text"
|
||||||
|
packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"]
|
||||||
|
revision = "75cc3cad82b5f47d3fb229ddda8c5167da14f294"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "google.golang.org/appengine"
|
||||||
|
packages = [".","internal","internal/app_identity","internal/base","internal/datastore","internal/log","internal/modules","internal/remote_api","internal/urlfetch","urlfetch"]
|
||||||
|
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "google.golang.org/genproto"
|
||||||
|
packages = ["googleapis/rpc/status"]
|
||||||
|
revision = "7f0da29060c682909f650ad8ed4e515bd74fa12a"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "google.golang.org/grpc"
|
||||||
|
packages = [".","balancer","balancer/roundrobin","codes","connectivity","credentials","credentials/oauth","encoding","grpclb/grpc_lb_v1/messages","grpclog","internal","keepalive","metadata","naming","peer","resolver","resolver/dns","resolver/passthrough","stats","status","tap","transport"]
|
||||||
|
revision = "5a9f7b402fe85096d2e1d0383435ee1876e863d0"
|
||||||
|
version = "v1.8.0"
|
||||||
|
|
||||||
|
[solve-meta]
|
||||||
|
analyzer-name = "dep"
|
||||||
|
analyzer-version = 1
|
||||||
|
inputs-digest = "b24c6670412eb0bc44ed1db77fecc52333f8725f3e3272bdc568f5683a63031f"
|
||||||
|
solver-name = "gps-cdcl"
|
||||||
|
solver-version = 1
|
|
@ -0,0 +1,35 @@
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/gogo/protobuf"
|
||||||
|
version = "0.5.0"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/golang/protobuf"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/opentracing/opentracing-go"
|
||||||
|
version = "1.0.2"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/sirupsen/logrus"
|
||||||
|
version = "1.0.3"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/stretchr/testify"
|
||||||
|
version = "1.1.4"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "go.uber.org/zap"
|
||||||
|
version = "1.7.1"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/net"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/oauth2"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "google.golang.org/grpc"
|
||||||
|
version = "1.8.0"
|
|
@ -0,0 +1,201 @@
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
|
@ -0,0 +1,86 @@
|
||||||
|
# Go gRPC Middleware
|
||||||
|
|
||||||
|
[![Travis Build](https://travis-ci.org/grpc-ecosystem/go-grpc-middleware.svg?branch=master)](https://travis-ci.org/grpc-ecosystem/go-grpc-middleware)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/grpc-ecosystem/go-grpc-middleware)](https://goreportcard.com/report/github.com/grpc-ecosystem/go-grpc-middleware)
|
||||||
|
[![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/grpc-ecosystem/go-grpc-middleware)
|
||||||
|
[![SourceGraph](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-middleware/-/badge.svg)](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-middleware/?badge)
|
||||||
|
[![codecov](https://codecov.io/gh/grpc-ecosystem/go-grpc-middleware/branch/master/graph/badge.svg)](https://codecov.io/gh/grpc-ecosystem/go-grpc-middleware)
|
||||||
|
[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
|
||||||
|
[![quality: production](https://img.shields.io/badge/quality-production-orange.svg)](#status)
|
||||||
|
[![Slack](slack.png)](https://join.slack.com/t/improbable-eng/shared_invite/enQtMzQ1ODcyMzQ5MjM4LWY5ZWZmNGM2ODc5MmViNmQ3ZTA3ZTY3NzQwOTBlMTkzZmIxZTIxODk0OWU3YjZhNWVlNDU3MDlkZGViZjhkMjc)
|
||||||
|
|
||||||
|
[gRPC Go](https://github.com/grpc/grpc-go) Middleware: interceptors, helpers, utilities.
|
||||||
|
|
||||||
|
**Important** The repo recently moved to `github.com/grpc-ecosystem/go-grpc-middleware`, please update your import paths.
|
||||||
|
|
||||||
|
## Middleware
|
||||||
|
|
||||||
|
[gRPC Go](https://github.com/grpc/grpc-go) recently acquired support for
|
||||||
|
Interceptors, i.e. [middleware](https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81#.gv7tdlghs)
|
||||||
|
that is executed either on the gRPC Server before the request is passed onto the user's application logic, or on the gRPC client either around the user call. It is a perfect way to implement
|
||||||
|
common patterns: auth, logging, message, validation, retries or monitoring.
|
||||||
|
|
||||||
|
These are generic building blocks that make it easy to build multiple microservices easily.
|
||||||
|
The purpose of this repository is to act as a go-to point for such reusable functionality. It contains
|
||||||
|
some of them itself, but also will link to useful external repos.
|
||||||
|
|
||||||
|
`grpc_middleware` itself provides support for chaining interceptors. See [Documentation](DOC.md), but here's an example:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||||
|
|
||||||
|
myServer := grpc.NewServer(
|
||||||
|
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
|
||||||
|
grpc_ctxtags.StreamServerInterceptor(),
|
||||||
|
grpc_opentracing.StreamServerInterceptor(),
|
||||||
|
grpc_prometheus.StreamServerInterceptor,
|
||||||
|
grpc_zap.StreamServerInterceptor(zapLogger),
|
||||||
|
grpc_auth.StreamServerInterceptor(myAuthFunction),
|
||||||
|
grpc_recovery.StreamServerInterceptor(),
|
||||||
|
)),
|
||||||
|
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
|
||||||
|
grpc_ctxtags.UnaryServerInterceptor(),
|
||||||
|
grpc_opentracing.UnaryServerInterceptor(),
|
||||||
|
grpc_prometheus.UnaryServerInterceptor,
|
||||||
|
grpc_zap.UnaryServerInterceptor(zapLogger),
|
||||||
|
grpc_auth.UnaryServerInterceptor(myAuthFunction),
|
||||||
|
grpc_recovery.UnaryServerInterceptor(),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Interceptors
|
||||||
|
|
||||||
|
*Please send a PR to add new interceptors or middleware to this list*
|
||||||
|
|
||||||
|
#### Auth
|
||||||
|
* [`grpc_auth`](auth) - a customizable (via `AuthFunc`) piece of auth middleware
|
||||||
|
|
||||||
|
#### Logging
|
||||||
|
* [`grpc_ctxtags`](tags/) - a library that adds a `Tag` map to context, with data populated from request body
|
||||||
|
* [`grpc_zap`](logging/zap/) - integration of [zap](https://github.com/uber-go/zap) logging library into gRPC handlers.
|
||||||
|
* [`grpc_logrus`](logging/logrus/) - integration of [logrus](https://github.com/sirupsen/logrus) logging library into gRPC handlers.
|
||||||
|
|
||||||
|
|
||||||
|
#### Monitoring
|
||||||
|
* [`grpc_prometheus`⚡](https://github.com/grpc-ecosystem/go-grpc-prometheus) - Prometheus client-side and server-side monitoring middleware
|
||||||
|
* [`otgrpc`⚡](https://github.com/grpc-ecosystem/grpc-opentracing/tree/master/go/otgrpc) - [OpenTracing](http://opentracing.io/) client-side and server-side interceptors
|
||||||
|
* [`grpc_opentracing`](tracing/opentracing) - [OpenTracing](http://opentracing.io/) client-side and server-side interceptors with support for streaming and handler-returned tags
|
||||||
|
|
||||||
|
#### Client
|
||||||
|
* [`grpc_retry`](retry/) - a generic gRPC response code retry mechanism, client-side middleware
|
||||||
|
|
||||||
|
#### Server
|
||||||
|
* [`grpc_validator`](validator/) - codegen inbound message validation from `.proto` options
|
||||||
|
* [`grpc_recovery`](recovery/) - turn panics into gRPC errors
|
||||||
|
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
This code has been running in *production* since May 2016 as the basis of the gRPC micro services stack at [Improbable](https://improbable.io).
|
||||||
|
|
||||||
|
Additional tooling will be added, and contributions are welcome.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
`go-grpc-middleware` is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
|
|
@ -0,0 +1,183 @@
|
||||||
|
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||||
|
// See LICENSE for licensing terms.
|
||||||
|
|
||||||
|
// gRPC Server Interceptor chaining middleware.
|
||||||
|
|
||||||
|
package grpc_middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ChainUnaryServer creates a single interceptor out of a chain of many interceptors.
|
||||||
|
//
|
||||||
|
// Execution is done in left-to-right order, including passing of context.
|
||||||
|
// For example ChainUnaryServer(one, two, three) will execute one before two before three, and three
|
||||||
|
// will see context changes of one and two.
|
||||||
|
func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor {
|
||||||
|
n := len(interceptors)
|
||||||
|
|
||||||
|
if n > 1 {
|
||||||
|
lastI := n - 1
|
||||||
|
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||||
|
var (
|
||||||
|
chainHandler grpc.UnaryHandler
|
||||||
|
curI int
|
||||||
|
)
|
||||||
|
|
||||||
|
chainHandler = func(currentCtx context.Context, currentReq interface{}) (interface{}, error) {
|
||||||
|
if curI == lastI {
|
||||||
|
return handler(currentCtx, currentReq)
|
||||||
|
}
|
||||||
|
curI++
|
||||||
|
resp, err := interceptors[curI](currentCtx, currentReq, info, chainHandler)
|
||||||
|
curI--
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return interceptors[0](ctx, req, info, chainHandler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 1 {
|
||||||
|
return interceptors[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||||
|
return func(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||||
|
return handler(ctx, req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainStreamServer creates a single interceptor out of a chain of many interceptors.
|
||||||
|
//
|
||||||
|
// Execution is done in left-to-right order, including passing of context.
|
||||||
|
// For example ChainUnaryServer(one, two, three) will execute one before two before three.
|
||||||
|
// If you want to pass context between interceptors, use WrapServerStream.
|
||||||
|
func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor {
|
||||||
|
n := len(interceptors)
|
||||||
|
|
||||||
|
if n > 1 {
|
||||||
|
lastI := n - 1
|
||||||
|
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||||
|
var (
|
||||||
|
chainHandler grpc.StreamHandler
|
||||||
|
curI int
|
||||||
|
)
|
||||||
|
|
||||||
|
chainHandler = func(currentSrv interface{}, currentStream grpc.ServerStream) error {
|
||||||
|
if curI == lastI {
|
||||||
|
return handler(currentSrv, currentStream)
|
||||||
|
}
|
||||||
|
curI++
|
||||||
|
err := interceptors[curI](currentSrv, currentStream, info, chainHandler)
|
||||||
|
curI--
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return interceptors[0](srv, stream, info, chainHandler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 1 {
|
||||||
|
return interceptors[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||||
|
return func(srv interface{}, stream grpc.ServerStream, _ *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||||
|
return handler(srv, stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainUnaryClient creates a single interceptor out of a chain of many interceptors.
|
||||||
|
//
|
||||||
|
// Execution is done in left-to-right order, including passing of context.
|
||||||
|
// For example ChainUnaryClient(one, two, three) will execute one before two before three.
|
||||||
|
func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor {
|
||||||
|
n := len(interceptors)
|
||||||
|
|
||||||
|
if n > 1 {
|
||||||
|
lastI := n - 1
|
||||||
|
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
||||||
|
var (
|
||||||
|
chainHandler grpc.UnaryInvoker
|
||||||
|
curI int
|
||||||
|
)
|
||||||
|
|
||||||
|
chainHandler = func(currentCtx context.Context, currentMethod string, currentReq, currentRepl interface{}, currentConn *grpc.ClientConn, currentOpts ...grpc.CallOption) error {
|
||||||
|
if curI == lastI {
|
||||||
|
return invoker(currentCtx, currentMethod, currentReq, currentRepl, currentConn, currentOpts...)
|
||||||
|
}
|
||||||
|
curI++
|
||||||
|
err := interceptors[curI](currentCtx, currentMethod, currentReq, currentRepl, currentConn, chainHandler, currentOpts...)
|
||||||
|
curI--
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return interceptors[0](ctx, method, req, reply, cc, chainHandler, opts...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 1 {
|
||||||
|
return interceptors[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||||
|
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
||||||
|
return invoker(ctx, method, req, reply, cc, opts...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainStreamClient creates a single interceptor out of a chain of many interceptors.
|
||||||
|
//
|
||||||
|
// Execution is done in left-to-right order, including passing of context.
|
||||||
|
// For example ChainStreamClient(one, two, three) will execute one before two before three.
|
||||||
|
func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor {
|
||||||
|
n := len(interceptors)
|
||||||
|
|
||||||
|
if n > 1 {
|
||||||
|
lastI := n - 1
|
||||||
|
return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||||
|
var (
|
||||||
|
chainHandler grpc.Streamer
|
||||||
|
curI int
|
||||||
|
)
|
||||||
|
|
||||||
|
chainHandler = func(currentCtx context.Context, currentDesc *grpc.StreamDesc, currentConn *grpc.ClientConn, currentMethod string, currentOpts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||||
|
if curI == lastI {
|
||||||
|
return streamer(currentCtx, currentDesc, currentConn, currentMethod, currentOpts...)
|
||||||
|
}
|
||||||
|
curI++
|
||||||
|
stream, err := interceptors[curI](currentCtx, currentDesc, currentConn, currentMethod, chainHandler, currentOpts...)
|
||||||
|
curI--
|
||||||
|
return stream, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return interceptors[0](ctx, desc, cc, method, chainHandler, opts...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 1 {
|
||||||
|
return interceptors[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||||
|
return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||||
|
return streamer(ctx, desc, cc, method, opts...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chain creates a single interceptor out of a chain of many interceptors.
|
||||||
|
//
|
||||||
|
// WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors.
|
||||||
|
// Basically syntactic sugar.
|
||||||
|
func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption {
|
||||||
|
return grpc.UnaryInterceptor(ChainUnaryServer(interceptors...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors.
|
||||||
|
// Basically syntactic sugar.
|
||||||
|
func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption {
|
||||||
|
return grpc.StreamInterceptor(ChainStreamServer(interceptors...))
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||||
|
// See LICENSE for licensing terms.
|
||||||
|
|
||||||
|
/*
|
||||||
|
`grpc_middleware` is a collection of gRPC middleware packages: interceptors, helpers and tools.
|
||||||
|
|
||||||
|
Middleware
|
||||||
|
|
||||||
|
gRPC is a fantastic RPC middleware, which sees a lot of adoption in the Golang world. However, the
|
||||||
|
upstream gRPC codebase is relatively bare bones.
|
||||||
|
|
||||||
|
This package, and most of its child packages provides commonly needed middleware for gRPC:
|
||||||
|
client-side interceptors for retires, server-side interceptors for input validation and auth,
|
||||||
|
functions for chaining said interceptors, metadata convenience methods and more.
|
||||||
|
|
||||||
|
Chaining
|
||||||
|
|
||||||
|
By default, gRPC doesn't allow one to have more than one interceptor either on the client nor on
|
||||||
|
the server side. `grpc_middleware` provides convenient chaining methods
|
||||||
|
|
||||||
|
Simple way of turning a multiple interceptors into a single interceptor. Here's an example for
|
||||||
|
server chaining:
|
||||||
|
|
||||||
|
myServer := grpc.NewServer(
|
||||||
|
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)),
|
||||||
|
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary),
|
||||||
|
)
|
||||||
|
|
||||||
|
These interceptors will be executed from left to right: logging, monitoring and auth.
|
||||||
|
|
||||||
|
Here's an example for client side chaining:
|
||||||
|
|
||||||
|
clientConn, err = grpc.Dial(
|
||||||
|
address,
|
||||||
|
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(monitoringClientUnary, retryUnary)),
|
||||||
|
grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(monitoringClientStream, retryStream)),
|
||||||
|
)
|
||||||
|
client = pb_testproto.NewTestServiceClient(clientConn)
|
||||||
|
resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"})
|
||||||
|
|
||||||
|
These interceptors will be executed from left to right: monitoring and then retry logic.
|
||||||
|
|
||||||
|
The retry interceptor will call every interceptor that follows it whenever when a retry happens.
|
||||||
|
|
||||||
|
Writing Your Own
|
||||||
|
|
||||||
|
Implementing your own interceptor is pretty trivial: there are interfaces for that. But the interesting
|
||||||
|
bit exposing common data to handlers (and other middleware), similarly to HTTP Middleware design.
|
||||||
|
For example, you may want to pass the identity of the caller from the auth interceptor all the way
|
||||||
|
to the handling function.
|
||||||
|
|
||||||
|
For example, a client side interceptor example for auth looks like:
|
||||||
|
|
||||||
|
func FakeAuthUnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||||
|
newCtx := context.WithValue(ctx, "user_id", "john@example.com")
|
||||||
|
return handler(newCtx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
Unfortunately, it's not as easy for streaming RPCs. These have the `context.Context` embedded within
|
||||||
|
the `grpc.ServerStream` object. To pass values through context, a wrapper (`WrappedServerStream`) is
|
||||||
|
needed. For example:
|
||||||
|
|
||||||
|
func FakeAuthStreamingInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||||
|
newStream := grpc_middleware.WrapServerStream(stream)
|
||||||
|
newStream.WrappedContext = context.WithValue(ctx, "user_id", "john@example.com")
|
||||||
|
return handler(srv, stream)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
package grpc_middleware
|
|
@ -0,0 +1,22 @@
|
||||||
|
SHELL="/bin/bash"
|
||||||
|
|
||||||
|
GOFILES_NOVENDOR = $(shell go list ./... | grep -v /vendor/)
|
||||||
|
|
||||||
|
all: vet fmt docs test
|
||||||
|
|
||||||
|
docs:
|
||||||
|
./scripts/docs.sh generate
|
||||||
|
|
||||||
|
checkdocs:
|
||||||
|
./scripts/docs.sh check
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
go fmt $(GOFILES_NOVENDOR)
|
||||||
|
|
||||||
|
vet:
|
||||||
|
go vet $(GOFILES_NOVENDOR)
|
||||||
|
|
||||||
|
test: vet
|
||||||
|
./scripts/test_all.sh
|
||||||
|
|
||||||
|
.PHONY: all docs validate test
|
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||||
|
// See LICENSE for licensing terms.
|
||||||
|
|
||||||
|
package grpc_middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WrappedServerStream is a thin wrapper around grpc.ServerStream that allows modifying context.
|
||||||
|
type WrappedServerStream struct {
|
||||||
|
grpc.ServerStream
|
||||||
|
// WrappedContext is the wrapper's own Context. You can assign it.
|
||||||
|
WrappedContext context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
// Context returns the wrapper's WrappedContext, overwriting the nested grpc.ServerStream.Context()
|
||||||
|
func (w *WrappedServerStream) Context() context.Context {
|
||||||
|
return w.WrappedContext
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapServerStream returns a ServerStream that has the ability to overwrite context.
|
||||||
|
func WrapServerStream(stream grpc.ServerStream) *WrappedServerStream {
|
||||||
|
if existing, ok := stream.(*WrappedServerStream); ok {
|
||||||
|
return existing
|
||||||
|
}
|
||||||
|
return &WrappedServerStream{ServerStream: stream, WrappedContext: stream.Context()}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
.DS_Store
|
||||||
|
/vendor
|
||||||
|
/cover
|
||||||
|
cover.out
|
||||||
|
lint.log
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Profiling output
|
||||||
|
*.prof
|
|
@ -0,0 +1,25 @@
|
||||||
|
sudo: false
|
||||||
|
language: go
|
||||||
|
go_import_path: go.uber.org/atomic
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.7.x
|
||||||
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
|
- 1.10.x
|
||||||
|
- 1.x # latest release
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- vendor
|
||||||
|
|
||||||
|
install:
|
||||||
|
- make install_ci
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make test_ci
|
||||||
|
- scripts/test-ubergo.sh
|
||||||
|
- make lint
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
|
@ -0,0 +1,27 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"atomic.go",
|
||||||
|
"error.go",
|
||||||
|
"string.go",
|
||||||
|
],
|
||||||
|
importmap = "k8s.io/kubernetes/vendor/go.uber.org/atomic",
|
||||||
|
importpath = "go.uber.org/atomic",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
|
@ -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.
|
|
@ -0,0 +1,64 @@
|
||||||
|
PACKAGES := $(shell glide nv)
|
||||||
|
# Many Go tools take file globs or directories as arguments instead of packages.
|
||||||
|
PACKAGE_FILES ?= *.go
|
||||||
|
|
||||||
|
|
||||||
|
# The linting tools evolve with each Go version, so run them only on the latest
|
||||||
|
# stable release.
|
||||||
|
GO_VERSION := $(shell go version | cut -d " " -f 3)
|
||||||
|
GO_MINOR_VERSION := $(word 2,$(subst ., ,$(GO_VERSION)))
|
||||||
|
LINTABLE_MINOR_VERSIONS := 7 8
|
||||||
|
ifneq ($(filter $(LINTABLE_MINOR_VERSIONS),$(GO_MINOR_VERSION)),)
|
||||||
|
SHOULD_LINT := true
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
export GO15VENDOREXPERIMENT=1
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build:
|
||||||
|
go build -i $(PACKAGES)
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install:
|
||||||
|
glide --version || go get github.com/Masterminds/glide
|
||||||
|
glide install
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
go test -cover -race $(PACKAGES)
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: install_ci
|
||||||
|
install_ci: install
|
||||||
|
go get github.com/wadey/gocovmerge
|
||||||
|
go get github.com/mattn/goveralls
|
||||||
|
go get golang.org/x/tools/cmd/cover
|
||||||
|
ifdef SHOULD_LINT
|
||||||
|
go get github.com/golang/lint/golint
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint:
|
||||||
|
ifdef SHOULD_LINT
|
||||||
|
@rm -rf lint.log
|
||||||
|
@echo "Checking formatting..."
|
||||||
|
@gofmt -d -s $(PACKAGE_FILES) 2>&1 | tee lint.log
|
||||||
|
@echo "Checking vet..."
|
||||||
|
@$(foreach dir,$(PACKAGE_FILES),go tool vet $(dir) 2>&1 | tee -a lint.log;)
|
||||||
|
@echo "Checking lint..."
|
||||||
|
@$(foreach dir,$(PKGS),golint $(dir) 2>&1 | tee -a lint.log;)
|
||||||
|
@echo "Checking for unresolved FIXMEs..."
|
||||||
|
@git grep -i fixme | grep -v -e vendor -e Makefile | tee -a lint.log
|
||||||
|
@[ ! -s lint.log ]
|
||||||
|
else
|
||||||
|
@echo "Skipping linters on" $(GO_VERSION)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: test_ci
|
||||||
|
test_ci: install_ci build
|
||||||
|
./scripts/cover.sh $(shell go list $(PACKAGES))
|
|
@ -0,0 +1,36 @@
|
||||||
|
# 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
|
||||||
|
`go get -u go.uber.org/atomic`
|
||||||
|
|
||||||
|
## 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.org/uber-go/atomic.svg?branch=master
|
||||||
|
[ci]: https://travis-ci.org/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
|
|
@ -0,0 +1,351 @@
|
||||||
|
// Copyright (c) 2016 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// Package atomic provides simple wrappers around numerics to enforce atomic
|
||||||
|
// access.
|
||||||
|
package atomic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Int32 is an atomic wrapper around an int32.
|
||||||
|
type Int32 struct{ v int32 }
|
||||||
|
|
||||||
|
// NewInt32 creates an Int32.
|
||||||
|
func NewInt32(i int32) *Int32 {
|
||||||
|
return &Int32{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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 is an atomic wrapper around an int64.
|
||||||
|
type Int64 struct{ v int64 }
|
||||||
|
|
||||||
|
// NewInt64 creates an Int64.
|
||||||
|
func NewInt64(i int64) *Int64 {
|
||||||
|
return &Int64{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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint32 is an atomic wrapper around an uint32.
|
||||||
|
type Uint32 struct{ v uint32 }
|
||||||
|
|
||||||
|
// NewUint32 creates a Uint32.
|
||||||
|
func NewUint32(i uint32) *Uint32 {
|
||||||
|
return &Uint32{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 int32 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 is an atomic wrapper around a uint64.
|
||||||
|
type Uint64 struct{ v uint64 }
|
||||||
|
|
||||||
|
// NewUint64 creates a Uint64.
|
||||||
|
func NewUint64(i uint64) *Uint64 {
|
||||||
|
return &Uint64{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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool is an atomic Boolean.
|
||||||
|
type Bool struct{ v uint32 }
|
||||||
|
|
||||||
|
// NewBool creates a Bool.
|
||||||
|
func NewBool(initial bool) *Bool {
|
||||||
|
return &Bool{boolToInt(initial)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load atomically loads the Boolean.
|
||||||
|
func (b *Bool) Load() bool {
|
||||||
|
return truthy(atomic.LoadUint32(&b.v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CAS is an atomic compare-and-swap.
|
||||||
|
func (b *Bool) CAS(old, new bool) bool {
|
||||||
|
return atomic.CompareAndSwapUint32(&b.v, boolToInt(old), boolToInt(new))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store atomically stores the passed value.
|
||||||
|
func (b *Bool) Store(new bool) {
|
||||||
|
atomic.StoreUint32(&b.v, boolToInt(new))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap sets the given value and returns the previous value.
|
||||||
|
func (b *Bool) Swap(new bool) bool {
|
||||||
|
return truthy(atomic.SwapUint32(&b.v, boolToInt(new)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle atomically negates the Boolean and returns the previous value.
|
||||||
|
func (b *Bool) Toggle() bool {
|
||||||
|
return truthy(atomic.AddUint32(&b.v, 1) - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func truthy(n uint32) bool {
|
||||||
|
return n&1 == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func boolToInt(b bool) uint32 {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 is an atomic wrapper around float64.
|
||||||
|
type Float64 struct {
|
||||||
|
v uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64 creates a Float64.
|
||||||
|
func NewFloat64(f float64) *Float64 {
|
||||||
|
return &Float64{math.Float64bits(f)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load atomically loads the wrapped value.
|
||||||
|
func (f *Float64) Load() float64 {
|
||||||
|
return math.Float64frombits(atomic.LoadUint64(&f.v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store atomically stores the passed value.
|
||||||
|
func (f *Float64) Store(s float64) {
|
||||||
|
atomic.StoreUint64(&f.v, math.Float64bits(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CAS is an atomic compare-and-swap.
|
||||||
|
func (f *Float64) CAS(old, new float64) bool {
|
||||||
|
return atomic.CompareAndSwapUint64(&f.v, math.Float64bits(old), math.Float64bits(new))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration is an atomic wrapper around time.Duration
|
||||||
|
// https://godoc.org/time#Duration
|
||||||
|
type Duration struct {
|
||||||
|
v Int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDuration creates a Duration.
|
||||||
|
func NewDuration(d time.Duration) *Duration {
|
||||||
|
return &Duration{v: *NewInt64(int64(d))}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load atomically loads the wrapped value.
|
||||||
|
func (d *Duration) Load() time.Duration {
|
||||||
|
return time.Duration(d.v.Load())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store atomically stores the passed value.
|
||||||
|
func (d *Duration) Store(n time.Duration) {
|
||||||
|
d.v.Store(int64(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap atomically swaps the wrapped time.Duration and returns the old value.
|
||||||
|
func (d *Duration) Swap(n time.Duration) time.Duration {
|
||||||
|
return time.Duration(d.v.Swap(int64(n)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CAS is an atomic compare-and-swap.
|
||||||
|
func (d *Duration) CAS(old, new time.Duration) bool {
|
||||||
|
return d.v.CAS(int64(old), int64(new))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value shadows the type of the same name from sync/atomic
|
||||||
|
// https://godoc.org/sync/atomic#Value
|
||||||
|
type Value struct{ atomic.Value }
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright (c) 2016 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
package atomic
|
||||||
|
|
||||||
|
// Error is an atomic type-safe wrapper around Value for errors
|
||||||
|
type Error struct{ v Value }
|
||||||
|
|
||||||
|
// errorHolder is non-nil holder for error object.
|
||||||
|
// atomic.Value panics on saving nil object, so err object needs to be
|
||||||
|
// wrapped with valid object first.
|
||||||
|
type errorHolder struct{ err error }
|
||||||
|
|
||||||
|
// NewError creates new atomic error object
|
||||||
|
func NewError(err error) *Error {
|
||||||
|
e := &Error{}
|
||||||
|
if err != nil {
|
||||||
|
e.Store(err)
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load atomically loads the wrapped error
|
||||||
|
func (e *Error) Load() error {
|
||||||
|
v := e.v.Load()
|
||||||
|
if v == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
eh := v.(errorHolder)
|
||||||
|
return eh.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store atomically stores error.
|
||||||
|
// NOTE: a holder object is allocated on each Store call.
|
||||||
|
func (e *Error) Store(err error) {
|
||||||
|
e.v.Store(errorHolder{err: err})
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
hash: f14d51408e3e0e4f73b34e4039484c78059cd7fc5f4996fdd73db20dc8d24f53
|
||||||
|
updated: 2016-10-27T00:10:51.16960137-07:00
|
||||||
|
imports: []
|
||||||
|
testImports:
|
||||||
|
- name: github.com/davecgh/go-spew
|
||||||
|
version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
|
||||||
|
subpackages:
|
||||||
|
- spew
|
||||||
|
- name: github.com/pmezard/go-difflib
|
||||||
|
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
|
||||||
|
subpackages:
|
||||||
|
- difflib
|
||||||
|
- name: github.com/stretchr/testify
|
||||||
|
version: d77da356e56a7428ad25149ca77381849a6a5232
|
||||||
|
subpackages:
|
||||||
|
- assert
|
||||||
|
- require
|
|
@ -0,0 +1,6 @@
|
||||||
|
package: go.uber.org/atomic
|
||||||
|
testImport:
|
||||||
|
- package: github.com/stretchr/testify
|
||||||
|
subpackages:
|
||||||
|
- assert
|
||||||
|
- require
|
|
@ -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 atomic
|
||||||
|
|
||||||
|
// String is an atomic type-safe wrapper around Value for strings.
|
||||||
|
type String struct{ v Value }
|
||||||
|
|
||||||
|
// NewString creates a String.
|
||||||
|
func NewString(str string) *String {
|
||||||
|
s := &String{}
|
||||||
|
if str != "" {
|
||||||
|
s.Store(str)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load atomically loads the wrapped string.
|
||||||
|
func (s *String) Load() string {
|
||||||
|
v := s.v.Load()
|
||||||
|
if v == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store atomically stores the passed string.
|
||||||
|
// Note: Converting the string to an interface{} to store in the Value
|
||||||
|
// requires an allocation.
|
||||||
|
func (s *String) Store(str string) {
|
||||||
|
s.v.Store(str)
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/vendor
|
|
@ -0,0 +1,33 @@
|
||||||
|
sudo: false
|
||||||
|
language: go
|
||||||
|
go_import_path: go.uber.org/multierr
|
||||||
|
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- GO15VENDOREXPERIMENT=1
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.7
|
||||||
|
- 1.8
|
||||||
|
- 1.9
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- vendor
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- go version
|
||||||
|
|
||||||
|
install:
|
||||||
|
- |
|
||||||
|
set -e
|
||||||
|
make install_ci
|
||||||
|
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
set -e
|
||||||
|
make lint
|
||||||
|
make test_ci
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
|
@ -0,0 +1,24 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["error.go"],
|
||||||
|
importmap = "k8s.io/kubernetes/vendor/go.uber.org/multierr",
|
||||||
|
importpath = "go.uber.org/multierr",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = ["//vendor/go.uber.org/atomic:go_default_library"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
|
@ -0,0 +1,28 @@
|
||||||
|
Releases
|
||||||
|
========
|
||||||
|
|
||||||
|
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
|
|
@ -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.
|
|
@ -0,0 +1,74 @@
|
||||||
|
export GO15VENDOREXPERIMENT=1
|
||||||
|
|
||||||
|
PACKAGES := $(shell glide nv)
|
||||||
|
|
||||||
|
GO_FILES := $(shell \
|
||||||
|
find . '(' -path '*/.*' -o -path './vendor' ')' -prune \
|
||||||
|
-o -name '*.go' -print | cut -b3-)
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install:
|
||||||
|
glide --version || go get github.com/Masterminds/glide
|
||||||
|
glide install
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build:
|
||||||
|
go build -i $(PACKAGES)
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
go test -cover -race $(PACKAGES)
|
||||||
|
|
||||||
|
.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: govet
|
||||||
|
govet:
|
||||||
|
$(eval VET_LOG := $(shell mktemp -t govet.XXXXX))
|
||||||
|
@go vet $(PACKAGES) 2>&1 \
|
||||||
|
| grep -v '^exit status' > $(VET_LOG) || true
|
||||||
|
@[ ! -s "$(VET_LOG)" ] || (echo "govet failed:" | cat - $(VET_LOG) && false)
|
||||||
|
|
||||||
|
.PHONY: golint
|
||||||
|
golint:
|
||||||
|
@go get github.com/golang/lint/golint
|
||||||
|
$(eval LINT_LOG := $(shell mktemp -t golint.XXXXX))
|
||||||
|
@cat /dev/null > $(LINT_LOG)
|
||||||
|
@$(foreach pkg, $(PACKAGES), golint $(pkg) >> $(LINT_LOG) || true;)
|
||||||
|
@[ ! -s "$(LINT_LOG)" ] || (echo "golint failed:" | cat - $(LINT_LOG) && false)
|
||||||
|
|
||||||
|
.PHONY: staticcheck
|
||||||
|
staticcheck:
|
||||||
|
@go get honnef.co/go/tools/cmd/staticcheck
|
||||||
|
$(eval STATICCHECK_LOG := $(shell mktemp -t staticcheck.XXXXX))
|
||||||
|
@staticcheck $(PACKAGES) 2>&1 > $(STATICCHECK_LOG) || true
|
||||||
|
@[ ! -s "$(STATICCHECK_LOG)" ] || (echo "staticcheck failed:" | cat - $(STATICCHECK_LOG) && false)
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint: gofmt govet golint staticcheck
|
||||||
|
|
||||||
|
.PHONY: cover
|
||||||
|
cover:
|
||||||
|
./scripts/cover.sh $(shell go list $(PACKAGES))
|
||||||
|
go tool cover -html=cover.out -o cover.html
|
||||||
|
|
||||||
|
update-license:
|
||||||
|
@go get go.uber.org/tools/update-license
|
||||||
|
@update-license \
|
||||||
|
$(shell go list -json $(PACKAGES) | \
|
||||||
|
jq -r '.Dir + "/" + (.GoFiles | .[])')
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
.PHONY: install_ci
|
||||||
|
install_ci: install
|
||||||
|
go get github.com/wadey/gocovmerge
|
||||||
|
go get github.com/mattn/goveralls
|
||||||
|
go get golang.org/x/tools/cmd/cover
|
||||||
|
|
||||||
|
.PHONY: test_ci
|
||||||
|
test_ci: install_ci
|
||||||
|
./scripts/cover.sh $(shell go list $(PACKAGES))
|
|
@ -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.org/uber-go/multierr.svg?branch=master
|
||||||
|
[cov-img]: https://codecov.io/gh/uber-go/multierr/branch/master/graph/badge.svg
|
||||||
|
[ci]: https://travis-ci.org/uber-go/multierr
|
||||||
|
[cov]: https://codecov.io/gh/uber-go/multierr
|
|
@ -0,0 +1,401 @@
|
||||||
|
// 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 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:")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// 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 (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"go.uber.org/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Separator for single-line error messages.
|
||||||
|
_singlelineSeparator = []byte("; ")
|
||||||
|
|
||||||
|
_newline = []byte("\n")
|
||||||
|
|
||||||
|
// 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, the returned slice is empty.
|
||||||
|
//
|
||||||
|
// 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:])
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
hash: b53b5e9a84b9cb3cc4b2d0499e23da2feca1eec318ce9bb717ecf35bf24bf221
|
||||||
|
updated: 2017-04-10T13:34:45.671678062-07:00
|
||||||
|
imports:
|
||||||
|
- name: go.uber.org/atomic
|
||||||
|
version: 3b8db5e93c4c02efbc313e17b2e796b0914a01fb
|
||||||
|
testImports:
|
||||||
|
- name: github.com/davecgh/go-spew
|
||||||
|
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
||||||
|
subpackages:
|
||||||
|
- spew
|
||||||
|
- name: github.com/pmezard/go-difflib
|
||||||
|
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
|
||||||
|
subpackages:
|
||||||
|
- difflib
|
||||||
|
- name: github.com/stretchr/testify
|
||||||
|
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
|
||||||
|
subpackages:
|
||||||
|
- assert
|
||||||
|
- require
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# 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
|
|
@ -0,0 +1,108 @@
|
||||||
|
# :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.org/uber-go/zap.svg?branch=master
|
||||||
|
[ci]: https://travis-ci.org/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
|
|
@ -0,0 +1,21 @@
|
||||||
|
language: go
|
||||||
|
sudo: false
|
||||||
|
go:
|
||||||
|
- 1.9.x
|
||||||
|
- 1.10.x
|
||||||
|
go_import_path: go.uber.org/zap
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- TEST_TIMEOUT_SCALE=10
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- vendor
|
||||||
|
install:
|
||||||
|
- make dependencies
|
||||||
|
script:
|
||||||
|
- make lint
|
||||||
|
- make test
|
||||||
|
- make bench
|
||||||
|
after_success:
|
||||||
|
- make cover
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
|
@ -0,0 +1,54 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"array.go",
|
||||||
|
"config.go",
|
||||||
|
"doc.go",
|
||||||
|
"encoder.go",
|
||||||
|
"error.go",
|
||||||
|
"field.go",
|
||||||
|
"flag.go",
|
||||||
|
"global.go",
|
||||||
|
"http_handler.go",
|
||||||
|
"level.go",
|
||||||
|
"logger.go",
|
||||||
|
"options.go",
|
||||||
|
"sink.go",
|
||||||
|
"stacktrace.go",
|
||||||
|
"sugar.go",
|
||||||
|
"time.go",
|
||||||
|
"writer.go",
|
||||||
|
],
|
||||||
|
importmap = "k8s.io/kubernetes/vendor/go.uber.org/zap",
|
||||||
|
importpath = "go.uber.org/zap",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"//vendor/go.uber.org/atomic:go_default_library",
|
||||||
|
"//vendor/go.uber.org/multierr:go_default_library",
|
||||||
|
"//vendor/go.uber.org/zap/internal/bufferpool:go_default_library",
|
||||||
|
"//vendor/go.uber.org/zap/zapcore:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [
|
||||||
|
":package-srcs",
|
||||||
|
"//vendor/go.uber.org/zap/buffer:all-srcs",
|
||||||
|
"//vendor/go.uber.org/zap/internal/bufferpool:all-srcs",
|
||||||
|
"//vendor/go.uber.org/zap/internal/color:all-srcs",
|
||||||
|
"//vendor/go.uber.org/zap/internal/exit:all-srcs",
|
||||||
|
"//vendor/go.uber.org/zap/zapcore:all-srcs",
|
||||||
|
],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
|
@ -0,0 +1,305 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 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
|
|
@ -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/
|
|
@ -0,0 +1,81 @@
|
||||||
|
# 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
|
||||||
|
```
|
||||||
|
|
||||||
|
Install zap's dependencies:
|
||||||
|
|
||||||
|
```
|
||||||
|
make dependencies
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,155 @@
|
||||||
|
# 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 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 |
|
||||||
|
|
||||||
|
[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
|
|
@ -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.
|
|
@ -0,0 +1,76 @@
|
||||||
|
export GO15VENDOREXPERIMENT=1
|
||||||
|
|
||||||
|
BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem
|
||||||
|
PKGS ?= $(shell glide novendor)
|
||||||
|
# Many Go tools take file globs or directories as arguments instead of packages.
|
||||||
|
PKG_FILES ?= *.go zapcore benchmarks buffer zapgrpc zaptest zaptest/observer internal/bufferpool internal/exit internal/color internal/ztest
|
||||||
|
|
||||||
|
# The linting tools evolve with each Go version, so run them only on the latest
|
||||||
|
# stable release.
|
||||||
|
GO_VERSION := $(shell go version | cut -d " " -f 3)
|
||||||
|
GO_MINOR_VERSION := $(word 2,$(subst ., ,$(GO_VERSION)))
|
||||||
|
LINTABLE_MINOR_VERSIONS := 10
|
||||||
|
ifneq ($(filter $(LINTABLE_MINOR_VERSIONS),$(GO_MINOR_VERSION)),)
|
||||||
|
SHOULD_LINT := true
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: lint test
|
||||||
|
|
||||||
|
.PHONY: dependencies
|
||||||
|
dependencies:
|
||||||
|
@echo "Installing Glide and locked dependencies..."
|
||||||
|
glide --version || go get -u -f github.com/Masterminds/glide
|
||||||
|
glide install
|
||||||
|
@echo "Installing test dependencies..."
|
||||||
|
go install ./vendor/github.com/axw/gocov/gocov
|
||||||
|
go install ./vendor/github.com/mattn/goveralls
|
||||||
|
ifdef SHOULD_LINT
|
||||||
|
@echo "Installing golint..."
|
||||||
|
go install ./vendor/github.com/golang/lint/golint
|
||||||
|
else
|
||||||
|
@echo "Not installing golint, since we don't expect to lint on" $(GO_VERSION)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Disable printf-like invocation checking due to testify.assert.Error()
|
||||||
|
VET_RULES := -printf=false
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint:
|
||||||
|
ifdef SHOULD_LINT
|
||||||
|
@rm -rf lint.log
|
||||||
|
@echo "Checking formatting..."
|
||||||
|
@gofmt -d -s $(PKG_FILES) 2>&1 | tee lint.log
|
||||||
|
@echo "Installing test dependencies for vet..."
|
||||||
|
@go test -i $(PKGS)
|
||||||
|
@echo "Checking vet..."
|
||||||
|
@$(foreach dir,$(PKG_FILES),go tool vet $(VET_RULES) $(dir) 2>&1 | tee -a lint.log;)
|
||||||
|
@echo "Checking lint..."
|
||||||
|
@$(foreach dir,$(PKGS),golint $(dir) 2>&1 | tee -a lint.log;)
|
||||||
|
@echo "Checking for unresolved FIXMEs..."
|
||||||
|
@git grep -i fixme | grep -v -e vendor -e Makefile | tee -a lint.log
|
||||||
|
@echo "Checking for license headers..."
|
||||||
|
@./check_license.sh | tee -a lint.log
|
||||||
|
@[ ! -s lint.log ]
|
||||||
|
else
|
||||||
|
@echo "Skipping linters on" $(GO_VERSION)
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
go test -race $(PKGS)
|
||||||
|
|
||||||
|
.PHONY: cover
|
||||||
|
cover:
|
||||||
|
./scripts/cover.sh $(PKGS)
|
||||||
|
|
||||||
|
.PHONY: bench
|
||||||
|
BENCH ?= .
|
||||||
|
bench:
|
||||||
|
@$(foreach pkg,$(PKGS),go test -bench=$(BENCH) -run="^$$" $(BENCH_FLAGS) $(pkg);)
|
||||||
|
|
||||||
|
.PHONY: updatereadme
|
||||||
|
updatereadme:
|
||||||
|
rm -f README.md
|
||||||
|
cat .readme.tmpl | go run internal/readme/readme.go > README.md
|
|
@ -0,0 +1,136 @@
|
||||||
|
# :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 | Objects Allocated |
|
||||||
|
| :--- | :---: | :---: |
|
||||||
|
| :zap: zap | 3131 ns/op | 5 allocs/op |
|
||||||
|
| :zap: zap (sugared) | 4173 ns/op | 21 allocs/op |
|
||||||
|
| zerolog | 16154 ns/op | 90 allocs/op |
|
||||||
|
| lion | 16341 ns/op | 111 allocs/op |
|
||||||
|
| go-kit | 17049 ns/op | 126 allocs/op |
|
||||||
|
| logrus | 23662 ns/op | 142 allocs/op |
|
||||||
|
| log15 | 36351 ns/op | 149 allocs/op |
|
||||||
|
| apex/log | 42530 ns/op | 126 allocs/op |
|
||||||
|
|
||||||
|
Log a message with a logger that already has 10 fields of context:
|
||||||
|
|
||||||
|
| Package | Time | Objects Allocated |
|
||||||
|
| :--- | :---: | :---: |
|
||||||
|
| :zap: zap | 380 ns/op | 0 allocs/op |
|
||||||
|
| :zap: zap (sugared) | 564 ns/op | 2 allocs/op |
|
||||||
|
| zerolog | 321 ns/op | 0 allocs/op |
|
||||||
|
| lion | 7092 ns/op | 39 allocs/op |
|
||||||
|
| go-kit | 20226 ns/op | 115 allocs/op |
|
||||||
|
| logrus | 22312 ns/op | 130 allocs/op |
|
||||||
|
| log15 | 28788 ns/op | 79 allocs/op |
|
||||||
|
| apex/log | 42063 ns/op | 115 allocs/op |
|
||||||
|
|
||||||
|
Log a static string, without any context or `printf`-style templating:
|
||||||
|
|
||||||
|
| Package | Time | Objects Allocated |
|
||||||
|
| :--- | :---: | :---: |
|
||||||
|
| :zap: zap | 361 ns/op | 0 allocs/op |
|
||||||
|
| :zap: zap (sugared) | 534 ns/op | 2 allocs/op |
|
||||||
|
| zerolog | 323 ns/op | 0 allocs/op |
|
||||||
|
| standard library | 575 ns/op | 2 allocs/op |
|
||||||
|
| go-kit | 922 ns/op | 13 allocs/op |
|
||||||
|
| lion | 1413 ns/op | 10 allocs/op |
|
||||||
|
| logrus | 2291 ns/op | 27 allocs/op |
|
||||||
|
| apex/log | 3690 ns/op | 11 allocs/op |
|
||||||
|
| log15 | 5954 ns/op | 26 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 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.org/uber-go/zap.svg?branch=master
|
||||||
|
[ci]: https://travis-ci.org/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
|
|
@ -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
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"buffer.go",
|
||||||
|
"pool.go",
|
||||||
|
],
|
||||||
|
importmap = "k8s.io/kubernetes/vendor/go.uber.org/zap/buffer",
|
||||||
|
importpath = "go.uber.org/zap/buffer",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
|
@ -0,0 +1,115 @@
|
||||||
|
// 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 "strconv"
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
|
@ -0,0 +1,243 @@
|
||||||
|
// 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 (
|
||||||
|
"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.
|
||||||
|
//
|
||||||
|
// Values configured here are per-second. See zapcore.NewSampler for details.
|
||||||
|
type SamplingConfig struct {
|
||||||
|
Initial int `json:"initial" yaml:"initial"`
|
||||||
|
Thereafter int `json:"thereafter" yaml:"thereafter"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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",
|
||||||
|
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",
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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 cfg.Sampling != nil {
|
||||||
|
opts = append(opts, WrapCore(func(core zapcore.Core) zapcore.Core {
|
||||||
|
return zapcore.NewSampler(core, time.Second, int(cfg.Sampling.Initial), int(cfg.Sampling.Thereafter))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
|
@ -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
|
|
@ -0,0 +1,75 @@
|
||||||
|
// 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) {
|
||||||
|
_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)
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue