Files
plane/monitor/lib/api/api.go
Henit Chobisa a93467b95b feat: Added Prime Monitor Go Service for monitoring, health check and feature flagging (#411)
* feat: added build meta data to monitor

* feat: added versioning to prime-monitor

* feat: added logger package for prime-monitor

* feat: implemented logging in cmd

* feat: implemented moduled monorepo architecture

* feat: added cron package for healthcheck

* feat: added constants and modules for healthcheck

* feat: added environment service getter method

* feat: added environment service parser for parsing the recieved keys

* feat: added environment service provider method

* feat: added retry based executer for the test methods

* feat: added http health check method and placeholders for redis & pg

* feat: added tests for healthcheck methods

* feat: added PerformHealthCheck Controller Method for execution of healthcheck controller

* feat: added healthcheck test file for testing the healthcheck

* feat: added healthcheck to work file

* feat: added readme for healthcheck package

* feat: created healthcheck register for prime scheduler

* feat: added cron command for running cron subpart of monitor

* feat: added prime schedule handler for cron

* feat: added start command for starting up prime scheduler

* feat: added build utility files for monitor

* fix: goreleaser builds

* feat: removed Redis method from healthcheck methods

* feat: added docker file for building prime-monitor

* feat: added flag for adding healthcheck duration for cron start

* chore: removed redis as a healthcheck method

* chore: modified actions to build monitor on branch build and docker images

* feat: added monitor service in docker compose caddy

* feat: added description for HealthCheckJob

* fix: status code issue for reachable and non reachable

* feat: added api package for connecting with prime api

* feat: modified cmd package to report healthcheck status to prime

* feat: added api types inside prime-monitor

* feat: added message field for meta while status reporting

* fix: modified constants for environment variables

* feat: added monitor readme

* fix: build-branch monitor content shift to build-branch-ee

* chore: added build args on release

* feat: remove version meta data from cli

* fix: docker file changed to fix the build to default

* fix: removed build flags from github branch build

* fix: moved cron start to root level start cmd

* fix: passed the recieved machine signature to api headers

* feat: optimised docker build for monitor
2024-06-20 12:14:46 +05:30

186 lines
4.7 KiB
Go

package prime_api
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
)
type IPrimeMonitorApi interface {
PostServiceStatus(StatusPayload) ErrorCode
}
type PrimeMonitorApi struct {
host string
apiKey string
client string
version string
machineSignature string
}
func NewMonitorApi(host, apiKey, version, machineSignature string) IPrimeMonitorApi {
return &PrimeMonitorApi{
host: host,
apiKey: apiKey,
client: "Prime-Monitor",
version: version,
machineSignature: machineSignature,
}
}
func (api *PrimeMonitorApi) SetClient(client string) {
api.client = client
}
var (
API_PREFIX = "/api"
MONITOR_ENDPOINT = API_PREFIX + "/monitor/"
)
// ----------------------- Controller Methods ------------------------------
// Posts the status of the services given, to the prime server, returns error if
// hinderer, else doesn't return anything
func (api *PrimeMonitorApi) PostServiceStatus(payload StatusPayload) ErrorCode {
_, err := api.post(api.host+MONITOR_ENDPOINT, payload)
if err != nil {
fmt.Println(err)
return UNABLE_TO_POST_SERVICE_STATUS
}
return 0
}
// ------------------------ Helper Methods ----------------------------------
/*
prepareRequest prepares an HTTP request with the necessary headers and parameters.
Parameters:
- method: string specifying the HTTP method (e.g., "GET", "POST").
- urlStr: string specifying the URL for the request.
- body: io.Reader containing the request body.
- params: map[string]string containing the query parameters.
Returns:
- *http.Request: The prepared HTTP request.
- error: An error if any occurs during the preparation.
*/
func (api *PrimeMonitorApi) prepareRequest(method, urlStr string, body io.Reader, params map[string]string) (*http.Request, error) {
if method == "GET" && params != nil {
parsedURL, err := url.Parse(urlStr)
if err != nil {
return nil, fmt.Errorf("error parsing URL: %v", err)
}
query := parsedURL.Query()
for key, value := range params {
query.Set(key, value)
}
parsedURL.RawQuery = query.Encode()
urlStr = parsedURL.String()
}
req, err := http.NewRequest(method, urlStr, body)
if err != nil {
return nil, fmt.Errorf("error creating request: %v", err)
}
headers := map[string]string{
"X-Api-Key": api.apiKey,
"X-Machine-Signature": api.machineSignature,
"X-Client": api.client,
"X-License-Version": api.version,
"Content-Type": "application/json",
}
for key, value := range headers {
req.Header.Add(key, value)
}
return req, nil
}
/*
doRequest executes the HTTP request and handles common response scenarios.
Parameters:
- req: *http.Request specifying the HTTP request to execute.
Returns:
- []byte: The response body.
- error: An error if any occurs during the request execution.
*/
func (api *PrimeMonitorApi) doRequest(req *http.Request) ([]byte, error) {
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("error making request: %v", err)
}
defer resp.Body.Close()
switch {
case resp.StatusCode >= 200 && resp.StatusCode <= 227:
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("error reading response body: %v", err)
}
return body, nil
case resp.StatusCode >= 300 && resp.StatusCode <= 308:
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("error reading response body: %v", err)
}
return body, nil
case resp.StatusCode >= 400 && resp.StatusCode <= 451:
return nil, fmt.Errorf("unexpected status code %d", resp.StatusCode)
default:
return nil, fmt.Errorf("unexpected status code: %v", resp.StatusCode)
}
}
/*
get performs a GET request.
Parameters:
- baseURL: string specifying the base URL for the request.
- params: map[string]string containing the query parameters.
Returns:
- []byte: The response body.
- error: An error if any occurs during the request.
*/
func (api *PrimeMonitorApi) get(baseURL string, params map[string]string) ([]byte, error) {
req, err := api.prepareRequest("GET", baseURL, nil, params)
if err != nil {
return nil, err
}
return api.doRequest(req)
}
/*
post performs a POST request with JSON body.
Parameters:
- baseURL: string specifying the base URL for the request.
- data: interface{} containing the data to be sent in the request body.
Returns:
- []byte: The response body.
- error: An error if any occurs during the request.
*/
func (api *PrimeMonitorApi) post(baseURL string, data interface{}) ([]byte, error) {
jsonData, err := json.Marshal(data)
if err != nil {
return nil, fmt.Errorf("error marshaling data: %v", err)
}
req, err := api.prepareRequest("POST", baseURL, bytes.NewBuffer(jsonData), nil)
if err != nil {
return nil, err
}
return api.doRequest(req)
}