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 }