summaryrefslogtreecommitdiff
path: root/vendor/github.com/uber/jaeger-client-go/utils
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/uber/jaeger-client-go/utils')
-rw-r--r--vendor/github.com/uber/jaeger-client-go/utils/http_json.go54
-rw-r--r--vendor/github.com/uber/jaeger-client-go/utils/localip.go84
-rw-r--r--vendor/github.com/uber/jaeger-client-go/utils/rand.go46
-rw-r--r--vendor/github.com/uber/jaeger-client-go/utils/rate_limiter.go77
-rw-r--r--vendor/github.com/uber/jaeger-client-go/utils/udp_client.go98
-rw-r--r--vendor/github.com/uber/jaeger-client-go/utils/utils.go87
6 files changed, 446 insertions, 0 deletions
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/http_json.go b/vendor/github.com/uber/jaeger-client-go/utils/http_json.go
new file mode 100644
index 000000000..237211f82
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/http_json.go
@@ -0,0 +1,54 @@
+// Copyright (c) 2017 Uber Technologies, 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 utils
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+)
+
+// GetJSON makes an HTTP call to the specified URL and parses the returned JSON into `out`.
+func GetJSON(url string, out interface{}) error {
+ resp, err := http.Get(url)
+ if err != nil {
+ return err
+ }
+ return ReadJSON(resp, out)
+}
+
+// ReadJSON reads JSON from http.Response and parses it into `out`
+func ReadJSON(resp *http.Response, out interface{}) error {
+ defer resp.Body.Close()
+
+ if resp.StatusCode >= 400 {
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return err
+ }
+
+ return fmt.Errorf("StatusCode: %d, Body: %s", resp.StatusCode, body)
+ }
+
+ if out == nil {
+ io.Copy(ioutil.Discard, resp.Body)
+ return nil
+ }
+
+ decoder := json.NewDecoder(resp.Body)
+ return decoder.Decode(out)
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/localip.go b/vendor/github.com/uber/jaeger-client-go/utils/localip.go
new file mode 100644
index 000000000..b51af7713
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/localip.go
@@ -0,0 +1,84 @@
+// Copyright (c) 2017 Uber Technologies, 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 utils
+
+import (
+ "errors"
+ "net"
+)
+
+// This code is borrowed from https://github.com/uber/tchannel-go/blob/dev/localip.go
+
+// scoreAddr scores how likely the given addr is to be a remote address and returns the
+// IP to use when listening. Any address which receives a negative score should not be used.
+// Scores are calculated as:
+// -1 for any unknown IP addresses.
+// +300 for IPv4 addresses
+// +100 for non-local addresses, extra +100 for "up" interaces.
+func scoreAddr(iface net.Interface, addr net.Addr) (int, net.IP) {
+ var ip net.IP
+ if netAddr, ok := addr.(*net.IPNet); ok {
+ ip = netAddr.IP
+ } else if netIP, ok := addr.(*net.IPAddr); ok {
+ ip = netIP.IP
+ } else {
+ return -1, nil
+ }
+
+ var score int
+ if ip.To4() != nil {
+ score += 300
+ }
+ if iface.Flags&net.FlagLoopback == 0 && !ip.IsLoopback() {
+ score += 100
+ if iface.Flags&net.FlagUp != 0 {
+ score += 100
+ }
+ }
+ return score, ip
+}
+
+// HostIP tries to find an IP that can be used by other machines to reach this machine.
+func HostIP() (net.IP, error) {
+ interfaces, err := net.Interfaces()
+ if err != nil {
+ return nil, err
+ }
+
+ bestScore := -1
+ var bestIP net.IP
+ // Select the highest scoring IP as the best IP.
+ for _, iface := range interfaces {
+ addrs, err := iface.Addrs()
+ if err != nil {
+ // Skip this interface if there is an error.
+ continue
+ }
+
+ for _, addr := range addrs {
+ score, ip := scoreAddr(iface, addr)
+ if score > bestScore {
+ bestScore = score
+ bestIP = ip
+ }
+ }
+ }
+
+ if bestScore == -1 {
+ return nil, errors.New("no addresses to listen on")
+ }
+
+ return bestIP, nil
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/rand.go b/vendor/github.com/uber/jaeger-client-go/utils/rand.go
new file mode 100644
index 000000000..9875f7f55
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/rand.go
@@ -0,0 +1,46 @@
+// Copyright (c) 2017 Uber Technologies, 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 utils
+
+import (
+ "math/rand"
+ "sync"
+)
+
+// lockedSource allows a random number generator to be used by multiple goroutines concurrently.
+// The code is very similar to math/rand.lockedSource, which is unfortunately not exposed.
+type lockedSource struct {
+ mut sync.Mutex
+ src rand.Source
+}
+
+// NewRand returns a rand.Rand that is threadsafe.
+func NewRand(seed int64) *rand.Rand {
+ return rand.New(&lockedSource{src: rand.NewSource(seed)})
+}
+
+func (r *lockedSource) Int63() (n int64) {
+ r.mut.Lock()
+ n = r.src.Int63()
+ r.mut.Unlock()
+ return
+}
+
+// Seed implements Seed() of Source
+func (r *lockedSource) Seed(seed int64) {
+ r.mut.Lock()
+ r.src.Seed(seed)
+ r.mut.Unlock()
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/rate_limiter.go b/vendor/github.com/uber/jaeger-client-go/utils/rate_limiter.go
new file mode 100644
index 000000000..1b8db9758
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/rate_limiter.go
@@ -0,0 +1,77 @@
+// Copyright (c) 2017 Uber Technologies, 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 utils
+
+import (
+ "sync"
+ "time"
+)
+
+// RateLimiter is a filter used to check if a message that is worth itemCost units is within the rate limits.
+type RateLimiter interface {
+ CheckCredit(itemCost float64) bool
+}
+
+type rateLimiter struct {
+ sync.Mutex
+
+ creditsPerSecond float64
+ balance float64
+ maxBalance float64
+ lastTick time.Time
+
+ timeNow func() time.Time
+}
+
+// NewRateLimiter creates a new rate limiter based on leaky bucket algorithm, formulated in terms of a
+// credits balance that is replenished every time CheckCredit() method is called (tick) by the amount proportional
+// to the time elapsed since the last tick, up to max of creditsPerSecond. A call to CheckCredit() takes a cost
+// of an item we want to pay with the balance. If the balance exceeds the cost of the item, the item is "purchased"
+// and the balance reduced, indicated by returned value of true. Otherwise the balance is unchanged and return false.
+//
+// This can be used to limit a rate of messages emitted by a service by instantiating the Rate Limiter with the
+// max number of messages a service is allowed to emit per second, and calling CheckCredit(1.0) for each message
+// to determine if the message is within the rate limit.
+//
+// It can also be used to limit the rate of traffic in bytes, by setting creditsPerSecond to desired throughput
+// as bytes/second, and calling CheckCredit() with the actual message size.
+func NewRateLimiter(creditsPerSecond, maxBalance float64) RateLimiter {
+ return &rateLimiter{
+ creditsPerSecond: creditsPerSecond,
+ balance: maxBalance,
+ maxBalance: maxBalance,
+ lastTick: time.Now(),
+ timeNow: time.Now}
+}
+
+func (b *rateLimiter) CheckCredit(itemCost float64) bool {
+ b.Lock()
+ defer b.Unlock()
+ // calculate how much time passed since the last tick, and update current tick
+ currentTime := b.timeNow()
+ elapsedTime := currentTime.Sub(b.lastTick)
+ b.lastTick = currentTime
+ // calculate how much credit have we accumulated since the last tick
+ b.balance += elapsedTime.Seconds() * b.creditsPerSecond
+ if b.balance > b.maxBalance {
+ b.balance = b.maxBalance
+ }
+ // if we have enough credits to pay for current item, then reduce balance and allow
+ if b.balance >= itemCost {
+ b.balance -= itemCost
+ return true
+ }
+ return false
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/udp_client.go b/vendor/github.com/uber/jaeger-client-go/utils/udp_client.go
new file mode 100644
index 000000000..6f042073d
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/udp_client.go
@@ -0,0 +1,98 @@
+// Copyright (c) 2017 Uber Technologies, 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 utils
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "net"
+
+ "github.com/uber/jaeger-client-go/thrift"
+
+ "github.com/uber/jaeger-client-go/thrift-gen/agent"
+ "github.com/uber/jaeger-client-go/thrift-gen/jaeger"
+ "github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
+)
+
+// UDPPacketMaxLength is the max size of UDP packet we want to send, synced with jaeger-agent
+const UDPPacketMaxLength = 65000
+
+// AgentClientUDP is a UDP client to Jaeger agent that implements agent.Agent interface.
+type AgentClientUDP struct {
+ agent.Agent
+ io.Closer
+
+ connUDP *net.UDPConn
+ client *agent.AgentClient
+ maxPacketSize int // max size of datagram in bytes
+ thriftBuffer *thrift.TMemoryBuffer // buffer used to calculate byte size of a span
+}
+
+// NewAgentClientUDP creates a client that sends spans to Jaeger Agent over UDP.
+func NewAgentClientUDP(hostPort string, maxPacketSize int) (*AgentClientUDP, error) {
+ if maxPacketSize == 0 {
+ maxPacketSize = UDPPacketMaxLength
+ }
+
+ thriftBuffer := thrift.NewTMemoryBufferLen(maxPacketSize)
+ protocolFactory := thrift.NewTCompactProtocolFactory()
+ client := agent.NewAgentClientFactory(thriftBuffer, protocolFactory)
+
+ destAddr, err := net.ResolveUDPAddr("udp", hostPort)
+ if err != nil {
+ return nil, err
+ }
+
+ connUDP, err := net.DialUDP(destAddr.Network(), nil, destAddr)
+ if err != nil {
+ return nil, err
+ }
+ if err := connUDP.SetWriteBuffer(maxPacketSize); err != nil {
+ return nil, err
+ }
+
+ clientUDP := &AgentClientUDP{
+ connUDP: connUDP,
+ client: client,
+ maxPacketSize: maxPacketSize,
+ thriftBuffer: thriftBuffer}
+ return clientUDP, nil
+}
+
+// EmitZipkinBatch implements EmitZipkinBatch() of Agent interface
+func (a *AgentClientUDP) EmitZipkinBatch(spans []*zipkincore.Span) error {
+ return errors.New("Not implemented")
+}
+
+// EmitBatch implements EmitBatch() of Agent interface
+func (a *AgentClientUDP) EmitBatch(batch *jaeger.Batch) error {
+ a.thriftBuffer.Reset()
+ a.client.SeqId = 0 // we have no need for distinct SeqIds for our one-way UDP messages
+ if err := a.client.EmitBatch(batch); err != nil {
+ return err
+ }
+ if a.thriftBuffer.Len() > a.maxPacketSize {
+ return fmt.Errorf("Data does not fit within one UDP packet; size %d, max %d, spans %d",
+ a.thriftBuffer.Len(), a.maxPacketSize, len(batch.Spans))
+ }
+ _, err := a.connUDP.Write(a.thriftBuffer.Bytes())
+ return err
+}
+
+// Close implements Close() of io.Closer and closes the underlying UDP connection.
+func (a *AgentClientUDP) Close() error {
+ return a.connUDP.Close()
+}
diff --git a/vendor/github.com/uber/jaeger-client-go/utils/utils.go b/vendor/github.com/uber/jaeger-client-go/utils/utils.go
new file mode 100644
index 000000000..ac3c325d1
--- /dev/null
+++ b/vendor/github.com/uber/jaeger-client-go/utils/utils.go
@@ -0,0 +1,87 @@
+// Copyright (c) 2017 Uber Technologies, 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 utils
+
+import (
+ "encoding/binary"
+ "errors"
+ "net"
+ "strconv"
+ "strings"
+ "time"
+)
+
+var (
+ // ErrEmptyIP an error for empty ip strings
+ ErrEmptyIP = errors.New("empty string given for ip")
+
+ // ErrNotHostColonPort an error for invalid host port string
+ ErrNotHostColonPort = errors.New("expecting host:port")
+
+ // ErrNotFourOctets an error for the wrong number of octets after splitting a string
+ ErrNotFourOctets = errors.New("Wrong number of octets")
+)
+
+// ParseIPToUint32 converts a string ip (e.g. "x.y.z.w") to an uint32
+func ParseIPToUint32(ip string) (uint32, error) {
+ if ip == "" {
+ return 0, ErrEmptyIP
+ }
+
+ if ip == "localhost" {
+ return 127<<24 | 1, nil
+ }
+
+ octets := strings.Split(ip, ".")
+ if len(octets) != 4 {
+ return 0, ErrNotFourOctets
+ }
+
+ var intIP uint32
+ for i := 0; i < 4; i++ {
+ octet, err := strconv.Atoi(octets[i])
+ if err != nil {
+ return 0, err
+ }
+ intIP = (intIP << 8) | uint32(octet)
+ }
+
+ return intIP, nil
+}
+
+// ParsePort converts port number from string to uin16
+func ParsePort(portString string) (uint16, error) {
+ port, err := strconv.ParseUint(portString, 10, 16)
+ return uint16(port), err
+}
+
+// PackIPAsUint32 packs an IPv4 as uint32
+func PackIPAsUint32(ip net.IP) uint32 {
+ if ipv4 := ip.To4(); ipv4 != nil {
+ return binary.BigEndian.Uint32(ipv4)
+ }
+ return 0
+}
+
+// TimeToMicrosecondsSinceEpochInt64 converts Go time.Time to a long
+// representing time since epoch in microseconds, which is used expected
+// in the Jaeger spans encoded as Thrift.
+func TimeToMicrosecondsSinceEpochInt64(t time.Time) int64 {
+ // ^^^ Passing time.Time by value is faster than passing a pointer!
+ // BenchmarkTimeByValue-8 2000000000 1.37 ns/op
+ // BenchmarkTimeByPtr-8 2000000000 1.98 ns/op
+
+ return t.UnixNano() / 1000
+}