This repository has been archived by the owner on Oct 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 21
/
server.go
127 lines (110 loc) · 4.14 KB
/
server.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
121
122
123
124
125
126
127
// Copyright 2019, OpenCensus Authors
//
// 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 main
import (
"contrib.go.opencensus.io/exporter/ocagent"
cryptoRand "crypto/rand"
"encoding/hex"
"flag"
"fmt"
"go.opencensus.io/plugin/ochttp"
"go.opencensus.io/plugin/ochttp/propagation/tracecontext"
"go.opencensus.io/trace"
"html/template"
"log"
"math/rand"
"net/http"
"time"
)
// Use a local agent by default to help in local development.
var agentHostAndPort = flag.String("agent", "localhost:55678", "Host:port of OpenCensus agent")
// Use local webpack server on port 8080 by default.
var ocwScriptEndpoint = flag.String("ocw_script_prefix", "http://localhost:8080", "HTTP(S) endpoint that serves OpenCensus Web JS script")
var listenAddr = flag.String("listen", ":8000", "")
// Data rendered to the HTML template
type pageData struct {
Traceparent string
AgentHostAndPort template.URL
OcwScriptEndpoint template.URL
}
func main() {
flag.Parse()
exp, err := ocagent.NewExporter(
ocagent.WithInsecure(),
ocagent.WithAddress(*agentHostAndPort),
ocagent.WithServiceName("hello-server"))
if err != nil {
log.Fatalf("Failed to create the agent exporter: %v", err)
}
defer exp.Stop()
trace.RegisterExporter(exp)
// Always trace for this demo. In a production application, you should
// configure this to a trace.ProbabilitySampler set at the desired
// probability.
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
serveMux := http.NewServeMux()
serveMux.HandleFunc("/", handleRequest)
fs := http.FileServer(http.Dir("static"))
serveMux.Handle("/static/", http.StripPrefix("/static/", fs))
var handler http.Handler = serveMux
handler = &ochttp.Handler{
Handler: serveMux,
Propagation: &tracecontext.HTTPFormat{},
}
// Note that the `ensureTraceHeader` middleware comes after the
// `ochttp.Handler` middleware so that it is executed first. That way it the
// traceparent header will already be set when the ochttp.Handler middleware
// runs.
handler = ensureTraceHeader(handler)
fmt.Printf("OC Web initial load example server listening on %v\n", *listenAddr)
log.Fatal(http.ListenAndServe(*listenAddr, handler))
}
// Adds a random traceparent header if none is specified. This is needed
// because the browser does not sent a trace header for the initial page
// load. The traceparent header is written to the HTML so that the browser span
// can become the parent of the initial load server span.
func ensureTraceHeader(next http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
traceparent := fmt.Sprintf("00-%s-%s-01", randHex(32), randHex(16))
r.Header.Add("traceparent", traceparent)
next.ServeHTTP(w, r)
}
}
func handleRequest(w http.ResponseWriter, r *http.Request) {
// Parse template.
_, parseSpan := trace.StartSpan(r.Context(), "Parse template")
tmpl := template.Must(template.ParseFiles("index.html"))
parseSpan.End()
// Sleep for [1,100] milliseconds to fake work.
_, delaySpan := trace.StartSpan(r.Context(), "Random delay")
time.Sleep(time.Duration(rand.Intn(100)+1) * time.Millisecond)
delaySpan.End()
// Render template.
_, renderSpan := trace.StartSpan(r.Context(), "Render template")
data := pageData{
Traceparent: r.Header.Get("traceparent"),
AgentHostAndPort: template.URL(*agentHostAndPort),
OcwScriptEndpoint: template.URL(*ocwScriptEndpoint),
}
tmpl.Execute(w, data)
renderSpan.End()
}
// randHex returns a random hexadecimal encoded string of given number of bytes.
func randHex(numBytes int) string {
b := make([]byte, numBytes/2)
if _, err := cryptoRand.Read(b); err != nil {
panic(err)
}
return hex.EncodeToString(b)[:numBytes]
}