Skip to content

Commit

Permalink
chore: improved global error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
dinxsh committed Dec 22, 2024
1 parent 8a484e3 commit 223aefc
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 22 deletions.
72 changes: 72 additions & 0 deletions src/serviceLogs/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package serviceLogs

import (
"fmt"
"github.com/pkg/errors"
)

// ErrInvalidRequest represents errors related to invalid API requests
type ErrInvalidRequest struct {

Check failure on line 9 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux amd64

other declaration of ErrInvalidRequest

Check failure on line 9 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux 386

other declaration of ErrInvalidRequest

Check failure on line 9 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin amd64

other declaration of ErrInvalidRequest

Check failure on line 9 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin arm64

other declaration of ErrInvalidRequest

Check failure on line 9 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for windows amd64

other declaration of ErrInvalidRequest
Op string
Message string
Err error
}

func (e *ErrInvalidRequest) Error() string {
if e.Err != nil {
return fmt.Sprintf("%s: %s: %v", e.Op, e.Message, e.Err)
}
return fmt.Sprintf("%s: %s", e.Op, e.Message)
}

func (e *ErrInvalidRequest) Unwrap() error {
return e.Err
}

// ErrLogResponse represents errors related to log response parsing or validation
type ErrLogResponse struct {

Check failure on line 27 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux amd64

other declaration of ErrLogResponse

Check failure on line 27 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux 386

other declaration of ErrLogResponse

Check failure on line 27 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin amd64

other declaration of ErrLogResponse

Check failure on line 27 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin arm64

other declaration of ErrLogResponse

Check failure on line 27 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for windows amd64

other declaration of ErrLogResponse
StatusCode int
Message string
Err error
}

func (e *ErrLogResponse) Error() string {
if e.Err != nil {
return fmt.Sprintf("log response error (status %d): %s: %v", e.StatusCode, e.Message, e.Err)
}
return fmt.Sprintf("log response error (status %d): %s", e.StatusCode, e.Message)
}

func (e *ErrLogResponse) Unwrap() error {
return e.Err
}

// NewInvalidRequestError creates a new ErrInvalidRequest
func NewInvalidRequestError(op string, message string, err error) error {

Check failure on line 45 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux amd64

other declaration of NewInvalidRequestError

Check failure on line 45 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux 386

other declaration of NewInvalidRequestError

Check failure on line 45 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin amd64

other declaration of NewInvalidRequestError

Check failure on line 45 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin arm64

other declaration of NewInvalidRequestError

Check failure on line 45 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for windows amd64

other declaration of NewInvalidRequestError
return &ErrInvalidRequest{
Op: op,
Message: message,
Err: err,
}
}

// NewLogResponseError creates a new ErrLogResponse
func NewLogResponseError(statusCode int, message string, err error) error {

Check failure on line 54 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux amd64

other declaration of NewLogResponseError

Check failure on line 54 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux 386

other declaration of NewLogResponseError

Check failure on line 54 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin amd64

other declaration of NewLogResponseError

Check failure on line 54 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin arm64

other declaration of NewLogResponseError

Check failure on line 54 in src/serviceLogs/errors.go

View workflow job for this annotation

GitHub Actions / Build && tests for windows amd64

other declaration of NewLogResponseError
return &ErrLogResponse{
StatusCode: statusCode,
Message: message,
Err: err,
}
}

// IsInvalidRequestError checks if the error is an ErrInvalidRequest
func IsInvalidRequestError(err error) bool {
var target *ErrInvalidRequest
return errors.As(err, &target)
}

// IsLogResponseError checks if the error is an ErrLogResponse
func IsLogResponseError(err error) bool {
var target *ErrLogResponse
return errors.As(err, &target)
}
13 changes: 9 additions & 4 deletions src/serviceLogs/handler_formatByTemplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import (
)

