-
Notifications
You must be signed in to change notification settings - Fork 145
/
analytics.go
108 lines (87 loc) · 2.77 KB
/
analytics.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
package mailgun
import (
"context"
"strings"
"github.com/mailgun/errors"
)
type MetricsPagination struct {
// Colon-separated value indicating column name and sort direction e.g. 'domain:asc'.
Sort string `json:"sort"`
// The number of items to skip over when satisfying the request.
// To get the first page of data set skip to zero.
// Then increment the skip by the limit for subsequent calls.
Skip int `json:"skip"`
// The maximum number of items returned in the response.
Limit int `json:"limit"`
// The total number of items in the query result set.
Total int `json:"total"`
}
// ListMetrics returns domain/account metrics.
//
// NOTE: Only for v1 API. To use the /v1 version define MG_URL in the environment variable
// as `https://api.mailgun.net/v1` or set `mg.SetAPIBase("https://api.mailgun.net/v1")`
//
// https://documentation.mailgun.com/docs/mailgun/api-reference/openapi-final/tag/Metrics/
func (mg *MailgunImpl) ListMetrics(opts MetricsOptions) (*MetricsIterator, error) {
if !strings.HasSuffix(mg.APIBase(), "/v1") {
return nil, errors.New("only v1 API is supported")
}
domain := mg.Domain()
if domain != "" {
domainFilter := MetricsFilterPredicate{
Attribute: "domain",
Comparator: "=",
LabeledValues: []MetricsLabeledValue{{Label: domain, Value: domain}},
}
opts.Filter.BoolGroupAnd = append(opts.Filter.BoolGroupAnd, domainFilter)
}
if opts.Pagination.Limit == 0 {
opts.Pagination.Limit = 10
}
req := newHTTPRequest(generatePublicApiUrl(mg, metricsEndpoint))
req.setClient(mg.Client())
req.setBasicAuth(basicAuthUser, mg.APIKey())
return &MetricsIterator{
opts: opts,
req: req,
}, nil
}
type MetricsIterator struct {
opts MetricsOptions
req *httpRequest
err error
}
func (iter *MetricsIterator) Err() error {
return iter.err
}
// Next retrieves the next page of items from the api. Returns false when there are
// no more pages to retrieve or if there was an error.
// Use `.Err()` to retrieve the error
func (iter *MetricsIterator) Next(ctx context.Context, resp *MetricsResponse) (more bool) {
if iter.err != nil {
return false
}
iter.err = iter.fetch(ctx, resp)
if iter.err != nil {
return false
}
iter.opts.Pagination.Skip = iter.opts.Pagination.Skip + iter.opts.Pagination.Limit
return len(resp.Items) == iter.opts.Pagination.Limit
}
func (iter *MetricsIterator) fetch(ctx context.Context, resp *MetricsResponse) error {
if resp == nil {
return errors.New("resp cannot be nil")
}
payload := newJSONEncodedPayload(iter.opts)
httpResp, err := makePostRequest(ctx, iter.req, payload)
if err != nil {
return err
}
// preallocate
resp.Items = make([]MetricsItem, 0, iter.opts.Pagination.Limit)
err = httpResp.parseFromJSON(resp)
if err != nil {
return errors.Wrap(err, "decoding response")
}
return nil
}