environment metrics handler (#319)

This commit is contained in:
Michael Quigley 2023-05-09 16:36:50 -04:00
parent 9f29bb59c7
commit 02c996b545
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
11 changed files with 458 additions and 12 deletions

View File

@ -71,6 +71,81 @@ func (h *getAccountMetricsHandler) Handle(params metadata.GetAccountMetricsParam
return metadata.NewGetAccountMetricsOK().WithPayload(response)
}
type getEnvironmentMetricsHandler struct {
cfg *metrics.InfluxConfig
idb influxdb2.Client
queryApi api.QueryAPI
}
func newGetEnvironmentMetricsHAndler(cfg *metrics.InfluxConfig) *getEnvironmentMetricsHandler {
idb := influxdb2.NewClient(cfg.Url, cfg.Token)
queryApi := idb.QueryAPI(cfg.Org)
return &getEnvironmentMetricsHandler{
cfg: cfg,
idb: idb,
queryApi: queryApi,
}
}
func (h *getEnvironmentMetricsHandler) Handle(params metadata.GetEnvironmentMetricsParams, principal *rest_model_zrok.Principal) middleware.Responder {
trx, err := str.Begin()
if err != nil {
logrus.Errorf("error starting transaction: %v", err)
return metadata.NewGetEnvironmentMetricsInternalServerError()
}
defer func() { _ = trx.Rollback() }()
env, err := str.GetEnvironment(int(params.EnvID), trx)
if err != nil {
logrus.Errorf("error finding environment '%d': %v", int(params.EnvID), err)
return metadata.NewGetEnvironmentMetricsUnauthorized()
}
if int64(env.Id) != principal.ID {
logrus.Errorf("unauthorized environemnt '%d' for '%v'", int(params.EnvID), principal.Email)
return metadata.NewGetEnvironmentMetricsUnauthorized()
}
duration := 30 * 24 * time.Hour
if params.Duration != nil {
v, err := time.ParseDuration(*params.Duration)
if err != nil {
logrus.Errorf("bad duration '%v' for '%v': %v", params.Duration, principal.Email, err)
return metadata.NewGetAccountMetricsBadRequest()
}
duration = v
}
slice := duration / 200
query := fmt.Sprintf("from(bucket: \"%v\")\n", h.cfg.Bucket) +
fmt.Sprintf("|> range(start: -%v)\n", duration) +
"|> filter(fn: (r) => r[\"_measurement\"] == \"xfer\")\n" +
"|> filter(fn: (r) => r[\"_field\"] == \"rx\" or r[\"_field\"] == \"tx\")\n" +
"|> filter(fn: (r) => r[\"namespace\"] == \"backend\")\n" +
fmt.Sprintf("|> filter(fn: (r) => r[\"envId\"] == \"%d\")\n", int64(env.Id)) +
"|> drop(columns: [\"share\", \"acctId\"])\n" +
fmt.Sprintf("|> aggregateWindow(every: %v, fn: sum, createEmpty: true)", slice)
rx, tx, timestamps, err := runFluxForRxTxArray(query, h.queryApi)
if err != nil {
logrus.Errorf("error running account metrics query for '%v': %v", principal.Email, err)
return metadata.NewGetAccountMetricsInternalServerError()
}
response := &rest_model_zrok.Metrics{
Scope: "account",
ID: fmt.Sprintf("%d", principal.ID),
Period: duration.Seconds(),
}
for i := 0; i < len(rx) && i < len(tx) && i < len(timestamps); i++ {
response.Samples = append(response.Samples, &rest_model_zrok.MetricsSample{
Rx: rx[i],
Tx: tx[i],
Timestamp: timestamps[i],
})
}
return metadata.NewGetEnvironmentMetricsOK().WithPayload(response)
}
func runFluxForRxTxArray(query string, queryApi api.QueryAPI) (rx, tx, timestamps []float64, err error) {
result, err := queryApi.Query(context.Background(), query)
if err != nil {

View File

@ -14,6 +14,7 @@ import (
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// NewGetEnvironmentMetricsParams creates a new GetEnvironmentMetricsParams object,
@ -65,7 +66,7 @@ type GetEnvironmentMetricsParams struct {
Duration *string
// EnvID.
EnvID string
EnvID float64
timeout time.Duration
Context context.Context
@ -132,13 +133,13 @@ func (o *GetEnvironmentMetricsParams) SetDuration(duration *string) {
}
// WithEnvID adds the envID to the get environment metrics params
func (o *GetEnvironmentMetricsParams) WithEnvID(envID string) *GetEnvironmentMetricsParams {
func (o *GetEnvironmentMetricsParams) WithEnvID(envID float64) *GetEnvironmentMetricsParams {
o.SetEnvID(envID)
return o
}
// SetEnvID adds the envId to the get environment metrics params
func (o *GetEnvironmentMetricsParams) SetEnvID(envID string) {
func (o *GetEnvironmentMetricsParams) SetEnvID(envID float64) {
o.EnvID = envID
}
@ -168,7 +169,7 @@ func (o *GetEnvironmentMetricsParams) WriteToRequest(r runtime.ClientRequest, re
}
// path param envId
if err := r.SetPathParam("envId", o.EnvID); err != nil {
if err := r.SetPathParam("envId", swag.FormatFloat64(o.EnvID)); err != nil {
return err
}

View File

@ -29,12 +29,24 @@ func (o *GetEnvironmentMetricsReader) ReadResponse(response runtime.ClientRespon
return nil, err
}
return result, nil
case 400:
result := NewGetEnvironmentMetricsBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 401:
result := NewGetEnvironmentMetricsUnauthorized()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 500:
result := NewGetEnvironmentMetricsInternalServerError()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@ -103,6 +115,57 @@ func (o *GetEnvironmentMetricsOK) readResponse(response runtime.ClientResponse,
return nil
}
// NewGetEnvironmentMetricsBadRequest creates a GetEnvironmentMetricsBadRequest with default headers values
func NewGetEnvironmentMetricsBadRequest() *GetEnvironmentMetricsBadRequest {
return &GetEnvironmentMetricsBadRequest{}
}
/*
GetEnvironmentMetricsBadRequest describes a response with status code 400, with default header values.
bad request
*/
type GetEnvironmentMetricsBadRequest struct {
}
// IsSuccess returns true when this get environment metrics bad request response has a 2xx status code
func (o *GetEnvironmentMetricsBadRequest) IsSuccess() bool {
return false
}
// IsRedirect returns true when this get environment metrics bad request response has a 3xx status code
func (o *GetEnvironmentMetricsBadRequest) IsRedirect() bool {
return false
}
// IsClientError returns true when this get environment metrics bad request response has a 4xx status code
func (o *GetEnvironmentMetricsBadRequest) IsClientError() bool {
return true
}
// IsServerError returns true when this get environment metrics bad request response has a 5xx status code
func (o *GetEnvironmentMetricsBadRequest) IsServerError() bool {
return false
}
// IsCode returns true when this get environment metrics bad request response a status code equal to that given
func (o *GetEnvironmentMetricsBadRequest) IsCode(code int) bool {
return code == 400
}
func (o *GetEnvironmentMetricsBadRequest) Error() string {
return fmt.Sprintf("[GET /metrics/environment/{envId}][%d] getEnvironmentMetricsBadRequest ", 400)
}
func (o *GetEnvironmentMetricsBadRequest) String() string {
return fmt.Sprintf("[GET /metrics/environment/{envId}][%d] getEnvironmentMetricsBadRequest ", 400)
}
func (o *GetEnvironmentMetricsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewGetEnvironmentMetricsUnauthorized creates a GetEnvironmentMetricsUnauthorized with default headers values
func NewGetEnvironmentMetricsUnauthorized() *GetEnvironmentMetricsUnauthorized {
return &GetEnvironmentMetricsUnauthorized{}
@ -153,3 +216,54 @@ func (o *GetEnvironmentMetricsUnauthorized) readResponse(response runtime.Client
return nil
}
// NewGetEnvironmentMetricsInternalServerError creates a GetEnvironmentMetricsInternalServerError with default headers values
func NewGetEnvironmentMetricsInternalServerError() *GetEnvironmentMetricsInternalServerError {
return &GetEnvironmentMetricsInternalServerError{}
}
/*
GetEnvironmentMetricsInternalServerError describes a response with status code 500, with default header values.
internal server error
*/
type GetEnvironmentMetricsInternalServerError struct {
}
// IsSuccess returns true when this get environment metrics internal server error response has a 2xx status code
func (o *GetEnvironmentMetricsInternalServerError) IsSuccess() bool {
return false
}
// IsRedirect returns true when this get environment metrics internal server error response has a 3xx status code
func (o *GetEnvironmentMetricsInternalServerError) IsRedirect() bool {
return false
}
// IsClientError returns true when this get environment metrics internal server error response has a 4xx status code
func (o *GetEnvironmentMetricsInternalServerError) IsClientError() bool {
return false
}
// IsServerError returns true when this get environment metrics internal server error response has a 5xx status code
func (o *GetEnvironmentMetricsInternalServerError) IsServerError() bool {
return true
}
// IsCode returns true when this get environment metrics internal server error response a status code equal to that given
func (o *GetEnvironmentMetricsInternalServerError) IsCode(code int) bool {
return code == 500
}
func (o *GetEnvironmentMetricsInternalServerError) Error() string {
return fmt.Sprintf("[GET /metrics/environment/{envId}][%d] getEnvironmentMetricsInternalServerError ", 500)
}
func (o *GetEnvironmentMetricsInternalServerError) String() string {
return fmt.Sprintf("[GET /metrics/environment/{envId}][%d] getEnvironmentMetricsInternalServerError ", 500)
}
func (o *GetEnvironmentMetricsInternalServerError) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}

View File

@ -29,12 +29,24 @@ func (o *GetShareMetricsReader) ReadResponse(response runtime.ClientResponse, co
return nil, err
}
return result, nil
case 400:
result := NewGetShareMetricsBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 401:
result := NewGetShareMetricsUnauthorized()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 500:
result := NewGetShareMetricsInternalServerError()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@ -103,6 +115,57 @@ func (o *GetShareMetricsOK) readResponse(response runtime.ClientResponse, consum
return nil
}
// NewGetShareMetricsBadRequest creates a GetShareMetricsBadRequest with default headers values
func NewGetShareMetricsBadRequest() *GetShareMetricsBadRequest {
return &GetShareMetricsBadRequest{}
}
/*
GetShareMetricsBadRequest describes a response with status code 400, with default header values.
bad request
*/
type GetShareMetricsBadRequest struct {
}
// IsSuccess returns true when this get share metrics bad request response has a 2xx status code
func (o *GetShareMetricsBadRequest) IsSuccess() bool {
return false
}
// IsRedirect returns true when this get share metrics bad request response has a 3xx status code
func (o *GetShareMetricsBadRequest) IsRedirect() bool {
return false
}
// IsClientError returns true when this get share metrics bad request response has a 4xx status code
func (o *GetShareMetricsBadRequest) IsClientError() bool {
return true
}
// IsServerError returns true when this get share metrics bad request response has a 5xx status code
func (o *GetShareMetricsBadRequest) IsServerError() bool {
return false
}
// IsCode returns true when this get share metrics bad request response a status code equal to that given
func (o *GetShareMetricsBadRequest) IsCode(code int) bool {
return code == 400
}
func (o *GetShareMetricsBadRequest) Error() string {
return fmt.Sprintf("[GET /metrics/share/{shrToken}][%d] getShareMetricsBadRequest ", 400)
}
func (o *GetShareMetricsBadRequest) String() string {
return fmt.Sprintf("[GET /metrics/share/{shrToken}][%d] getShareMetricsBadRequest ", 400)
}
func (o *GetShareMetricsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewGetShareMetricsUnauthorized creates a GetShareMetricsUnauthorized with default headers values
func NewGetShareMetricsUnauthorized() *GetShareMetricsUnauthorized {
return &GetShareMetricsUnauthorized{}
@ -153,3 +216,54 @@ func (o *GetShareMetricsUnauthorized) readResponse(response runtime.ClientRespon
return nil
}
// NewGetShareMetricsInternalServerError creates a GetShareMetricsInternalServerError with default headers values
func NewGetShareMetricsInternalServerError() *GetShareMetricsInternalServerError {
return &GetShareMetricsInternalServerError{}
}
/*
GetShareMetricsInternalServerError describes a response with status code 500, with default header values.
internal server error
*/
type GetShareMetricsInternalServerError struct {
}
// IsSuccess returns true when this get share metrics internal server error response has a 2xx status code
func (o *GetShareMetricsInternalServerError) IsSuccess() bool {
return false
}
// IsRedirect returns true when this get share metrics internal server error response has a 3xx status code
func (o *GetShareMetricsInternalServerError) IsRedirect() bool {
return false
}
// IsClientError returns true when this get share metrics internal server error response has a 4xx status code
func (o *GetShareMetricsInternalServerError) IsClientError() bool {
return false
}
// IsServerError returns true when this get share metrics internal server error response has a 5xx status code
func (o *GetShareMetricsInternalServerError) IsServerError() bool {
return true
}
// IsCode returns true when this get share metrics internal server error response a status code equal to that given
func (o *GetShareMetricsInternalServerError) IsCode(code int) bool {
return code == 500
}
func (o *GetShareMetricsInternalServerError) Error() string {
return fmt.Sprintf("[GET /metrics/share/{shrToken}][%d] getShareMetricsInternalServerError ", 500)
}
func (o *GetShareMetricsInternalServerError) String() string {
return fmt.Sprintf("[GET /metrics/share/{shrToken}][%d] getShareMetricsInternalServerError ", 500)
}
func (o *GetShareMetricsInternalServerError) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}

View File

@ -567,7 +567,7 @@ func init() {
"operationId": "getEnvironmentMetrics",
"parameters": [
{
"type": "string",
"type": "number",
"name": "envId",
"in": "path",
"required": true
@ -585,8 +585,14 @@ func init() {
"$ref": "#/definitions/metrics"
}
},
"400": {
"description": "bad request"
},
"401": {
"description": "unauthorized"
},
"500": {
"description": "internal server error"
}
}
}
@ -622,8 +628,14 @@ func init() {
"$ref": "#/definitions/metrics"
}
},
"400": {
"description": "bad request"
},
"401": {
"description": "unauthorized"
},
"500": {
"description": "internal server error"
}
}
}
@ -1991,7 +2003,7 @@ func init() {
"operationId": "getEnvironmentMetrics",
"parameters": [
{
"type": "string",
"type": "number",
"name": "envId",
"in": "path",
"required": true
@ -2009,8 +2021,14 @@ func init() {
"$ref": "#/definitions/metrics"
}
},
"400": {
"description": "bad request"
},
"401": {
"description": "unauthorized"
},
"500": {
"description": "internal server error"
}
}
}
@ -2046,8 +2064,14 @@ func init() {
"$ref": "#/definitions/metrics"
}
},
"400": {
"description": "bad request"
},
"401": {
"description": "unauthorized"
},
"500": {
"description": "internal server error"
}
}
}

View File

@ -12,6 +12,7 @@ import (
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// NewGetEnvironmentMetricsParams creates a new GetEnvironmentMetricsParams object
@ -39,7 +40,7 @@ type GetEnvironmentMetricsParams struct {
Required: true
In: path
*/
EnvID string
EnvID float64
}
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
@ -95,7 +96,12 @@ func (o *GetEnvironmentMetricsParams) bindEnvID(rawData []string, hasKey bool, f
// Required: true
// Parameter is provided by construction from the route
o.EnvID = raw
value, err := swag.ConvertFloat64(raw)
if err != nil {
return errors.InvalidType("envId", "path", "float64", raw)
}
o.EnvID = value
return nil
}

View File

@ -58,6 +58,31 @@ func (o *GetEnvironmentMetricsOK) WriteResponse(rw http.ResponseWriter, producer
}
}
// GetEnvironmentMetricsBadRequestCode is the HTTP code returned for type GetEnvironmentMetricsBadRequest
const GetEnvironmentMetricsBadRequestCode int = 400
/*
GetEnvironmentMetricsBadRequest bad request
swagger:response getEnvironmentMetricsBadRequest
*/
type GetEnvironmentMetricsBadRequest struct {
}
// NewGetEnvironmentMetricsBadRequest creates GetEnvironmentMetricsBadRequest with default headers values
func NewGetEnvironmentMetricsBadRequest() *GetEnvironmentMetricsBadRequest {
return &GetEnvironmentMetricsBadRequest{}
}
// WriteResponse to the client
func (o *GetEnvironmentMetricsBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
rw.WriteHeader(400)
}
// GetEnvironmentMetricsUnauthorizedCode is the HTTP code returned for type GetEnvironmentMetricsUnauthorized
const GetEnvironmentMetricsUnauthorizedCode int = 401
@ -82,3 +107,28 @@ func (o *GetEnvironmentMetricsUnauthorized) WriteResponse(rw http.ResponseWriter
rw.WriteHeader(401)
}
// GetEnvironmentMetricsInternalServerErrorCode is the HTTP code returned for type GetEnvironmentMetricsInternalServerError
const GetEnvironmentMetricsInternalServerErrorCode int = 500
/*
GetEnvironmentMetricsInternalServerError internal server error
swagger:response getEnvironmentMetricsInternalServerError
*/
type GetEnvironmentMetricsInternalServerError struct {
}
// NewGetEnvironmentMetricsInternalServerError creates GetEnvironmentMetricsInternalServerError with default headers values
func NewGetEnvironmentMetricsInternalServerError() *GetEnvironmentMetricsInternalServerError {
return &GetEnvironmentMetricsInternalServerError{}
}
// WriteResponse to the client
func (o *GetEnvironmentMetricsInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
rw.WriteHeader(500)
}

View File

@ -10,11 +10,13 @@ import (
"net/url"
golangswaggerpaths "path"
"strings"
"github.com/go-openapi/swag"
)
// GetEnvironmentMetricsURL generates an URL for the get environment metrics operation
type GetEnvironmentMetricsURL struct {
EnvID string
EnvID float64
Duration *string
@ -44,7 +46,7 @@ func (o *GetEnvironmentMetricsURL) Build() (*url.URL, error) {
var _path = "/metrics/environment/{envId}"
envID := o.EnvID
envID := swag.FormatFloat64(o.EnvID)
if envID != "" {
_path = strings.Replace(_path, "{envId}", envID, -1)
} else {

View File

@ -58,6 +58,31 @@ func (o *GetShareMetricsOK) WriteResponse(rw http.ResponseWriter, producer runti
}
}
// GetShareMetricsBadRequestCode is the HTTP code returned for type GetShareMetricsBadRequest
const GetShareMetricsBadRequestCode int = 400
/*
GetShareMetricsBadRequest bad request
swagger:response getShareMetricsBadRequest
*/
type GetShareMetricsBadRequest struct {
}
// NewGetShareMetricsBadRequest creates GetShareMetricsBadRequest with default headers values
func NewGetShareMetricsBadRequest() *GetShareMetricsBadRequest {
return &GetShareMetricsBadRequest{}
}
// WriteResponse to the client
func (o *GetShareMetricsBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
rw.WriteHeader(400)
}
// GetShareMetricsUnauthorizedCode is the HTTP code returned for type GetShareMetricsUnauthorized
const GetShareMetricsUnauthorizedCode int = 401
@ -82,3 +107,28 @@ func (o *GetShareMetricsUnauthorized) WriteResponse(rw http.ResponseWriter, prod
rw.WriteHeader(401)
}
// GetShareMetricsInternalServerErrorCode is the HTTP code returned for type GetShareMetricsInternalServerError
const GetShareMetricsInternalServerErrorCode int = 500
/*
GetShareMetricsInternalServerError internal server error
swagger:response getShareMetricsInternalServerError
*/
type GetShareMetricsInternalServerError struct {
}
// NewGetShareMetricsInternalServerError creates GetShareMetricsInternalServerError with default headers values
func NewGetShareMetricsInternalServerError() *GetShareMetricsInternalServerError {
return &GetShareMetricsInternalServerError{}
}
// WriteResponse to the client
func (o *GetShareMetricsInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
rw.WriteHeader(500)
}

View File

@ -425,7 +425,7 @@ paths:
parameters:
- name: envId
in: path
type: string
type: number
required: true
- name: duration
in: query
@ -435,8 +435,13 @@ paths:
description: environment metrics
schema:
$ref: "#/definitions/metrics"
400:
description: bad request
401:
description: unauthorized
500:
description: internal server error
/metrics/share/{shrToken}:
get:
@ -458,8 +463,13 @@ paths:
description: share metrics
schema:
$ref: "#/definitions/metrics"
400:
description: bad request
401:
description: unauthorized
500:
description: internal server error
/version:
get:

View File

@ -56,7 +56,7 @@ export function getAccountMetrics(options) {
}
/**
* @param {string} envId
* @param {number} envId
* @param {object} options Optional options
* @param {string} [options.duration]
* @return {Promise<module:types.metrics>} environment metrics