Skip to content

Commit a86355b

Browse files
CLOUDP-72746: Add Performance Advisor API call to atlas go client (#137)
1 parent a4f9004 commit a86355b

File tree

4 files changed

+448
-2
lines changed

4 files changed

+448
-2
lines changed

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3-
github.com/go-test/deep v1.0.1 h1:UQhStjbkDClarlmv0am7OXXO4/GaPdCGiUiMTvi28sg=
4-
github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
53
github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M=
64
github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
75
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=

mongodbatlas/mongodbatlas.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ type Client struct {
106106
CustomAWSDNS AWSCustomDNSService
107107
Integrations IntegrationsService
108108
LDAPConfigurations LDAPConfigurationsService
109+
PerformanceAdvisor PerformanceAdvisorService
109110

110111
onRequestCompleted RequestCompletionCallback
111112
}
@@ -243,6 +244,7 @@ func NewClient(httpClient *http.Client) *Client {
243244
c.CustomAWSDNS = &AWSCustomDNSServiceOp{Client: c}
244245
c.Integrations = &IntegrationsServiceOp{Client: c}
245246
c.LDAPConfigurations = &LDAPConfigurationsServiceOp{Client: c}
247+
c.PerformanceAdvisor = &PerformanceAdvisorServiceOp{Client: c}
246248

247249
return c
248250
}
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
package mongodbatlas
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
)
8+
9+
const (
10+
performanceAdvisorPath = "groups/%s/processes/%s/performanceAdvisor"
11+
performanceAdvisorNamespacesPath = performanceAdvisorPath + "/namespaces"
12+
performanceAdvisorSlowQueryLogsPath = performanceAdvisorPath + "/slowQueryLogs"
13+
performanceAdvisorSuggestedIndexesLogsPath = performanceAdvisorPath + "/suggestedIndexes"
14+
)
15+
16+
// PerformanceAdvisorService is an interface of the Performance Advisor
17+
// endpoints of the MongoDB Atlas API.
18+
//
19+
// See more: https://docs.atlas.mongodb.com/reference/api/performance-advisor/
20+
type PerformanceAdvisorService interface {
21+
GetNamespaces(context.Context, string, string, *NamespaceOptions) (*Namespaces, *Response, error)
22+
GetSlowQueries(context.Context, string, string, *SlowQueryOptions) (*SlowQueries, *Response, error)
23+
GetSuggestedIndexes(context.Context, string, string, *SuggestedIndexOptions) (*SuggestedIndexes, *Response, error)
24+
}
25+
26+
// PerformanceAdvisorServiceOp handles communication with the Performance Advisor related methods of the MongoDB Atlas API
27+
type PerformanceAdvisorServiceOp service
28+
29+
var _ PerformanceAdvisorService = &PerformanceAdvisorServiceOp{}
30+
31+
// Namespace represents a Namespace.
32+
type Namespace struct {
33+
Namespace string `json:"namespace,omitempty"` // A namespace on the specified host.
34+
Type string `json:"type,omitempty"` // The type of namespace.
35+
}
36+
37+
// Namespaces represents a list of Namespace.
38+
type Namespaces struct {
39+
Namespaces []*Namespace `json:"namespaces,omitempty"`
40+
}
41+
42+
// SlowQuery represents a slow query.
43+
type SlowQuery struct {
44+
Namespace string `json:"namespace,omitempty"` // The namespace in which the slow query ran.
45+
Line string `json:"line,omitempty"` // The raw log line pertaining to the slow query.
46+
}
47+
48+
// SlowQueries represents a list of SlowQuery.
49+
type SlowQueries struct {
50+
SlowQuery []*SlowQuery `json:"slowQueries,omitempty"` // A list of documents with information about slow queries as detected by the Performance Advisor.
51+
}
52+
53+
// Shape represents a document with information about the query shapes that are served by the suggested indexes.
54+
type Shape struct {
55+
AvgMs float64 `json:"avgMs,omitempty"` // Average duration in milliseconds for the queries examined that match this shape.
56+
Count int64 `json:"count,omitempty"` // Number of queries examined that match this shape.
57+
ID string `json:"id,omitempty"` // Unique id for this shape. Exists only for the duration of the API request.
58+
InefficiencyScore int64 `json:"inefficiencyScore,omitempty"` // Average number of documents read for every document returned by the query.
59+
Namespace string `json:"namespace,omitempty"` // The namespace in which the slow query ran.
60+
Operations []*Operation `json:"operations,omitempty"` // It represents documents with specific information and log lines for individual queries.
61+
}
62+
63+
// Operation represents a document with specific information and log lines for individual queries.
64+
type Operation struct {
65+
Raw string `json:"raw,omitempty"` // Raw log line produced by the query.
66+
Stats Stats `json:"stats,omitempty"` // Query statistics.
67+
Predicates []map[string]map[string]string `json:"predicates,omitempty"` // Documents containing the search criteria used by the query.
68+
}
69+
70+
// Stats represents query statistics.
71+
type Stats struct {
72+
MS float64 `json:"ms,omitempty"` // Duration in milliseconds of the query.
73+
NReturned int64 `json:"nReturned,omitempty"` // Number of results returned by the query.
74+
NScanned int64 `json:"nScanned,omitempty"` // Number of documents read by the query.
75+
TS int64 `json:"ts,omitempty"` // Query timestamp, in seconds since epoch.
76+
}
77+
78+
// SuggestedIndex represents a suggested index.
79+
type SuggestedIndex struct {
80+
ID string `json:"id,omitempty"` // Unique id for this suggested index.
81+
Impact []string `json:"impact,omitempty"` // List of unique identifiers which correspond the query shapes in this response which pertain to this suggested index.
82+
Namespace string `json:"namespace,omitempty"` // Namespace of the suggested index.
83+
Weight float64 `json:"weight,omitempty"` // Estimated percentage performance improvement that the suggested index would provide.
84+
Index []map[string]int `json:"index,omitempty"` // Array of documents that specifies a key in the index and its sort order, ascending or descending.
85+
}
86+
87+
// SuggestedIndexes represents an array of suggested indexes.
88+
type SuggestedIndexes struct {
89+
SuggestedIndexes []*SuggestedIndex `json:"suggestedIndexes,omitempty"` // Documents with information about the indexes suggested by the Performance Advisor.
90+
Shapes []*Shape `json:"shapes,omitempty"` // Documents with information about the query shapes that are served by the suggested indexes.
91+
92+
}
93+
94+
// SlowQueryOptions contains the request query parameters for the API request.
95+
type SlowQueryOptions struct {
96+
Namespaces string `url:"namespaces,omitempty"` // Namespaces from which to retrieve slow query logs. A namespace consists of the database and collection resource separated by a ., such as <database>.<collection>.
97+
NLogs int64 `url:"nLogs,omitempty"` // Maximum number of log lines to return. Defaults to 20000.
98+
NamespaceOptions
99+
}
100+
101+
// NamespaceOptions contains the request query parameters for the API request.
102+
type NamespaceOptions struct {
103+
Since int64 `url:"since,omitempty"` // Point in time, specified as milliseconds since the Unix Epoch, from which you want to receive results.
104+
Duration int64 `url:"duration,omitempty"` // Length of time from the since parameter, in milliseconds, for which you want to receive results.
105+
}
106+
107+
// SuggestedIndexOptions contains the request query parameters for the API request.
108+
type SuggestedIndexOptions struct {
109+
Namespaces string `url:"namespaces,omitempty"` // Namespaces from which to retrieve slow query logs. A namespace consists of the database and collection resource separated by a ., such as <database>.<collection>.
110+
NIndexes int64 `url:"nIndexes,omitempty"` // Maximum number of indexes to suggest. Defaults to unlimited.
111+
NExamples int64 `url:"NExamples,omitempty"` // Maximum number of examples queries to provide that will be improved by a suggested index. Defaults to 5.
112+
NamespaceOptions
113+
}
114+
115+
// GetNamespaces retrieves the namespaces for collections experiencing slow queries for a specified host.
116+
//
117+
// See more: https://docs.atlas.mongodb.com/reference/api/pa-namespaces-get-all/
118+
func (s *PerformanceAdvisorServiceOp) GetNamespaces(ctx context.Context, groupID, processName string, opts *NamespaceOptions) (*Namespaces, *Response, error) {
119+
if groupID == "" {
120+
return nil, nil, NewArgError("groupID", "must be set")
121+
}
122+
123+
if processName == "" {
124+
return nil, nil, NewArgError("processName", "must be set")
125+
}
126+
127+
path := fmt.Sprintf(performanceAdvisorNamespacesPath, groupID, processName)
128+
path, err := setListOptions(path, opts)
129+
if err != nil {
130+
return nil, nil, err
131+
}
132+
133+
req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil)
134+
if err != nil {
135+
return nil, nil, err
136+
}
137+
138+
root := new(Namespaces)
139+
resp, err := s.Client.Do(ctx, req, root)
140+
if err != nil {
141+
return nil, resp, err
142+
}
143+
144+
return root, resp, err
145+
}
146+
147+
// GetSlowQueries gets log lines for slow queries as determined by the Performance Advisor.
148+
//
149+
// See more: https://docs.atlas.mongodb.com/reference/api/pa-get-slow-query-logs/
150+
func (s *PerformanceAdvisorServiceOp) GetSlowQueries(ctx context.Context, groupID, processName string, opts *SlowQueryOptions) (*SlowQueries, *Response, error) {
151+
if groupID == "" {
152+
return nil, nil, NewArgError("groupID", "must be set")
153+
}
154+
155+
if processName == "" {
156+
return nil, nil, NewArgError("processName", "must be set")
157+
}
158+
159+
path := fmt.Sprintf(performanceAdvisorSlowQueryLogsPath, groupID, processName)
160+
path, err := setListOptions(path, opts)
161+
if err != nil {
162+
return nil, nil, err
163+
}
164+
165+
req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil)
166+
if err != nil {
167+
return nil, nil, err
168+
}
169+
170+
root := new(SlowQueries)
171+
resp, err := s.Client.Do(ctx, req, root)
172+
if err != nil {
173+
return nil, resp, err
174+
}
175+
176+
return root, resp, err
177+
}
178+
179+
// GetSuggestedIndexes gets suggested indexes as determined by the Performance Advisor.
180+
//
181+
// See more: https://docs.atlas.mongodb.com/reference/api/pa-suggested-indexes-get-all/
182+
func (s *PerformanceAdvisorServiceOp) GetSuggestedIndexes(ctx context.Context, groupID, processName string, opts *SuggestedIndexOptions) (*SuggestedIndexes, *Response, error) {
183+
if groupID == "" {
184+
return nil, nil, NewArgError("groupID", "must be set")
185+
}
186+
187+
if processName == "" {
188+
return nil, nil, NewArgError("processName", "must be set")
189+
}
190+
191+
path := fmt.Sprintf(performanceAdvisorSuggestedIndexesLogsPath, groupID, processName)
192+
path, err := setListOptions(path, opts)
193+
if err != nil {
194+
return nil, nil, err
195+
}
196+
197+
req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil)
198+
if err != nil {
199+
return nil, nil, err
200+
}
201+
202+
root := new(SuggestedIndexes)
203+
resp, err := s.Client.Do(ctx, req, root)
204+
if err != nil {
205+
return nil, resp, err
206+
}
207+
208+
return root, resp, err
209+
}

0 commit comments

Comments
 (0)