diff --git a/ee/query-service/app/api/api.go b/ee/query-service/app/api/api.go index 418cd00cf9..83303f3663 100644 --- a/ee/query-service/app/api/api.go +++ b/ee/query-service/app/api/api.go @@ -170,6 +170,11 @@ func (ah *APIHandler) RegisterRoutes(router *mux.Router, am *baseapp.AuthMiddlew am.ViewAccess(ah.listLicensesV2)). Methods(http.MethodGet) + router.HandleFunc("/api/v1/usage_alerts", am.AdminAccess(ah.listUsageAlerts)).Methods(http.MethodGet) + router.HandleFunc("/api/v1/usage_alerts", am.AdminAccess(ah.createUsageAlert)).Methods(http.MethodPost) + router.HandleFunc("/api/v1/usage_alerts/{id}", am.AdminAccess(ah.updateUsageAlert)).Methods(http.MethodPut) + router.HandleFunc("/api/v1/usage_alerts/{id}", am.AdminAccess(ah.deleteUsageAlert)).Methods(http.MethodDelete) + ah.APIHandler.RegisterRoutes(router, am) } diff --git a/ee/query-service/app/api/license.go b/ee/query-service/app/api/license.go index 51cfddefb1..850afc7656 100644 --- a/ee/query-service/app/api/license.go +++ b/ee/query-service/app/api/license.go @@ -7,6 +7,8 @@ import ( "io" "net/http" + "github.com/gorilla/mux" + "github.com/xtgo/uuid" "go.signoz.io/signoz/ee/query-service/constants" "go.signoz.io/signoz/ee/query-service/model" "go.uber.org/zap" @@ -59,6 +61,23 @@ type billingDetails struct { } `json:"data"` } +type UsageAlert struct { + ID uuid.UUID `db:"id"` + InstallationID uuid.UUID `db:"installation_id"` + LicenseKey uuid.UUID `db:"license_key"` + Emails string `db:"emails"` + Type string `db:"type"` + Threshold float64 `db:"threshold"` + AlertSent int `db:"alert_sent"` +} + +type usageAlertResponse struct { + Status string `json:"status"` + Data struct { + Alerts []UsageAlert `json:"alerts"` + } `json:"data"` +} + func (ah *APIHandler) listLicenses(w http.ResponseWriter, r *http.Request) { licenses, apiError := ah.LM().GetLicenses(context.Background()) if apiError != nil { @@ -270,3 +289,115 @@ func (ah *APIHandler) portalSession(w http.ResponseWriter, r *http.Request) { ah.Respond(w, resp.Data) } + +func (ah *APIHandler) listUsageAlerts(w http.ResponseWriter, r *http.Request) { + licenseKey := r.URL.Query().Get("licenseKey") + + if licenseKey == "" { + RespondError(w, model.BadRequest(fmt.Errorf("license key is required")), nil) + return + } + + billingAlertURL := fmt.Sprintf("%s/alerts?licenseKey=%s", constants.LicenseSignozIo, licenseKey) + + hClient := &http.Client{} + req, err := http.NewRequest("GET", billingAlertURL, nil) + if err != nil { + RespondError(w, model.InternalError(err), nil) + return + } + req.Header.Add("X-SigNoz-SecretKey", constants.LicenseAPIKey) + billingAlertResp, err := hClient.Do(req) + if err != nil { + RespondError(w, model.InternalError(err), nil) + return + } + + // decode response body + var alerts usageAlertResponse + if err := json.NewDecoder(billingAlertResp.Body).Decode(&alerts); err != nil { + RespondError(w, model.InternalError(err), nil) + return + } + + ah.Respond(w, alerts) +} + +func (ah *APIHandler) createUsageAlert(w http.ResponseWriter, r *http.Request) { + var alert UsageAlert + + if err := json.NewDecoder(r.Body).Decode(&alert); err != nil { + RespondError(w, model.BadRequest(err), nil) + return + } + + billingAlertURL := fmt.Sprintf("%s/alerts", constants.LicenseSignozIo) + + hClient := &http.Client{} + req, err := http.NewRequest("POST", billingAlertURL, r.Body) + if err != nil { + RespondError(w, model.InternalError(err), nil) + return + } + req.Header.Add("X-SigNoz-SecretKey", constants.LicenseAPIKey) + _, err = hClient.Do(req) + if err != nil { + RespondError(w, model.InternalError(err), nil) + return + } + + ah.Respond(w, nil) +} + +func (ah *APIHandler) deleteUsageAlert(w http.ResponseWriter, r *http.Request) { + alertID := mux.Vars(r)["id"] + + if alertID == "" { + RespondError(w, model.BadRequest(fmt.Errorf("alertID is required")), nil) + return + } + + billingAlertURL := fmt.Sprintf("%s/alerts/%s", constants.LicenseSignozIo, alertID) + + hClient := &http.Client{} + req, err := http.NewRequest("DELETE", billingAlertURL, nil) + if err != nil { + RespondError(w, model.InternalError(err), nil) + return + } + req.Header.Add("X-SigNoz-SecretKey", constants.LicenseAPIKey) + _, err = hClient.Do(req) + if err != nil { + RespondError(w, model.InternalError(err), nil) + return + } + + ah.Respond(w, nil) +} + +func (ah *APIHandler) updateUsageAlert(w http.ResponseWriter, r *http.Request) { + alertID := mux.Vars(r)["id"] + + if alertID == "" { + RespondError(w, model.BadRequest(fmt.Errorf("alertID is required")), nil) + return + } + + billingAlertURL := fmt.Sprintf("%s/alerts/%s", constants.LicenseSignozIo, alertID) + + hClient := &http.Client{} + req, err := http.NewRequest("PUT", billingAlertURL, r.Body) + if err != nil { + RespondError(w, model.InternalError(err), nil) + return + } + + req.Header.Add("X-SigNoz-SecretKey", constants.LicenseAPIKey) + _, err = hClient.Do(req) + if err != nil { + RespondError(w, model.InternalError(err), nil) + return + } + + ah.Respond(w, nil) +}