Skip to content

Commit 92b977d

Browse files
committed
Add star wars example with a sample tracer
1 parent 3751705 commit 92b977d

File tree

1 file changed

+159
-0
lines changed
  • examples/star-wars-with-trace

1 file changed

+159
-0
lines changed

examples/star-wars-with-trace/main.go

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"io/ioutil"
8+
"log"
9+
"net/http"
10+
"time"
11+
12+
"github.com/graphql-go/graphql/gqlerrors"
13+
"github.com/graphql-go/graphql/testutil"
14+
15+
"github.com/graphql-go/graphql"
16+
)
17+
18+
func main() {
19+
http.HandleFunc("/graphql", func(w http.ResponseWriter, r *http.Request) {
20+
var query string
21+
if r.Method == http.MethodGet {
22+
query = r.URL.Query().Get("query")
23+
} else {
24+
q := struct {
25+
Query string `json:"query"`
26+
}{}
27+
bs, err := ioutil.ReadAll(r.Body)
28+
if err != nil {
29+
http.Error(w, err.Error(), http.StatusBadRequest)
30+
}
31+
err = json.Unmarshal(bs, &q)
32+
if err != nil {
33+
http.Error(w, err.Error(), http.StatusBadRequest)
34+
}
35+
query = q.Query
36+
}
37+
testutil.StarWarsSchema.AddExtensions(&Tracer{})
38+
39+
result := graphql.Do(graphql.Params{
40+
Schema: testutil.StarWarsSchema,
41+
RequestString: query,
42+
})
43+
json.NewEncoder(w).Encode(result)
44+
})
45+
fmt.Println("Now server is running on port 8080")
46+
fmt.Println("Test with Get : curl -g 'http://localhost:8080/graphql?query={hero{name}}'")
47+
http.ListenAndServe(":8080", nil)
48+
}
49+
50+
// Test Tracer
51+
52+
type Tracer struct {
53+
result TracingResult
54+
resolvers map[string]*TracingResolverResult
55+
}
56+
57+
func (t *Tracer) Init(ctx context.Context, _ *graphql.Params) {
58+
t.result = TracingResult{
59+
Version: 1,
60+
Execution: TracingExecutionResult{
61+
Resolvers: []TracingResolverResult{},
62+
},
63+
}
64+
t.resolvers = make(map[string]*TracingResolverResult)
65+
}
66+
67+
func (t *Tracer) Name() string {
68+
return "tracing"
69+
}
70+
71+
func (t *Tracer) HasResult() bool {
72+
return true
73+
}
74+
75+
func (t *Tracer) GetResult(ctx context.Context) interface{} {
76+
log.Println("getresult was called")
77+
return t.result
78+
}
79+
80+
func (t *Tracer) ParseDidStart(context.Context) {
81+
t.result.Parsing.StartOffset = time.Since(t.result.StartTime)
82+
}
83+
84+
func (t *Tracer) ParseEnded(context.Context, error) {
85+
t.result.Parsing.Duration = time.Since(t.result.StartTime.Add(t.result.Parsing.StartOffset))
86+
}
87+
88+
func (t *Tracer) ValidationDidStart(context.Context) {
89+
t.result.Validation.StartOffset = time.Since(t.result.StartTime)
90+
}
91+
92+
func (t *Tracer) ValidationEnded(context.Context, []gqlerrors.FormattedError) {
93+
t.result.Validation.Duration = time.Since(t.result.StartTime.Add(t.result.Validation.StartOffset))
94+
}
95+
96+
func (t *Tracer) ExecutionDidStart(ctx context.Context) {
97+
t.result.StartTime = time.Now()
98+
log.Println("Execution did start")
99+
}
100+
101+
func (t *Tracer) ExecutionEnded(ctx context.Context) {
102+
t.result.EndTime = time.Now()
103+
t.result.Duration = t.result.EndTime.Sub(t.result.StartTime)
104+
for _, r := range t.resolvers {
105+
t.result.Execution.Resolvers = append(t.result.Execution.Resolvers, *r)
106+
}
107+
log.Println("Execution ended")
108+
}
109+
110+
func (t *Tracer) ResolveFieldDidStart(ctx context.Context, i *graphql.ResolveInfo) {
111+
t.resolvers[fmt.Sprint(i.Path.AsArray())] = &TracingResolverResult{
112+
Path: i.Path.AsArray(),
113+
ParentType: i.ParentType.String(),
114+
FieldName: i.FieldName,
115+
ReturnType: i.ReturnType.String(),
116+
StartOffset: time.Since(t.result.StartTime),
117+
}
118+
119+
log.Printf("Resolving %+v field started!", i.FieldName)
120+
}
121+
122+
func (t *Tracer) ResolveFieldEnded(ctx context.Context, i *graphql.ResolveInfo) {
123+
r := t.resolvers[fmt.Sprint(i.Path.AsArray())]
124+
r.Duration = time.Since(t.result.StartTime.Add(t.resolvers[fmt.Sprint(i.Path.AsArray())].StartOffset))
125+
log.Printf("Resolving %v field ended!", i.FieldName)
126+
}
127+
128+
type TracingResult struct {
129+
Version int `json:"version"`
130+
StartTime time.Time `json:"startTime"`
131+
EndTime time.Time `json:"endTime"`
132+
Duration time.Duration `json:"duration"`
133+
Parsing TracingParsingResult `json:"parsing"`
134+
Validation TracingValidationResult `json:"validation"`
135+
Execution TracingExecutionResult `json:"execution"`
136+
}
137+
138+
type TracingParsingResult struct {
139+
StartOffset time.Duration `json:"startOffset"`
140+
Duration time.Duration `json:"duration"`
141+
}
142+
143+
type TracingValidationResult struct {
144+
StartOffset time.Duration `json:"startOffset"`
145+
Duration time.Duration `json:"duration"`
146+
}
147+
148+
type TracingExecutionResult struct {
149+
Resolvers []TracingResolverResult `json:"resolvers"`
150+
}
151+
152+
type TracingResolverResult struct {
153+
Path []interface{} `json:"path"`
154+
ParentType string `json:"parentType"`
155+
FieldName string `json:"fieldName"`
156+
ReturnType string `json:"returnType"`
157+
StartOffset time.Duration `json:"startOffset"`
158+
Duration time.Duration `json:"duration"`
159+
}

0 commit comments

Comments
 (0)