Files
houston-be/service/monitoringService/monitoring_service_client.go

285 lines
9.5 KiB
Go

package monitoringService
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/spf13/viper"
"go.uber.org/zap"
"houston/common/util"
"houston/logger"
"houston/model"
"houston/pkg/rest"
service "houston/service/response"
"io"
"net/http"
"os"
"strings"
"sync"
"time"
)
type ActionsImpl struct {
BaseURL string
Client rest.HttpRestClient
DefaultTimeout time.Duration
GetGrafanaImagesPath string
GetImpactedCustomersCSVPath string
}
func NewMonitoringServiceActionsImpl(client rest.HttpRestClient) *ActionsImpl {
return &ActionsImpl{
Client: client,
BaseURL: viper.GetString("MONITORING_SERVICE_BASEURL"),
DefaultTimeout: viper.GetDuration("DEFAULT_MONITORING_SERVICE_TIMEOUT"),
GetGrafanaImagesPath: viper.GetString("MONITORING_SERVICE_GET_GRAFANA_IMAGES_PATH"),
GetImpactedCustomersCSVPath: viper.GetString("MONITORING_SERVICE_GET_IMPACTED_CUSTOMERS_CSV_PATH"),
}
}
func (monitoringService *ActionsImpl) GetGrafanaImages(incidents []string, requestId string,
responseChannel chan service.MonitoringServiceClientResponse) {
fullURL := monitoringService.BaseURL + monitoringService.GetGrafanaImagesPath
requestHeaders := map[string]string{
"Content-Type": "application/json",
"CORRELATION_ID": requestId,
}
getGrafanaImagesRequestBody := model.GetGrafanaImagesRequest{
Incidents: incidents,
}
payload, err := json.Marshal(getGrafanaImagesRequestBody)
if err != nil {
logger.Error("Error while marshalling request body", zap.Error(err))
responseChannel <- service.MonitoringServiceClientResponse{Error: err}
return
}
response, err := monitoringService.Client.PostWithTimeout(fullURL, *bytes.NewBuffer(payload), requestHeaders,
monitoringService.DefaultTimeout, nil)
if err != nil {
logger.Error("Error while getting grafana images", zap.Error(err))
responseChannel <- service.MonitoringServiceClientResponse{Error: err}
return
}
if response.StatusCode == http.StatusNotFound {
logger.Info("No grafana images found for the given incident")
responseChannel <- service.MonitoringServiceClientResponse{}
return
}
if response.StatusCode != http.StatusOK {
logger.Error("Error while generating grafana images", zap.Error(err))
responseChannel <- service.MonitoringServiceClientResponse{Error: errors.New("error while generating grafana images")}
return
}
if response.Body == nil {
logger.Error("empty response body received from monitoring service")
responseChannel <- service.MonitoringServiceClientResponse{
Error: errors.New("empty response body received from monitoring service"),
}
return
}
directoryPath, err := processGrafanaImagesResponse(requestId, response)
if err != nil {
logger.Error("Error while processing grafana images response", zap.Error(err))
responseChannel <- service.MonitoringServiceClientResponse{Error: err}
return
}
responseChannel <- service.MonitoringServiceClientResponse{DirectoryPath: directoryPath}
return
}
func processGrafanaImagesResponse(requestId string, response *http.Response) (string, error) {
currentDirectory, _ := os.Getwd()
grafanaFilesDirectory := currentDirectory + "/krakatoa_files"
// Create files directory if not exists to store all grafana images
err := util.CheckAndCreateDirectory(grafanaFilesDirectory)
if err != nil {
logger.Error("Error while creating directory", zap.Error(err))
return "", err
}
destinationDirectoryPath := fmt.Sprintf("%v/%v", grafanaFilesDirectory, requestId)
err = util.CheckAndCreateDirectory(destinationDirectoryPath)
zipFileName := requestId + ".zip"
zipFilePath := fmt.Sprintf("%v/%v.zip", destinationDirectoryPath, requestId)
zipFile, err := util.CreateFileWithName(destinationDirectoryPath, zipFileName)
if err != nil {
logger.Error("Error while creating zip file", zap.Error(err))
return "", err
}
defer util.CloseFile(zipFile)
_, err = io.Copy(zipFile, response.Body)
if err != nil {
logger.Error("Error while copying zip file", zap.Error(err))
return "", err
}
err = unzipAndDeleteZipFile(zipFilePath, destinationDirectoryPath)
if err != nil {
return "", err
}
return destinationDirectoryPath, nil
}
func (monitoringService *ActionsImpl) GetImpactedCustomersCSV(incidents []string, requestId string,
responseChannel chan service.MonitoringServiceClientResponse) {
fullURL := monitoringService.BaseURL + monitoringService.GetImpactedCustomersCSVPath
requestHeaders := map[string]string{
"Content-Type": "application/json",
"CORRELATION_ID": requestId,
}
getImpactedCustomersCSVRequestBody := model.GetGrafanaImagesRequest{
Incidents: incidents,
}
payload, err := json.Marshal(getImpactedCustomersCSVRequestBody)
if err != nil {
logger.Error("Error while marshalling request body", zap.Error(err))
responseChannel <- service.MonitoringServiceClientResponse{Error: err}
return
}
response, err := monitoringService.Client.PostWithTimeout(fullURL, *bytes.NewBuffer(payload), requestHeaders,
monitoringService.DefaultTimeout, nil)
if response == nil {
logger.Error("no response received from monitoring service")
responseChannel <- service.MonitoringServiceClientResponse{
Error: errors.New("no response received from monitoring service"),
}
return
}
if response.StatusCode == http.StatusNotFound {
logger.Error("no configs found for the given incidents", zap.Error(err))
responseChannel <- service.MonitoringServiceClientResponse{}
}
if err != nil {
logger.Error("Error while getting impacted customers csv", zap.Error(err))
responseChannel <- service.MonitoringServiceClientResponse{Error: err}
return
}
if response.StatusCode != http.StatusOK {
logger.Error("error while generating impacted customers csv", zap.Error(err))
responseChannel <- service.MonitoringServiceClientResponse{Error: errors.New(
"error while generating impacted customers csv")}
return
}
if response.Body == nil {
logger.Error("empty response body received from monitoring service")
responseChannel <- service.MonitoringServiceClientResponse{
Error: errors.New("empty response body received from monitoring service"),
}
return
}
directoryPath, err := processImpactedCustomersCSV(requestId, response, monitoringService.Client)
if err != nil {
logger.Error("Error while processing impacted customers csv response", zap.Error(err))
responseChannel <- service.MonitoringServiceClientResponse{Error: err}
return
}
responseChannel <- service.MonitoringServiceClientResponse{
DirectoryPath: directoryPath,
}
return
}
func processImpactedCustomersCSV(requestId string, response *http.Response,
restClient rest.HttpRestClient) (string, error) {
currentDirectory, _ := os.Getwd()
grafanaFilesDirectory := currentDirectory + "/krakatoa_files"
responseBody, err := io.ReadAll(response.Body)
if err != nil {
logger.Error("Error while reading response body", zap.Error(err))
return "", err
}
var impactedCustomersCSVPaths []string
err = json.Unmarshal(responseBody, &impactedCustomersCSVPaths)
if err != nil {
logger.Error("error while unmarshalling response body", zap.Error(err))
return "", errors.New("error while unmarshalling response body")
}
err = util.CheckAndCreateDirectory(grafanaFilesDirectory)
if err != nil {
logger.Error("Error while creating directory", zap.Error(err))
return "", err
}
destinationDirectoryPath := fmt.Sprintf("%v/%v", grafanaFilesDirectory, requestId)
err = util.CheckAndCreateDirectory(destinationDirectoryPath)
if err != nil {
logger.Error("Error while creating directory", zap.Error(err))
return "", err
}
var waitGroup sync.WaitGroup
var downloadErrors []error
for _, impactedCustomersCSVPath := range impactedCustomersCSVPaths {
waitGroup.Add(1)
impactedCustomersCSVPath := impactedCustomersCSVPath
go func() {
err := downloadAndSaveCSVFile(restClient, impactedCustomersCSVPath, destinationDirectoryPath, &waitGroup)
if err != nil {
logger.Error("error while downloading and saving csv file", zap.Error(err))
downloadErrors = append(downloadErrors, err)
}
}()
}
waitGroup.Wait()
if len(downloadErrors) > 0 {
return "", errors.New("error while downloading and saving csv files")
} else {
return destinationDirectoryPath, nil
}
}
func downloadAndSaveCSVFile(restClient rest.HttpRestClient, fileURL string, destinationDirectoryPath string,
waitGroup *sync.WaitGroup) error {
defer waitGroup.Done()
response, err := restClient.Get(fileURL, nil, nil, true)
if err != nil {
logger.Error("Error while getting csv file", zap.Error(err))
return err
}
if response.StatusCode == http.StatusNotFound {
logger.Info("No CSV found for the given incident")
return nil
}
if response.StatusCode != http.StatusOK || response.Body == nil {
return errors.New("error while getting csv file")
}
fileName := strings.Trim(fmt.Sprintf("%v.csv", response.Header.Get("ETag")), "\"")
csvFile, err := util.CreateFileWithName(destinationDirectoryPath, fileName)
if err != nil {
logger.Error("Error while creating csv file", zap.Error(err))
return err
}
defer util.CloseFile(csvFile)
_, err = io.Copy(csvFile, response.Body)
if err != nil {
logger.Error("Error while copying csv file", zap.Error(err))
return err
}
return nil
}
func unzipAndDeleteZipFile(zipFilePath string, destinationDirectoryPath string) error {
err := util.UnzipFile(zipFilePath, destinationDirectoryPath)
if err != nil {
logger.Error("Error while unzipping file", zap.Error(err))
return err
}
err = util.DeleteFile(zipFilePath)
if err != nil {
logger.Error("Error while deleting file", zap.Error(err))
return err
}
return nil
}