forked from honeycombio/beeline-go
/
main.go
114 lines (103 loc) · 3.27 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package main
import (
"context"
"crypto/sha256"
"fmt"
"io"
"io/ioutil"
"log"
"math"
"math/rand"
"net/http"
"strings"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/honeycombio/beeline-go"
"github.com/honeycombio/beeline-go/wrappers/hnynethttp"
)
func main() {
// Initialize beeline. The only required field is WriteKey.
beeline.Init(beeline.Config{
WriteKey: "abcabc123123abcabc",
Dataset: "beeline-example",
ServiceName: "sample app",
// SamplerHook: sampler,
// PresendHook: presend,
// for demonstration, send the event to STDOUT instead of Honeycomb.
// Remove the STDOUT setting when filling in a real write key.
STDOUT: true,
})
globalmux := http.NewServeMux()
globalmux.HandleFunc("/hello/", hello)
// wrap the globalmux with the honeycomb middleware to send one event per
// request
log.Fatal(http.ListenAndServe("localhost:8080", hnynethttp.WrapHandler(globalmux)))
}
func hello(w http.ResponseWriter, r *http.Request) {
beeline.AddField(r.Context(), "email", "one@two.com")
bigJob(r.Context())
outboundCall(r.Context())
// send our response to the caller
io.WriteString(w, fmt.Sprintf("Hello world!\n"))
}
// bigJob is going to take a long time and do lots of interesting work. It
// should get its own span.
func bigJob(ctx context.Context) {
ctx, span := beeline.StartSpan(ctx, "bigJob")
defer span.Send()
beeline.AddField(ctx, "m1", 5.67)
beeline.AddField(ctx, "m2", 8.90)
// bigJob will take ~300ms
sleepTime := math.Abs(200.0 + (rand.NormFloat64()*50 + 100))
time.Sleep(time.Duration(sleepTime) * time.Millisecond)
// this job also discovered something that's relevant to the whole trace
beeline.AddFieldToTrace(ctx, "vip_user", true)
}
// outboundCall demonstrates wrapping an outbound HTTP client
func outboundCall(ctx context.Context) {
// let's make an outbound HTTP call
client := &http.Client{
Transport: hnynethttp.WrapRoundTripper(http.DefaultTransport),
Timeout: time.Second * 5,
}
req, _ := http.NewRequest(http.MethodGet, "http://scooterlabs.com/echo.json", strings.NewReader(""))
req = req.WithContext(ctx)
resp, err := client.Do(req)
if err == nil {
defer resp.Body.Close()
bod, _ := ioutil.ReadAll(resp.Body)
// data, _ := base64.StdEncoding.DecodeString(string(bod))
beeline.AddField(ctx, "resp.body", string(bod))
}
}
func presend(fields map[string]interface{}) {
// If the email address field exists, add a field representing the
// domain of the user's email address and hash the original email
if email, ok := fields["app.email"]; ok {
if emailStr, ok := email.(string); ok {
splitEmail := strings.SplitN(emailStr, "@", 2)
if len(splitEmail) == 2 {
domain := splitEmail[1]
fields["doamin"] = domain
}
// then hash the email so it is obscured
hashedEmail := sha256.Sum256([]byte(fmt.Sprintf("%v", emailStr)))
fields["app.email"] = fmt.Sprintf("%x", hashedEmail)
}
}
}
func sampler(fields map[string]interface{}) (bool, int) {
// example sampler that samples at 1/3 when the "m1" field is present and
// 1/2 when it is absent
var sampleRate = 2
if _, ok := fields["app.m1"]; ok {
sampleRate = 3
}
if rand.Intn(sampleRate) == 0 {
// keep the event!
return true, sampleRate
}
// sample rate here doesn't matter because the event is going to get
// dropped
return false, 0
}