Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/YaleSpinup/cost-api into …
Browse files Browse the repository at this point in the history
…DocumentDBmetric
  • Loading branch information
nvnyale committed Nov 14, 2022
2 parents b207c97 + ffcc966 commit ba5ac5c
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
84 changes: 84 additions & 0 deletions api/handlers_metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,90 @@ func (s *server) GetDocDBMetricsURLHandler(w http.ResponseWriter, r *http.Reques
w.Write(meta)
}

func (s *server) GetDataSyncMetricsURLHandler(w http.ResponseWriter, r *http.Request) {
w = LogWriter{w}
vars := mux.Vars(r)
account := s.mapAccountNumber(vars["account"])
taskId := vars["taskId"]

policy, err := defaultCloudWatchMetricsPolicy()
if err != nil {
handleError(w, err)
return
}

role := fmt.Sprintf("arn:aws:iam::%s:role/%s", account, s.session.RoleName)
session, err := s.assumeRole(
r.Context(),
s.session.ExternalID,
role,
policy,
)
if err != nil {
msg := fmt.Sprintf("failed to assume role in account: %s", account)
handleError(w, apierror.New(apierror.ErrForbidden, msg, nil))
return
}

cwService := cloudwatch.New(cloudwatch.WithSession(session.Session))

queries := r.URL.Query()
metrics := queries["metric"]
if len(metrics) == 0 {
handleError(w, apierror.New(apierror.ErrBadRequest, "at least one metric is required", nil))
return
}

req := cloudwatch.MetricsRequest{}
if err := parseQuery(r, req); err != nil {
handleError(w, apierror.New(apierror.ErrBadRequest, "failed to parse query", err))
return
}

key := fmt.Sprintf("%s/%s/%s/%s%s", account, s.org, taskId, strings.Join(metrics, "-"), req.String())
log.Debugf("object key: %s", key)

hashedCacheKey := s.imageCache.HashedKey(key)
if res, expire, ok := s.resultCache.GetWithExpiration(hashedCacheKey); ok {
log.Debugf("found cached object: %s", res)

if body, ok := res.([]byte); ok {
w.Header().Set("X-Cache-Hit", "true")
w.Header().Set("X-Cache-Expire", fmt.Sprintf("%0.fs", time.Until(expire).Seconds()))
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(body)
return
}
}

cwMetrics := []cloudwatch.Metric{}
for _, m := range metrics {
cwMetrics = append(cwMetrics, cloudwatch.Metric{"AWS/DataSync", m, "TaskId", taskId})
}
req["metrics"] = cwMetrics

log.Debugf("getting metrics with request %+v", req)
image, err := cwService.GetMetricWidget(r.Context(), req)
if err != nil {
log.Errorf("failed getting metrics widget image: %s", err)
handleError(w, err)
return
}

meta, err := s.imageCache.Save(r.Context(), hashedCacheKey, image)
if err != nil {
log.Errorf("failed saving metrics widget image to cache: %s", err)
handleError(w, err)
return
}
s.resultCache.Set(hashedCacheKey, meta, 300*time.Second)

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(meta)
}

func parseQuery(r *http.Request, request cloudwatch.MetricsRequest) error {
log.SetLevel(log.DebugLevel)
queries := r.URL.Query()
Expand Down
2 changes: 2 additions & 0 deletions api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ func (s *server) routes() {
metricsApi.HandleFunc("/{account}/rds/{type}/{id}/graph", s.GetRDSMetricsURLHandler).Methods(http.MethodGet)
// metrics endpoints for DocumentDB services
metricsApi.HandleFunc("/{account}/docdb/{type}/{id}/graph", s.GetDocDBMetricsURLHandler).Methods(http.MethodGet)
// metrics endpoints for DataSync services
metricsApi.HandleFunc("/{account}/movers/{taskId}/graph", s.GetDataSyncMetricsURLHandler).Methods(http.MethodGet)

inventoryApi := s.router.PathPrefix("/v1/inventory").Subrouter()
inventoryApi.HandleFunc("/ping", s.PingHandler).Methods(http.MethodGet)
Expand Down

0 comments on commit ba5ac5c

Please sign in to comment.