Skip to content

Commit 782398a

Browse files
seiffertpatryk
authored andcommitted
Add partial support for VirtualDNS analytics (cloudflare#183)
* Add support for Virtual DNS user analytics
1 parent 1dc2b6e commit 782398a

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed

virtualdns.go

+65
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package cloudflare
22

33
import (
44
"encoding/json"
5+
"net/url"
6+
"strings"
7+
"time"
58

69
"github.com/pkg/errors"
710
)
@@ -18,6 +21,31 @@ type VirtualDNS struct {
1821
ModifiedOn string `json:"modified_on"`
1922
}
2023

24+
// VirtualDNSAnalyticsMetrics respresents a group of aggregated Virtual DNS metrics.
25+
type VirtualDNSAnalyticsMetrics struct {
26+
QueryCount *int64 `json:"queryCount"`
27+
UncachedCount *int64 `json:"uncachedCount"`
28+
StaleCount *int64 `json:"staleCount"`
29+
ResponseTimeAvg *float64 `json:"responseTimeAvg"`
30+
ResponseTimeMedian *float64 `json:"responseTimeMedian"`
31+
ResponseTime90th *float64 `json:"responseTime90th"`
32+
ResponseTime99th *float64 `json:"responseTime99th"`
33+
}
34+
35+
// VirtualDNSAnalytics represents a set of aggregated Virtual DNS metrics.
36+
// TODO: Add the queried data and not only the aggregated values.
37+
type VirtualDNSAnalytics struct {
38+
Totals VirtualDNSAnalyticsMetrics `json:"totals"`
39+
Min VirtualDNSAnalyticsMetrics `json:"min"`
40+
Max VirtualDNSAnalyticsMetrics `json:"max"`
41+
}
42+
43+
type VirtualDNSUserAnalyticsOptions struct {
44+
Metrics []string
45+
Since *time.Time
46+
Until *time.Time
47+
}
48+
2149
// VirtualDNSResponse represents a Virtual DNS response.
2250
type VirtualDNSResponse struct {
2351
Response
@@ -30,6 +58,12 @@ type VirtualDNSListResponse struct {
3058
Result []*VirtualDNS `json:"result"`
3159
}
3260

61+
// VirtualDNSAnalyticsResponse represents a Virtual DNS analytics response.
62+
type VirtualDNSAnalyticsResponse struct {
63+
Response
64+
Result VirtualDNSAnalytics `json:"result"`
65+
}
66+
3367
// CreateVirtualDNS creates a new Virtual DNS cluster.
3468
//
3569
// API reference: https://api.cloudflare.com/#virtual-dns-users--create-a-virtual-dns-cluster
@@ -123,3 +157,34 @@ func (api *API) DeleteVirtualDNS(virtualDNSID string) error {
123157

124158
return nil
125159
}
160+
161+
// encode encodes non-nil fields into URL encoded form.
162+
func (o VirtualDNSUserAnalyticsOptions) encode() string {
163+
v := url.Values{}
164+
if o.Since != nil {
165+
v.Set("since", (*o.Since).UTC().Format(time.RFC3339))
166+
}
167+
if o.Until != nil {
168+
v.Set("until", (*o.Until).UTC().Format(time.RFC3339))
169+
}
170+
if o.Metrics != nil {
171+
v.Set("metrics", strings.Join(o.Metrics, ","))
172+
}
173+
return v.Encode()
174+
}
175+
176+
func (api *API) VirtualDNSUserAnalytics(virtualDNSID string, o VirtualDNSUserAnalyticsOptions) (VirtualDNSAnalytics, error) {
177+
uri := "/user/virtual_dns/" + virtualDNSID + "/dns_analytics/report?" + o.encode()
178+
res, err := api.makeRequest("GET", uri, nil)
179+
if err != nil {
180+
return VirtualDNSAnalytics{}, errors.Wrap(err, errMakeRequestError)
181+
}
182+
183+
response := VirtualDNSAnalyticsResponse{}
184+
err = json.Unmarshal(res, &response)
185+
if err != nil {
186+
return VirtualDNSAnalytics{}, errors.Wrap(err, errUnmarshalError)
187+
}
188+
189+
return response.Result, nil
190+
}

virtualdns_test.go

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package cloudflare
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"testing"
7+
"time"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func float64Ptr(v float64) *float64 {
13+
return &v
14+
}
15+
16+
func int64Ptr(v int64) *int64 {
17+
return &v
18+
}
19+
20+
func TestVirtualDNSUserAnalytics(t *testing.T) {
21+
setup()
22+
defer teardown()
23+
24+
since := time.Now().Add(-1 * time.Hour)
25+
until := time.Now()
26+
27+
handler := func(w http.ResponseWriter, r *http.Request) {
28+
expectedMetrics := "queryCount,uncachedCount,staleCount,responseTimeAvg,responseTimeMedia,responseTime90th,responseTime99th"
29+
30+
assert.Equal(t, r.Method, "GET", "Expected method 'GET'")
31+
assert.Equal(t, expectedMetrics, r.URL.Query().Get("metrics"), "Expected many metrics in URL parameter")
32+
assert.Equal(t, since.Format(time.RFC3339), r.URL.Query().Get("since"), "Expected since parameter in URL")
33+
assert.Equal(t, until.Format(time.RFC3339), r.URL.Query().Get("until"), "Expected until parameter in URL")
34+
35+
w.Header().Set("content-type", "application/json")
36+
fmt.Fprint(w, `{
37+
"result": {
38+
"totals":{
39+
"queryCount": 5,
40+
"uncachedCount":6,
41+
"staleCount":7,
42+
"responseTimeAvg":1.0,
43+
"responseTimeMedian":2.0,
44+
"responseTime90th":3.0,
45+
"responseTime99th":4.0
46+
}
47+
},
48+
"success": true,
49+
"errors": null,
50+
"messages": null
51+
}`)
52+
}
53+
54+
mux.HandleFunc("/user/virtual_dns/12345/dns_analytics/report", handler)
55+
want := VirtualDNSAnalytics{
56+
Totals: VirtualDNSAnalyticsMetrics{
57+
QueryCount: int64Ptr(5),
58+
UncachedCount: int64Ptr(6),
59+
StaleCount: int64Ptr(7),
60+
ResponseTimeAvg: float64Ptr(1.0),
61+
ResponseTimeMedian: float64Ptr(2.0),
62+
ResponseTime90th: float64Ptr(3.0),
63+
ResponseTime99th: float64Ptr(4.0),
64+
},
65+
}
66+
67+
params := VirtualDNSUserAnalyticsOptions{
68+
Metrics: []string{
69+
"queryCount",
70+
"uncachedCount",
71+
"staleCount",
72+
"responseTimeAvg",
73+
"responseTimeMedia",
74+
"responseTime90th",
75+
"responseTime99th",
76+
},
77+
Since: &since,
78+
Until: &until,
79+
}
80+
actual, err := client.VirtualDNSUserAnalytics("12345", params)
81+
if assert.NoError(t, err) {
82+
assert.Equal(t, want, actual)
83+
}
84+
}

0 commit comments

Comments
 (0)