func getFullWithTemplate(logData []Data, formatTemplate string) error {
if len(logData) == 0 {
return NewInvalidRequestError("getFullWithTemplate", "no log data available", nil)
}

ft, err := fixTemplate(formatTemplate)
if err != nil {
return err
Expand All @@ -31,12 +35,13 @@ func formatDataByTemplate(data Data, formatTemplate string) error {
var b bytes.Buffer
t, err := template.New("").Parse(formatTemplate)
if err != nil {
return err
return NewInvalidRequestError("formatDataByTemplate", "failed to parse template", err)
}
err = t.Execute(&b, data)
if err != nil {
return err

if err = t.Execute(&b, data); err != nil {
return NewInvalidRequestError("formatDataByTemplate", "failed to execute template", err)
}

fmt.Println(b.String())
return nil
}
Expand Down
65 changes: 50 additions & 15 deletions src/serviceLogs/handler_getLogs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package serviceLogs
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"time"
Expand Down Expand Up @@ -33,45 +35,78 @@ type Data struct {
Message string `json:"message"`
}

var (
ErrInvalidRequest = errors.New("invalid request")

Check failure on line 39 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux amd64

ErrInvalidRequest redeclared in this block

Check failure on line 39 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux 386

ErrInvalidRequest redeclared in this block

Check failure on line 39 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin amd64

ErrInvalidRequest redeclared in this block

Check failure on line 39 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin arm64

ErrInvalidRequest redeclared in this block

Check failure on line 39 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for windows amd64

ErrInvalidRequest redeclared in this block
ErrLogResponse = errors.New("log response error")

Check failure on line 40 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux amd64

ErrLogResponse redeclared in this block

Check failure on line 40 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux 386

ErrLogResponse redeclared in this block

Check failure on line 40 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin amd64

ErrLogResponse redeclared in this block

Check failure on line 40 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin arm64

ErrLogResponse redeclared in this block

Check failure on line 40 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for windows amd64

ErrLogResponse redeclared in this block
ErrInvalidResponse = errors.New("invalid response")
)

type InvalidRequestError struct {
FuncName string
Msg string
Err error
}

func (e *InvalidRequestError) Error() string {
return fmt.Sprintf("%s: %s: %v", e.FuncName, e.Msg, e.Err)
}

func NewInvalidRequestError(funcName, msg string, err error) error {

Check failure on line 54 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux amd64

NewInvalidRequestError redeclared in this block

Check failure on line 54 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux 386

NewInvalidRequestError redeclared in this block

Check failure on line 54 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin amd64

NewInvalidRequestError redeclared in this block

Check failure on line 54 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin arm64

NewInvalidRequestError redeclared in this block

Check failure on line 54 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for windows amd64

NewInvalidRequestError redeclared in this block
return &InvalidRequestError{FuncName: funcName, Msg: msg, Err: err}
}

type LogResponseError struct {
StatusCode int
Msg string
Err error
}

func (e *LogResponseError) Error() string {
return fmt.Sprintf("status code: %d: %s: %v", e.StatusCode, e.Msg, e.Err)
}

func NewLogResponseError(statusCode int, msg string, err error) error {

Check failure on line 68 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux amd64

NewLogResponseError redeclared in this block

Check failure on line 68 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for linux 386

NewLogResponseError redeclared in this block

Check failure on line 68 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin amd64

NewLogResponseError redeclared in this block

Check failure on line 68 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for darwin arm64

NewLogResponseError redeclared in this block

Check failure on line 68 in src/serviceLogs/handler_getLogs.go

View workflow job for this annotation

GitHub Actions / Build && tests for windows amd64

NewLogResponseError redeclared in this block
return &LogResponseError{StatusCode: statusCode, Msg: msg, Err: err}
}

func getLogs(ctx context.Context, method, url, format, formatTemplate, mode string) error {
c := http.Client{Timeout: time.Duration(1) * time.Minute}

req, err := http.NewRequest(method, url, nil)
if err != nil {
return err
return NewInvalidRequestError("getLogs", "failed to create request", err)
}
req = req.WithContext(ctx)
req.Header.Add("Content-Type", "application/json")

resp, err := c.Do(req)
if err != nil {
return err
return NewInvalidRequestError("getLogs", "failed to execute request", err)
}

defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)

if err != nil {
return err
return NewLogResponseError(resp.StatusCode, "failed to read response body", err)
}

jsonData, err := parseResponse(body)
if err != nil {
return err
if resp.StatusCode != http.StatusOK {
return NewLogResponseError(resp.StatusCode, fmt.Sprintf("unexpected status code: %d", resp.StatusCode), nil)
}
err = parseResponseByFormat(jsonData, format, formatTemplate, mode)

jsonData, err := parseResponse(body)
if err != nil {
return err
return NewLogResponseError(resp.StatusCode, "failed to parse response", err)
}
return nil

return parseResponseByFormat(jsonData, format, formatTemplate, mode)
}

func parseResponse(body []byte) (Response, error) {
var jsonData Response
err := json.Unmarshal(body, &jsonData)
if err != nil || len(jsonData.Items) == 0 {
return Response{}, err
var response Response
if err := json.Unmarshal(body, &response); err != nil {
return Response{}, NewLogResponseError(0, "failed to unmarshal response", err)
}
return jsonData, nil
return response, nil
}
15 changes: 12 additions & 3 deletions src/serviceLogs/handler_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,21 @@ import (
func (h *Handler) Run(ctx context.Context, config RunConfig) error {
inputs, err := h.checkInputValues(config)
if err != nil {
return err
return NewInvalidRequestError("Run", "invalid input values", err)
}

if config.Container.ID == "" {
return NewInvalidRequestError("Run", "container ID is required", nil)
}

// TODO - janhajek check empty containerID
if err = h.printLogs(ctx, inputs, config.Project.ID, config.ServiceId, config.Container.ID); err != nil {
return err
if IsInvalidRequestError(err) {
return err
}
if IsLogResponseError(err) {
return err
}
return NewLogResponseError(0, "failed to print logs", err)
}

return nil
Expand Down

0 comments on commit 223aefc

Please sign in to comment.