github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/edgeworkers/report.go (about)

     1  package edgeworkers
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  	"net/url"
     9  
    10  	validation "github.com/go-ozzo/ozzo-validation/v4"
    11  )
    12  
    13  type (
    14  	// Reports is an edgeworkers reports API interface
    15  	Reports interface {
    16  		// GetSummaryReport gets summary overview for EdgeWorker reports. Report id is  1
    17  		//
    18  		// See: https://techdocs.akamai.com/edgeworkers/reference/get-report
    19  		GetSummaryReport(context.Context, GetSummaryReportRequest) (*GetSummaryReportResponse, error)
    20  
    21  		// GetReport gets details for an EdgeWorker
    22  		//
    23  		// See: https://techdocs.akamai.com/edgeworkers/reference/get-report
    24  		GetReport(context.Context, GetReportRequest) (*GetReportResponse, error)
    25  
    26  		// ListReports lists EdgeWorker reports
    27  		//
    28  		// See: https://techdocs.akamai.com/edgeworkers/reference/get-reports
    29  		ListReports(context.Context) (*ListReportsResponse, error)
    30  	}
    31  
    32  	// GetSummaryReportRequest contains parameters used to get summary overview for EdgeWorker reports
    33  	GetSummaryReportRequest struct {
    34  		Start string
    35  		// If end date is not provided, then API will assign current date by default
    36  		End          string
    37  		EdgeWorker   string
    38  		Status       *string
    39  		EventHandler *string
    40  	}
    41  
    42  	// GetSummaryReportResponse represents a response object returned by GetSummaryReport
    43  	GetSummaryReportResponse struct {
    44  		ReportID    int         `json:"reportId"`
    45  		Name        string      `json:"name"`
    46  		Description string      `json:"description"`
    47  		Start       string      `json:"start"`
    48  		End         string      `json:"end"`
    49  		Data        DataSummary `json:"data"`
    50  		Unavailable *bool       `json:"unavailable"`
    51  	}
    52  
    53  	// DataSummary represents reports summary overview data for EdgeWorker
    54  	DataSummary struct {
    55  		Memory       *Summary `json:"memory"`
    56  		Successes    *Total   `json:"successes"`
    57  		InitDuration *Summary `json:"initDuration"`
    58  		ExecDuration *Summary `json:"execDuration"`
    59  		Errors       *Total   `json:"errors"`
    60  		Invocations  *Total   `json:"invocations"`
    61  	}
    62  
    63  	// GetReportRequest contains parameters used to get an EdgeWorker report
    64  	GetReportRequest struct {
    65  		ReportID int
    66  		Start    string
    67  		// If end date is not provided, then API will assign current date by default
    68  		End          string
    69  		EdgeWorker   string
    70  		Status       *string
    71  		EventHandler *string
    72  	}
    73  
    74  	// GetReportResponse represents a response object returned by GetReport
    75  	GetReportResponse struct {
    76  		ReportID    int          `json:"reportId"`
    77  		Name        string       `json:"name"`
    78  		Description string       `json:"description"`
    79  		Start       string       `json:"start"`
    80  		End         string       `json:"end"`
    81  		Data        []ReportData `json:"data"`
    82  	}
    83  
    84  	// ReportData represents report data
    85  	ReportData struct {
    86  		EdgeWorkerID int  `json:"edgeWorkerId"`
    87  		Data         Data `json:"data"`
    88  	}
    89  
    90  	// Data represents data object
    91  	Data struct {
    92  		OnClientRequest  *OnClientRequest  `json:"onClientRequest"`
    93  		OnOriginRequest  *OnOriginRequest  `json:"onOriginRequest"`
    94  		OnOriginResponse *OnOriginResponse `json:"onOriginResponse"`
    95  		OnClientResponse *OnClientResponse `json:"onClientResponse"`
    96  		ResponseProvider *ResponseProvider `json:"responseProvider"`
    97  		Init             *Init             `json:"init"`
    98  	}
    99  
   100  	// OnClientRequest represents OnClientRequest list
   101  	OnClientRequest []OnRequestAndResponse
   102  	// OnOriginRequest represents OnOriginRequest list
   103  	OnOriginRequest []OnRequestAndResponse
   104  	// OnOriginResponse represents OnOriginResponse list
   105  	OnOriginResponse []OnRequestAndResponse
   106  	// OnClientResponse represents OnClientResponse list
   107  	OnClientResponse []OnRequestAndResponse
   108  	// ResponseProvider represents ResponseProvider list
   109  	ResponseProvider []OnRequestAndResponse
   110  	// Init represents Init list
   111  	Init []InitObject
   112  
   113  	// OnRequestAndResponse represents object structure for OnClientRequest, OnOriginRequest, OnOriginResponse,
   114  	// OnClientResponse, ResponseProvider fields
   115  	OnRequestAndResponse struct {
   116  		Status            *string  `json:"status"`
   117  		StartDateTime     string   `json:"startDateTime"`
   118  		EdgeWorkerVersion string   `json:"edgeWorkerVersion"`
   119  		ExecDuration      *Summary `json:"execDuration"`
   120  		Invocations       int      `json:"invocations"`
   121  		Memory            *Summary `json:"memory"`
   122  	}
   123  
   124  	// InitObject represents object structure for Init field
   125  	InitObject struct {
   126  		StartDateTime     string  `json:"startDateTime"`
   127  		EdgeWorkerVersion string  `json:"edgeWorkerVersion"`
   128  		InitDuration      Summary `json:"initDuration"`
   129  		Invocations       int     `json:"invocations"`
   130  	}
   131  
   132  	// Summary represents data object for memory usage, initialization duration and execution duration
   133  	Summary struct {
   134  		Avg float64 `json:"avg"`
   135  		Min float64 `json:"min"`
   136  		Max float64 `json:"max"`
   137  	}
   138  
   139  	// Total describes total count for Successes, Invocations, Errors
   140  	Total struct {
   141  		Total int `json:"total"`
   142  	}
   143  
   144  	// ListReportsResponse represents list of report types
   145  	ListReportsResponse struct {
   146  		Reports []ReportResponse `json:"reports"`
   147  	}
   148  
   149  	// ReportResponse represents report type object
   150  	ReportResponse struct {
   151  		ReportID    int    `json:"reportId"`
   152  		Name        string `json:"name"`
   153  		Description string `json:"description"`
   154  		Unavailable bool   `json:"unavailable"`
   155  	}
   156  )
   157  
   158  // These constants represent all the valid report statuses
   159  const (
   160  	StatusSuccess                   = "success"
   161  	StatusGenericError              = "genericError"
   162  	StatusUnknownEdgeWorkerID       = "unknownEdgeWorkerId"
   163  	StatusUnimplementedEventHandler = "unimplementedEventHandler"
   164  	StatusRuntimeError              = "runtimeError"
   165  	StatusExecutionError            = "executionError"
   166  	StatusTimeoutError              = "timeoutError"
   167  	StatusResourceLimitHit          = "resourceLimitHit"
   168  	StatusCPUTimeoutError           = "cpuTimeoutError"
   169  	StatusWallTimeoutError          = "wallTimeoutError"
   170  	StatusInitCPUTimeoutError       = "initCpuTimeoutError"
   171  	StatusInitWallTimeoutError      = "initWallTimeoutError"
   172  )
   173  
   174  // These constants represent all the valid report event handlers
   175  const (
   176  	EventHandlerOnClientRequest  = "onClientRequest"
   177  	EventHandlerOnOriginRequest  = "onOriginRequest"
   178  	EventHandlerOnOriginResponse = "onOriginResponse"
   179  	EventHandlerOnClientResponse = "onClientResponse"
   180  	EventHandlerResponseProvider = "responseProvider"
   181  )
   182  
   183  var (
   184  	// ErrGetSummaryReport is returned in case an error occurs on GetSummaryReport operation
   185  	ErrGetSummaryReport = errors.New("get summary overview for EdgeWorker reports")
   186  	// ErrGetReport is returned in case an error occurs on GetReport operation
   187  	ErrGetReport = errors.New("get an EdgeWorker report")
   188  	// ErrListReports is returned in case an error occurs on ListReports operation
   189  	ErrListReports = errors.New("get EdgeWorker reports")
   190  )
   191  
   192  // Validate validates GetSummaryReportRequest
   193  func (r GetSummaryReportRequest) Validate() error {
   194  	return validation.Errors{
   195  		"Start": validation.Validate(r.Start, validation.Required, validation.Date("2006-01-02T15:04:05.999Z").Error(
   196  			fmt.Sprintf("value '%s' is invalid. It must have format '2006-01-02T15:04:05.999Z'", r.Start))),
   197  		"End": validation.Validate(r.End, validation.Date("2006-01-02T15:04:05.999Z").Error(
   198  			fmt.Sprintf("value '%s' is invalid. It must have format '2006-01-02T15:04:05.999Z'", r.End))),
   199  		"EdgeWorker": validation.Validate(r.EdgeWorker, validation.Required),
   200  		"Status": validation.Validate(r.Status, validation.NilOrNotEmpty, validation.In(StatusSuccess, StatusGenericError, StatusUnknownEdgeWorkerID, StatusUnimplementedEventHandler,
   201  			StatusRuntimeError, StatusExecutionError, StatusTimeoutError, StatusResourceLimitHit, StatusCPUTimeoutError, StatusWallTimeoutError, StatusInitCPUTimeoutError,
   202  			StatusInitWallTimeoutError).Error(fmt.Sprintf("value '%s' is invalid. Must be one of: 'success', 'genericError', "+
   203  			"'unknownEdgeWorkerId', 'unimplementedEventHandler', 'runtimeError', 'executionError', 'timeoutError', "+
   204  			"'resourceLimitHit', 'cpuTimeoutError', 'wallTimeoutError', 'initCpuTimeoutError', 'initWallTimeoutError'", stringFromPtr(r.Status)))),
   205  		"EventHandler": validation.Validate(r.EventHandler, validation.NilOrNotEmpty, validation.In(EventHandlerOnClientRequest, EventHandlerOnOriginRequest, EventHandlerOnOriginResponse,
   206  			EventHandlerOnClientResponse, EventHandlerResponseProvider).Error(fmt.Sprintf("value '%s' is invalid. Must be one of: 'onClientRequest', "+
   207  			"'onOriginRequest', 'onOriginResponse', 'onClientResponse', 'responseProvider'", stringFromPtr(r.EventHandler)))),
   208  	}.Filter()
   209  }
   210  
   211  // Validate validates GetReportRequest
   212  func (r GetReportRequest) Validate() error {
   213  	return validation.Errors{
   214  		"ReportID": validation.Validate(r.ReportID, validation.Required, validation.Min(2)),
   215  		"Start": validation.Validate(r.Start, validation.Required, validation.Date("2006-01-02T15:04:05.999Z").Error(
   216  			fmt.Sprintf("value '%s' is invalid. It must have format '2006-01-02T15:04:05.999Z'", r.Start))),
   217  		"End": validation.Validate(r.End, validation.Date("2006-01-02T15:04:05.999Z").Error(
   218  			fmt.Sprintf("value '%s' is invalid. It must have format '2006-01-02T15:04:05.999Z'", r.End))),
   219  		"EdgeWorker": validation.Validate(r.EdgeWorker, validation.Required),
   220  		"Status": validation.Validate(r.Status, validation.NilOrNotEmpty, validation.In(StatusSuccess, StatusGenericError, StatusUnknownEdgeWorkerID, StatusUnimplementedEventHandler,
   221  			StatusRuntimeError, StatusExecutionError, StatusTimeoutError, StatusResourceLimitHit, StatusCPUTimeoutError, StatusWallTimeoutError, StatusInitCPUTimeoutError,
   222  			StatusInitWallTimeoutError).Error(fmt.Sprintf("value '%s' is invalid. Must be one of: 'success', 'genericError', "+
   223  			"'unknownEdgeWorkerId', 'unimplementedEventHandler', 'runtimeError', 'executionError', 'timeoutError', "+
   224  			"'resourceLimitHit', 'cpuTimeoutError', 'wallTimeoutError', 'initCpuTimeoutError', 'initWallTimeoutError'", stringFromPtr(r.Status)))),
   225  		"EventHandler": validation.Validate(r.EventHandler, validation.NilOrNotEmpty, validation.In(EventHandlerOnClientRequest, EventHandlerOnOriginRequest, EventHandlerOnOriginResponse,
   226  			EventHandlerOnClientResponse, EventHandlerResponseProvider).Error(fmt.Sprintf("value '%s' is invalid. Must be one of: 'onClientRequest', "+
   227  			"'onOriginRequest', 'onOriginResponse', 'onClientResponse', 'responseProvider'", stringFromPtr(r.EventHandler)))),
   228  	}.Filter()
   229  }
   230  
   231  func stringFromPtr(s *string) string {
   232  	if s == nil {
   233  		return ""
   234  	}
   235  	return *s
   236  }
   237  
   238  func (e *edgeworkers) GetSummaryReport(ctx context.Context, params GetSummaryReportRequest) (*GetSummaryReportResponse, error) {
   239  	logger := e.Log(ctx)
   240  	logger.Debug("GetSummaryReport")
   241  
   242  	if err := params.Validate(); err != nil {
   243  		return nil, fmt.Errorf("%s: %w: %s", ErrGetSummaryReport, ErrStructValidation, err)
   244  	}
   245  
   246  	uri, err := url.Parse("/edgeworkers/v1/reports/1")
   247  	if err != nil {
   248  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrGetSummaryReport, err)
   249  	}
   250  
   251  	q := uri.Query()
   252  	q.Add("edgeWorker", params.EdgeWorker)
   253  	q.Add("start", params.Start)
   254  	if params.End != "" {
   255  		q.Add("end", params.End)
   256  	}
   257  	if params.Status != nil {
   258  		status := *params.Status
   259  		q.Add("status", status)
   260  	}
   261  	if params.EventHandler != nil {
   262  		status := *params.EventHandler
   263  		q.Add("eventHandler", status)
   264  	}
   265  	uri.RawQuery = q.Encode()
   266  
   267  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
   268  	if err != nil {
   269  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetSummaryReport, err)
   270  	}
   271  
   272  	var result GetSummaryReportResponse
   273  	resp, err := e.Exec(req, &result)
   274  	if err != nil {
   275  		return nil, fmt.Errorf("%w: request failed: %s", ErrGetSummaryReport, err)
   276  	}
   277  
   278  	if resp.StatusCode != http.StatusOK {
   279  		return nil, fmt.Errorf("%s: %w", ErrGetSummaryReport, e.Error(resp))
   280  	}
   281  
   282  	return &result, nil
   283  }
   284  
   285  func (e *edgeworkers) GetReport(ctx context.Context, params GetReportRequest) (*GetReportResponse, error) {
   286  	logger := e.Log(ctx)
   287  	logger.Debug("GetReport")
   288  
   289  	if err := params.Validate(); err != nil {
   290  		return nil, fmt.Errorf("%s: %w: %s", ErrGetReport, ErrStructValidation, err)
   291  	}
   292  
   293  	uri, err := url.Parse(fmt.Sprintf("/edgeworkers/v1/reports/%d", params.ReportID))
   294  	if err != nil {
   295  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrGetReport, err)
   296  	}
   297  
   298  	q := uri.Query()
   299  	q.Add("edgeWorker", params.EdgeWorker)
   300  	q.Add("start", params.Start)
   301  	if params.End != "" {
   302  		q.Add("end", params.End)
   303  	}
   304  	if params.Status != nil {
   305  		status := *params.Status
   306  		q.Add("status", status)
   307  	}
   308  	if params.EventHandler != nil {
   309  		status := *params.EventHandler
   310  		q.Add("eventHandler", status)
   311  	}
   312  	uri.RawQuery = q.Encode()
   313  
   314  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
   315  	if err != nil {
   316  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetReport, err)
   317  	}
   318  
   319  	var result GetReportResponse
   320  	resp, err := e.Exec(req, &result)
   321  	if err != nil {
   322  		return nil, fmt.Errorf("%w: request failed: %s", ErrGetReport, err)
   323  	}
   324  
   325  	if resp.StatusCode != http.StatusOK {
   326  		return nil, fmt.Errorf("%s: %w", ErrGetReport, e.Error(resp))
   327  	}
   328  
   329  	return &result, nil
   330  }
   331  
   332  func (e *edgeworkers) ListReports(ctx context.Context) (*ListReportsResponse, error) {
   333  	logger := e.Log(ctx)
   334  	logger.Debug("ListReports")
   335  
   336  	uri := fmt.Sprintf("/edgeworkers/v1/reports")
   337  
   338  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil)
   339  	if err != nil {
   340  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrListReports, err)
   341  	}
   342  
   343  	var result ListReportsResponse
   344  	resp, err := e.Exec(req, &result)
   345  	if err != nil {
   346  		return nil, fmt.Errorf("%w: request failed: %s", ErrListReports, err)
   347  	}
   348  
   349  	if resp.StatusCode != http.StatusOK {
   350  		return nil, fmt.Errorf("%s: %w", ErrListReports, e.Error(resp))
   351  	}
   352  
   353  	return &result, nil
   354  }