-
Notifications
You must be signed in to change notification settings - Fork 592
/
Copy pathclient.go
179 lines (142 loc) · 5.75 KB
/
client.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/contrib/samplers/aws/xray/internal"
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
)
// getSamplingRulesOutput is used to store parsed json sampling rules.
type getSamplingRulesOutput struct {
SamplingRuleRecords []*samplingRuleRecords `json:"SamplingRuleRecords"`
}
type samplingRuleRecords struct {
SamplingRule *ruleProperties `json:"SamplingRule"`
}
// ruleProperties is the base set of properties that define a sampling rule.
type ruleProperties struct {
RuleName string `json:"RuleName"`
ServiceType string `json:"ServiceType"`
ResourceARN string `json:"ResourceARN"`
Attributes map[string]string `json:"Attributes"`
ServiceName string `json:"ServiceName"`
Host string `json:"Host"`
HTTPMethod string `json:"HTTPMethod"`
URLPath string `json:"URLPath"`
ReservoirSize float64 `json:"ReservoirSize"`
FixedRate float64 `json:"FixedRate"`
Priority int64 `json:"Priority"`
Version int64 `json:"Version"`
}
type getSamplingTargetsInput struct {
SamplingStatisticsDocuments []*samplingStatisticsDocument
}
// samplingStatisticsDocument is used to store current state of sampling data.
type samplingStatisticsDocument struct {
// A unique identifier for the service in hexadecimal.
ClientID *string
// The name of the sampling rule.
RuleName *string
// The number of requests that matched the rule.
RequestCount *int64
// The number of requests borrowed.
BorrowCount *int64
// The number of requests sampled using the rule.
SampledCount *int64
// The current time.
Timestamp *int64
}
// getSamplingTargetsOutput is used to store parsed json sampling targets.
type getSamplingTargetsOutput struct {
LastRuleModification *float64 `json:"LastRuleModification,omitempty"`
SamplingTargetDocuments []*samplingTargetDocument `json:"SamplingTargetDocuments,omitempty"`
UnprocessedStatistics []*unprocessedStatistic `json:"UnprocessedStatistics,omitempty"`
}
// samplingTargetDocument contains updated targeted information retrieved from X-Ray service.
type samplingTargetDocument struct {
// The percentage of matching requests to instrument, after the reservoir is
// exhausted.
FixedRate *float64 `json:"FixedRate,omitempty"`
// The number of seconds for the service to wait before getting sampling targets
// again.
Interval *int64 `json:"Interval,omitempty"`
// The number of requests per second that X-Ray allocated this service.
ReservoirQuota *float64 `json:"ReservoirQuota,omitempty"`
// The reservoir quota expires.
ReservoirQuotaTTL *float64 `json:"ReservoirQuotaTTL,omitempty"`
// The name of the sampling rule.
RuleName *string `json:"RuleName,omitempty"`
}
type unprocessedStatistic struct {
ErrorCode *string `json:"ErrorCode,omitempty"`
Message *string `json:"Message,omitempty"`
RuleName *string `json:"RuleName,omitempty"`
}
type xrayClient struct {
// HTTP client for sending sampling requests to the collector.
httpClient *http.Client
// Resolved URL to call getSamplingRules API.
samplingRulesURL string
// Resolved URL to call getSamplingTargets API.
samplingTargetsURL string
}
// newClient returns an HTTP client with proxy endpoint.
func newClient(endpoint url.URL) (client *xrayClient, err error) {
// Construct resolved URLs for getSamplingRules and getSamplingTargets API calls.
endpoint.Path = "/GetSamplingRules"
samplingRulesURL := endpoint
endpoint.Path = "/SamplingTargets"
samplingTargetsURL := endpoint
return &xrayClient{
httpClient: &http.Client{},
samplingRulesURL: samplingRulesURL.String(),
samplingTargetsURL: samplingTargetsURL.String(),
}, nil
}
// getSamplingRules calls the collector(aws proxy enabled) for sampling rules.
func (c *xrayClient) getSamplingRules(ctx context.Context) (*getSamplingRulesOutput, error) {
emptySamplingRulesInputJSON := []byte(`{"NextToken": null}`)
body := bytes.NewReader(emptySamplingRulesInputJSON)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.samplingRulesURL, body)
if err != nil {
return nil, fmt.Errorf("xray client: failed to create http request: %w", err)
}
output, err := c.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("xray client: unable to retrieve sampling settings: %w", err)
}
defer output.Body.Close()
var samplingRulesOutput *getSamplingRulesOutput
if err := json.NewDecoder(output.Body).Decode(&samplingRulesOutput); err != nil {
return nil, fmt.Errorf("xray client: unable to unmarshal the response body: %w", err)
}
return samplingRulesOutput, nil
}
// getSamplingTargets calls the collector(aws proxy enabled) for sampling targets.
func (c *xrayClient) getSamplingTargets(ctx context.Context, s []*samplingStatisticsDocument) (*getSamplingTargetsOutput, error) {
statistics := getSamplingTargetsInput{
SamplingStatisticsDocuments: s,
}
statisticsByte, err := json.Marshal(statistics)
if err != nil {
return nil, err
}
body := bytes.NewReader(statisticsByte)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.samplingTargetsURL, body)
if err != nil {
return nil, fmt.Errorf("xray client: failed to create http request: %w", err)
}
output, err := c.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("xray client: unable to retrieve sampling settings: %w", err)
}
defer output.Body.Close()
var samplingTargetsOutput *getSamplingTargetsOutput
if err := json.NewDecoder(output.Body).Decode(&samplingTargetsOutput); err != nil {
return nil, fmt.Errorf("xray client: unable to unmarshal the response body: %w", err)
}
return samplingTargetsOutput, nil
}