/
main.go
120 lines (106 loc) · 3.29 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
115
116
117
118
119
120
package main
import (
"database/sql"
"fmt"
"io"
"log"
"net/http"
_ "github.com/go-sql-driver/mysql"
"github.com/honeycombio/beeline-go"
"github.com/honeycombio/beeline-go/wrappers/hnynethttp"
"github.com/honeycombio/beeline-go/wrappers/hnysql"
)
func main() {
// Initialize beeline. The only required field is WriteKey.
beeline.Init(beeline.Config{
WriteKey: "abcabc123123",
Dataset: "http+sql",
// for demonstration, send the event to STDOUT instead of Honeycomb.
// Remove the STDOUT setting when filling in a real write key.
// NOTE: This should *only* be set to true in development environments.
// Setting to true is Production environments can cause problems.
STDOUT: true,
})
// open a regular sqlx connection and wrap it
odb, err := sql.Open("mysql", "root:@tcp(127.0.0.1)/donut")
if err != nil {
fmt.Printf("connection err: %s\n", err)
return
}
db := hnysql.WrapDB(odb)
// hand it to the app for use in the handler
a := &app{}
a.db = db
globalmux := http.NewServeMux()
globalmux.HandleFunc("/hello/", a.hello)
// wrap the globalmux with the honeycomb middleware to send one event per
// request
log.Fatal(http.ListenAndServe("localhost:8080", hnynethttp.WrapHandler(globalmux)))
}
type app struct {
db *hnysql.DB
}
func (a *app) hello(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// get all flavors from the DB
rows, err := a.db.QueryContext(ctx, "SELECT flavor FROM flavors GROUP BY flavor")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// collect them
flavors := []string{}
for rows.Next() {
var flavor string
if err := rows.Scan(&flavor); err != nil {
log.Fatal(err)
}
flavors = append(flavors, flavor)
}
// add some custom fields to the Honeycomb event
beeline.AddField(ctx, "flavors_count", len(flavors))
beeline.AddField(ctx, "flavors", flavors)
// send our response to the caller
io.WriteString(w,
fmt.Sprintf("Hello world! Here are our %d flavors:\n", len(flavors)))
for _, flavor := range flavors {
io.WriteString(w, flavor+"\n")
}
}
// A call to the hello endpoint produces two events, one for the HTTP request
// and one for the SQL call. They look like this:
//
// {
// "data": {
// "duration_ms": 2.735045,
// "flavors": ["chocolate","mint","rose","vanilla"],
// "flavors_count": 4,
// "meta.localhostname": "cobbler",
// "meta.type": "http request",
// "mux.handler.name": "main.(*app).(main.hello)-fm",
// "mux.handler.pattern": "/hello/",
// "mux.handler.type": "http.HandlerFunc",
// "request.content_length": 0,
// "request.header.user_agent": "curl/7.54.0",
// "request.host": "localhost:8080",
// "request.method": "GET",
// "request.path": "/hello/foo",
// "request.proto": "HTTP/1.1",
// "request.remote_addr": "[::1]:52317",
// "response.status_code": 200
// "trace.trace_id": "a0eca504-a652-46da-b968-07dd076e2d0c",
// },
// "time": "2018-04-06T22:42:18.449138413-07:00"
// }
// {
// "data": {
// "sql.call": "QueryContext",
// "duration_ms": 1.75518,
// "meta.localhostname": "cobbler",
// "meta.type": "sql",
// "sql.open_conns": 0,
// "sql.query": "SELECT flavor FROM flavors GROUP BY flavor"
// "trace.trace_id": "a0eca504-a652-46da-b968-07dd076e2d0c",
// },
// "time": "2018-04-06T22:42:18.449620729-07:00"
// }