github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/alerts/alertsHandler/alertsHandler.go (about)

     1  /*
     2  Copyright 2023.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package alertsHandler
    18  
    19  import (
    20  	"encoding/json"
    21  	"errors"
    22  	"time"
    23  
    24  	"github.com/google/uuid"
    25  	alertsqlite "github.com/siglens/siglens/pkg/alerts/alertsqlite"
    26  	"github.com/siglens/siglens/pkg/config"
    27  	"gorm.io/gorm"
    28  
    29  	"github.com/siglens/siglens/pkg/alerts/alertutils"
    30  	"github.com/siglens/siglens/pkg/utils"
    31  	"github.com/valyala/fasthttp"
    32  
    33  	log "github.com/sirupsen/logrus"
    34  )
    35  
    36  type database interface {
    37  	Connect() error
    38  	CloseDb()
    39  	SetDB(db *gorm.DB)
    40  	CreateAlert(alertInfo *alertutils.AlertDetails) (alertutils.AlertDetails, error)
    41  	GetAlert(alert_id string) (*alertutils.AlertDetails, error)
    42  	CreateAlertHistory(alertHistoryDetails *alertutils.AlertHistoryDetails) (*alertutils.AlertHistoryDetails, error)
    43  	GetAlertHistory(alertId string) ([]*alertutils.AlertHistoryDetails, error)
    44  	GetAllAlerts(orgId uint64) ([]alertutils.AlertDetails, error)
    45  	CreateMinionSearch(alertInfo *alertutils.MinionSearch) (alertutils.MinionSearch, error)
    46  	GetMinionSearch(alert_id string) (*alertutils.MinionSearch, error)
    47  	GetAllMinionSearches(orgId uint64) ([]alertutils.MinionSearch, error)
    48  	UpdateMinionSearchStateByAlertID(alertId string, alertState alertutils.AlertState) error
    49  	UpdateAlert(*alertutils.AlertDetails) error
    50  	UpdateSilenceMinutes(*alertutils.AlertDetails) error
    51  	DeleteAlert(alert_id string) error
    52  	CreateContact(*alertutils.Contact) error
    53  	GetAllContactPoints(orgId uint64) ([]alertutils.Contact, error)
    54  	UpdateContactPoint(contact *alertutils.Contact) error
    55  	GetCoolDownDetails(alert_id string) (uint64, time.Time, error)
    56  	GetContactDetails(alert_id string) (string, string, string, error)
    57  	GetEmailAndChannelID(contact_id string) ([]string, []alertutils.SlackTokenConfig, []string, error)
    58  	UpdateLastSentTime(alert_id string) error
    59  	UpdateAlertStateByAlertID(alertId string, alertState alertutils.AlertState) error
    60  	DeleteContactPoint(contact_id string) error
    61  }
    62  
    63  var databaseObj database
    64  
    65  var invalidDatabaseProvider = "database provider is not configured in server.yaml"
    66  
    67  func ConnectSiglensDB() error {
    68  	databaseObj = &alertsqlite.Sqlite{}
    69  	if databaseObj == nil {
    70  		log.Errorf("ConnectSiglensDB: %v", invalidDatabaseProvider)
    71  		return errors.New("ConnectSiglensDB: database provider is not configured in server.yaml")
    72  	}
    73  	err := databaseObj.Connect()
    74  	if err != nil {
    75  		return err
    76  	}
    77  	return nil
    78  }
    79  
    80  func Disconnect() {
    81  	if databaseObj == nil {
    82  		return
    83  	}
    84  	databaseObj.CloseDb()
    85  }
    86  
    87  func ProcessVersionInfo(ctx *fasthttp.RequestCtx) {
    88  	responseBody := make(map[string]interface{})
    89  	ctx.SetStatusCode(fasthttp.StatusOK)
    90  	responseBody["version"] = config.SigLensVersion
    91  	utils.WriteJsonResponse(ctx, responseBody)
    92  }
    93  
    94  func ProcessCreateAlertRequest(ctx *fasthttp.RequestCtx, org_id uint64) {
    95  	if databaseObj == nil {
    96  		responseBody := make(map[string]interface{})
    97  		log.Errorf("ProcessCreateAlertRequest: failed to create alert, err = %+v", invalidDatabaseProvider)
    98  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
    99  		responseBody["error"] = invalidDatabaseProvider
   100  		utils.WriteJsonResponse(ctx, responseBody)
   101  		return
   102  	}
   103  	responseBody := make(map[string]interface{})
   104  	var alertToBeCreated alertutils.AlertDetails
   105  
   106  	rawJSON := ctx.PostBody()
   107  	if len(rawJSON) == 0 {
   108  		log.Errorf("ProcessCreateAlertRequest: empty json body received")
   109  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   110  		responseBody["error"] = "empty json body received"
   111  		utils.WriteJsonResponse(ctx, responseBody)
   112  		return
   113  	}
   114  	alertToBeCreated.OrgId = org_id
   115  	err := json.Unmarshal(rawJSON, &alertToBeCreated)
   116  	if err != nil {
   117  		log.Errorf("ProcessCreateAlertRequest: could not unmarshal json body, err=%v", err)
   118  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   119  		responseBody["error"] = err.Error()
   120  		utils.WriteJsonResponse(ctx, responseBody)
   121  		return
   122  	}
   123  	alertDataObj, err := databaseObj.CreateAlert(&alertToBeCreated)
   124  	if err != nil {
   125  		log.Errorf("ProcessCreateAlertRequest: could not create alert=%v, err=%v", alertToBeCreated.AlertName, err)
   126  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   127  		responseBody["error"] = err.Error()
   128  		utils.WriteJsonResponse(ctx, responseBody)
   129  		return
   130  	}
   131  
   132  	_, err = AddCronJob(&alertDataObj)
   133  	if err != nil {
   134  		log.Errorf("ProcessCreateAlertRequest: could not add a new CronJob corresponding to alert=%+v, err=%+v", alertDataObj.AlertName, err)
   135  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   136  		responseBody["error"] = err.Error()
   137  		utils.WriteJsonResponse(ctx, responseBody)
   138  		return
   139  	}
   140  
   141  	ctx.SetStatusCode(fasthttp.StatusOK)
   142  	responseBody["message"] = "Successfully created an alert"
   143  	utils.WriteJsonResponse(ctx, responseBody)
   144  }
   145  
   146  func ProcessSilenceAlertRequest(ctx *fasthttp.RequestCtx) {
   147  	responseBody := make(map[string]interface{})
   148  
   149  	// Check if databaseObj is nil
   150  	if databaseObj == nil {
   151  		log.Error("ProcessSilenceAlertRequest: databaseObj is nil")
   152  		ctx.SetStatusCode(fasthttp.StatusInternalServerError)
   153  		responseBody["error"] = "Internal server error"
   154  		utils.WriteJsonResponse(ctx, responseBody)
   155  		return
   156  	}
   157  
   158  	// Check if request body is empty
   159  	if string(ctx.PostBody()) == "" {
   160  		log.Error("ProcessSilenceAlertRequest: request body is empty")
   161  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   162  		responseBody["error"] = "Request body is empty"
   163  		utils.WriteJsonResponse(ctx, responseBody)
   164  		return
   165  	}
   166  
   167  	// Parse request
   168  	var silenceRequest struct {
   169  		AlertID        string `json:"alert_id"`
   170  		SilenceMinutes uint64 `json:"silence_minutes"`
   171  	}
   172  	if err := json.Unmarshal(ctx.PostBody(), &silenceRequest); err != nil {
   173  		log.Errorf("ProcessSilenceAlertRequest: could not parse request body, err=%+v", err)
   174  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   175  		responseBody["error"] = err.Error()
   176  		utils.WriteJsonResponse(ctx, responseBody)
   177  		return
   178  	}
   179  
   180  	// Find alert and update SilenceMinutes
   181  	alertDataObj, err := databaseObj.GetAlert(silenceRequest.AlertID)
   182  	if err != nil {
   183  		log.Errorf("ProcessSilenceAlertRequest: could not find alert, err=%+v", err)
   184  		ctx.SetStatusCode(fasthttp.StatusNotFound)
   185  		responseBody["error"] = err.Error()
   186  		utils.WriteJsonResponse(ctx, responseBody)
   187  		return
   188  	}
   189  
   190  	alertDataObj.SilenceMinutes = silenceRequest.SilenceMinutes
   191  	// Update the SilenceMinutes
   192  	err = databaseObj.UpdateAlert(alertDataObj)
   193  	if err != nil {
   194  		log.Errorf("ProcessUpdateSilenceRequestRequest: could not update alert=%+v, err=%+v", alertDataObj.AlertName, err)
   195  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   196  		responseBody["error"] = err.Error()
   197  		utils.WriteJsonResponse(ctx, responseBody)
   198  		return
   199  	}
   200  	ctx.SetStatusCode(fasthttp.StatusOK)
   201  	responseBody["message"] = "Successfully updated silence period"
   202  	utils.WriteJsonResponse(ctx, responseBody)
   203  }
   204  
   205  func ProcessGetAlertRequest(ctx *fasthttp.RequestCtx) {
   206  	if databaseObj == nil {
   207  		responseBody := make(map[string]interface{})
   208  		log.Errorf("ProcessGetAlertRequest: failed to get alert, err = %+v", invalidDatabaseProvider)
   209  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   210  		responseBody["error"] = invalidDatabaseProvider
   211  		utils.WriteJsonResponse(ctx, responseBody)
   212  		return
   213  	}
   214  
   215  	responseBody := make(map[string]interface{})
   216  	alert_id := utils.ExtractParamAsString(ctx.UserValue("alertID"))
   217  	alert, err := databaseObj.GetAlert(alert_id)
   218  	if err != nil {
   219  		log.Errorf("ProcessGetAlertRequest: failed to get alert with alertId = %+v, err = %+v", alert_id, err.Error())
   220  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   221  		responseBody["error"] = err.Error()
   222  		utils.WriteJsonResponse(ctx, responseBody)
   223  		return
   224  	}
   225  
   226  	responseBody["alert"] = alert
   227  	ctx.SetStatusCode(fasthttp.StatusOK)
   228  	utils.WriteJsonResponse(ctx, responseBody)
   229  }
   230  
   231  func ProcessGetAllAlertsRequest(ctx *fasthttp.RequestCtx, org_id uint64) {
   232  	if databaseObj == nil {
   233  		responseBody := make(map[string]interface{})
   234  		log.Errorf("ProcessGetAllAlertsRequest: failed to get all alerts, err = %+v", invalidDatabaseProvider)
   235  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   236  		responseBody["error"] = invalidDatabaseProvider
   237  		utils.WriteJsonResponse(ctx, responseBody)
   238  		return
   239  	}
   240  
   241  	responseBody := make(map[string]interface{})
   242  	alerts, err := databaseObj.GetAllAlerts(org_id)
   243  	if err != nil {
   244  		log.Errorf("ProcessGetAllAlertsRequest: could not get all alerts, err: %+v", err.Error())
   245  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   246  		responseBody["error"] = err.Error()
   247  		utils.WriteJsonResponse(ctx, responseBody)
   248  		return
   249  	}
   250  
   251  	responseBody["alerts"] = alerts
   252  	ctx.SetStatusCode(fasthttp.StatusOK)
   253  	utils.WriteJsonResponse(ctx, responseBody)
   254  }
   255  
   256  func ProcessGetAllMinionSearchesRequest(ctx *fasthttp.RequestCtx, orgID uint64) {
   257  	if databaseObj == nil {
   258  		responseBody := make(map[string]interface{})
   259  		log.Errorf("ProcessGetAllMinionSearchesRequest: failed to get all alerts, err = %+v", invalidDatabaseProvider)
   260  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   261  		responseBody["error"] = invalidDatabaseProvider
   262  		utils.WriteJsonResponse(ctx, responseBody)
   263  		return
   264  	}
   265  
   266  	responseBody := make(map[string]interface{})
   267  	minionSearches, err := databaseObj.GetAllMinionSearches(orgID)
   268  	if err != nil {
   269  		log.Errorf("ProcessGetAllMinionSearchesRequest: could not get all alerts, err: %+v", err.Error())
   270  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   271  		responseBody["error"] = err.Error()
   272  		utils.WriteJsonResponse(ctx, responseBody)
   273  		return
   274  	}
   275  
   276  	responseBody["minionSearches"] = minionSearches
   277  	ctx.SetStatusCode(fasthttp.StatusOK)
   278  	utils.WriteJsonResponse(ctx, responseBody)
   279  }
   280  
   281  func ProcessUpdateAlertRequest(ctx *fasthttp.RequestCtx) {
   282  	if databaseObj == nil {
   283  		responseBody := make(map[string]interface{})
   284  		log.Errorf("ProcessUpdateAlertRequest: failed to update alert, err = %+v", invalidDatabaseProvider)
   285  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   286  		responseBody["error"] = invalidDatabaseProvider
   287  		utils.WriteJsonResponse(ctx, responseBody)
   288  		return
   289  	}
   290  	responseBody := make(map[string]interface{})
   291  	rawJSON := ctx.PostBody()
   292  	if len(rawJSON) == 0 {
   293  		log.Errorf("ProcessUpdateAlertRequest: empty json body received")
   294  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   295  		responseBody["error"] = "empty json body received"
   296  		utils.WriteJsonResponse(ctx, responseBody)
   297  		return
   298  	}
   299  
   300  	var alertToBeUpdated *alertutils.AlertDetails
   301  	err := json.Unmarshal(rawJSON, &alertToBeUpdated)
   302  	if err != nil {
   303  		log.Errorf("ProcessUpdateAlertRequest: could not unmarshal json body, err=%v", err)
   304  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   305  		responseBody["error"] = err.Error()
   306  		utils.WriteJsonResponse(ctx, responseBody)
   307  		return
   308  	}
   309  
   310  	err = databaseObj.UpdateAlert(alertToBeUpdated)
   311  	if err != nil {
   312  		log.Errorf("ProcessUpdateAlertRequest: could not update alert=%+v, err=%+v", alertToBeUpdated.AlertName, err)
   313  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   314  		responseBody["error"] = err.Error()
   315  		utils.WriteJsonResponse(ctx, responseBody)
   316  		return
   317  	}
   318  
   319  	// TODO: Update Username with specific user who changed the config. Username can be fetched from "ctx" when the authentication is implemented.
   320  	alertEvent := alertutils.AlertHistoryDetails{
   321  		AlertId:          alertToBeUpdated.AlertId,
   322  		EventDescription: alertutils.ConfigChange,
   323  		UserName:         alertutils.UserModified,
   324  		EventTriggeredAt: time.Now().UTC(),
   325  	}
   326  	_, err = databaseObj.CreateAlertHistory(&alertEvent)
   327  	if err != nil {
   328  		log.Errorf("ProcessUpdateAlertRequest: could not create alert event in alert history. found error = %v", err)
   329  	}
   330  
   331  	err = RemoveCronJob(alertToBeUpdated.AlertId)
   332  
   333  	if err != nil {
   334  		log.Errorf("ProcessUpdateAlertRequest: could not remove old cron job corresponding to alert=%+v, err=%+v", alertToBeUpdated.AlertName, err)
   335  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   336  		responseBody["error"] = err.Error()
   337  		utils.WriteJsonResponse(ctx, responseBody)
   338  		return
   339  	}
   340  	_, err = AddCronJob(alertToBeUpdated)
   341  	if err != nil {
   342  		log.Errorf("ProcessUpdateAlertRequest: could not add a new cron job corresponding to alert=%+v, err=%+v", alertToBeUpdated.AlertName, err)
   343  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   344  		responseBody["error"] = err.Error()
   345  		utils.WriteJsonResponse(ctx, responseBody)
   346  		return
   347  	}
   348  
   349  	responseBody["message"] = "Alert updated successfully"
   350  	utils.WriteJsonResponse(ctx, responseBody)
   351  	ctx.SetStatusCode(fasthttp.StatusOK)
   352  }
   353  
   354  func ProcessAlertHistoryRequest(ctx *fasthttp.RequestCtx) {
   355  	if databaseObj == nil {
   356  		responseBody := make(map[string]interface{})
   357  		log.Errorf("ProcessAlertHistoryRequest: failed to get alert history, err = %+v", invalidDatabaseProvider)
   358  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   359  		responseBody["error"] = invalidDatabaseProvider
   360  		utils.WriteJsonResponse(ctx, responseBody)
   361  		return
   362  	}
   363  
   364  	responseBody := make(map[string]interface{})
   365  	alertId := utils.ExtractParamAsString(ctx.UserValue("alertID"))
   366  	alertHistory, err := databaseObj.GetAlertHistory(alertId)
   367  	if err != nil {
   368  		log.Errorf("ProcessAlertHistoryRequest: failed to get alert history with alertId = %+v, err = %+v", alertId, err.Error())
   369  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   370  		responseBody["error"] = err.Error()
   371  		utils.WriteJsonResponse(ctx, responseBody)
   372  		return
   373  	}
   374  
   375  	responseBody["alertHistory"] = alertHistory
   376  	ctx.SetStatusCode(fasthttp.StatusOK)
   377  	utils.WriteJsonResponse(ctx, responseBody)
   378  }
   379  
   380  // request body should contain alert_id only
   381  func ProcessDeleteAlertRequest(ctx *fasthttp.RequestCtx) {
   382  	if databaseObj == nil {
   383  		responseBody := make(map[string]interface{})
   384  		log.Errorf("ProcessDeleteAlertRequest: failed to delete alert, err = %+v", invalidDatabaseProvider)
   385  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   386  		responseBody["error"] = invalidDatabaseProvider
   387  		utils.WriteJsonResponse(ctx, responseBody)
   388  		return
   389  	}
   390  	responseBody := make(map[string]interface{})
   391  	rawJSON := ctx.PostBody()
   392  	if len(rawJSON) == 0 {
   393  		log.Errorf("ProcessDeleteAlertRequest: empty json body received")
   394  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   395  		responseBody["error"] = "empty json body received"
   396  		utils.WriteJsonResponse(ctx, responseBody)
   397  		return
   398  	}
   399  
   400  	var alertToBeRemoved *alertutils.AlertDetails
   401  	err := json.Unmarshal(rawJSON, &alertToBeRemoved)
   402  	if err != nil {
   403  		log.Errorf("ProcessDeleteAlertRequest: could not unmarshal json body, err=%v", err)
   404  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   405  		responseBody["error"] = err.Error()
   406  		utils.WriteJsonResponse(ctx, responseBody)
   407  		return
   408  	}
   409  	err = RemoveCronJob(alertToBeRemoved.AlertId)
   410  	if err != nil {
   411  		log.Errorf("ProcessDeleteAlertRequest: RemoveCronJob failed , alert id=%v, err=%v", alertToBeRemoved.AlertId, err)
   412  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   413  		responseBody["error"] = err.Error()
   414  		utils.WriteJsonResponse(ctx, responseBody)
   415  		return
   416  	}
   417  
   418  	err = databaseObj.DeleteAlert(alertToBeRemoved.AlertId)
   419  	if err != nil {
   420  		log.Errorf("ProcessDeleteAlertRequest: failed to delete alert with id=%v, err=%v", alertToBeRemoved.AlertId, err)
   421  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   422  		responseBody["error"] = err.Error()
   423  		utils.WriteJsonResponse(ctx, responseBody)
   424  		return
   425  	}
   426  
   427  	responseBody["message"] = "Alert deleted successfully"
   428  	utils.WriteJsonResponse(ctx, responseBody)
   429  	ctx.SetStatusCode(fasthttp.StatusOK)
   430  }
   431  
   432  func ProcessCreateContactRequest(ctx *fasthttp.RequestCtx, org_id uint64) {
   433  	if databaseObj == nil {
   434  		responseBody := make(map[string]interface{})
   435  		log.Errorf("ProcessCreateContactRequest: failed to create a contact point, err = %+v", invalidDatabaseProvider)
   436  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   437  		responseBody["error"] = invalidDatabaseProvider
   438  		utils.WriteJsonResponse(ctx, responseBody)
   439  		return
   440  	}
   441  	responseBody := make(map[string]interface{})
   442  	var contactToBeCreated *alertutils.Contact
   443  
   444  	rawJSON := ctx.PostBody()
   445  	if len(rawJSON) == 0 {
   446  		log.Errorf("ProcessCreateContactRequest: empty json body received")
   447  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   448  		responseBody["error"] = "empty json body received"
   449  		utils.WriteJsonResponse(ctx, responseBody)
   450  		return
   451  	}
   452  	err := json.Unmarshal(rawJSON, &contactToBeCreated)
   453  	if err != nil {
   454  		log.Errorf("ProcessCreateContactRequest: could not unmarshal json body, err=%v", err)
   455  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   456  		responseBody["error"] = "could not unmarshal json body"
   457  		utils.WriteJsonResponse(ctx, responseBody)
   458  		return
   459  	}
   460  	contactToBeCreated.OrgId = org_id
   461  	err = databaseObj.CreateContact(contactToBeCreated)
   462  	if err != nil {
   463  		log.Errorf("ProcessCreateContactRequest: could not create contact with name=%v, err=%v", contactToBeCreated.ContactName, err)
   464  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   465  		responseBody["error"] = err.Error()
   466  		utils.WriteJsonResponse(ctx, responseBody)
   467  		return
   468  	}
   469  	ctx.SetStatusCode(fasthttp.StatusOK)
   470  	responseBody["message"] = "Successfully created a contact point"
   471  	utils.WriteJsonResponse(ctx, responseBody)
   472  }
   473  
   474  func ProcessGetAllContactsRequest(ctx *fasthttp.RequestCtx, org_id uint64) {
   475  	if databaseObj == nil {
   476  		responseBody := make(map[string]interface{})
   477  		log.Errorf("ProcessGetAllContactsRequest: failed to get all contacts, err = %+v", invalidDatabaseProvider)
   478  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   479  		responseBody["error"] = invalidDatabaseProvider
   480  		utils.WriteJsonResponse(ctx, responseBody)
   481  		return
   482  	}
   483  
   484  	responseBody := make(map[string]interface{})
   485  	contacts, err := databaseObj.GetAllContactPoints(org_id)
   486  	if err != nil {
   487  		log.Errorf("ProcessGetAllContactsRequest: could not get all contact points, err = %+v", err.Error())
   488  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   489  		responseBody["error"] = err.Error()
   490  		utils.WriteJsonResponse(ctx, responseBody)
   491  		return
   492  	}
   493  	responseBody["contacts"] = contacts
   494  	ctx.SetStatusCode(fasthttp.StatusOK)
   495  	utils.WriteJsonResponse(ctx, responseBody)
   496  }
   497  
   498  func ProcessUpdateContactRequest(ctx *fasthttp.RequestCtx) {
   499  	if databaseObj == nil {
   500  		responseBody := make(map[string]interface{})
   501  		log.Errorf("ProcessUpdateContactRequest: failed to update contact, err = %+v", invalidDatabaseProvider)
   502  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   503  		responseBody["error"] = invalidDatabaseProvider
   504  		utils.WriteJsonResponse(ctx, responseBody)
   505  		return
   506  	}
   507  
   508  	responseBody := make(map[string]interface{})
   509  	rawJSON := ctx.PostBody()
   510  	if len(rawJSON) == 0 {
   511  		log.Errorf("ProcessUpdateContactRequest: empty json body received")
   512  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   513  		responseBody["error"] = "empty json body received"
   514  		utils.WriteJsonResponse(ctx, responseBody)
   515  		return
   516  	}
   517  
   518  	var contactToBeUpdated *alertutils.Contact
   519  	err := json.Unmarshal(rawJSON, &contactToBeUpdated)
   520  	if err != nil {
   521  		log.Errorf("ProcessUpdateContactRequest: could not unmarshal json body, err=%v", err)
   522  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   523  		responseBody["error"] = err.Error()
   524  		utils.WriteJsonResponse(ctx, responseBody)
   525  		return
   526  	}
   527  	err = databaseObj.UpdateContactPoint(contactToBeUpdated)
   528  	if err != nil {
   529  		log.Errorf("ProcessUpdateContactRequest: could not update contact = %+v, err = %+v", contactToBeUpdated.ContactName, err)
   530  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   531  		responseBody["error"] = err.Error()
   532  		utils.WriteJsonResponse(ctx, responseBody)
   533  		return
   534  	}
   535  	responseBody["message"] = "Contact details updated successfully"
   536  	utils.WriteJsonResponse(ctx, responseBody)
   537  	ctx.SetStatusCode(fasthttp.StatusOK)
   538  }
   539  
   540  func ProcessDeleteContactRequest(ctx *fasthttp.RequestCtx) {
   541  	if databaseObj == nil {
   542  		responseBody := make(map[string]interface{})
   543  		log.Errorf("ProcessDeleteContactRequest: failed to delete contact, err = %+v", invalidDatabaseProvider)
   544  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   545  		responseBody["error"] = invalidDatabaseProvider
   546  		utils.WriteJsonResponse(ctx, responseBody)
   547  		return
   548  	}
   549  
   550  	responseBody := make(map[string]interface{})
   551  	rawJSON := ctx.PostBody()
   552  	if len(rawJSON) == 0 {
   553  		log.Errorf("ProcessDeleteContactRequest: empty json body received")
   554  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   555  		responseBody["error"] = "empty json body received"
   556  		utils.WriteJsonResponse(ctx, responseBody)
   557  		return
   558  	}
   559  
   560  	var contact *alertutils.Contact
   561  	err := json.Unmarshal(rawJSON, &contact)
   562  	if err != nil {
   563  		log.Errorf("ProcessDeleteContactRequest: could not unmarshal json body, err=%v", err)
   564  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   565  		responseBody["error"] = err.Error()
   566  		utils.WriteJsonResponse(ctx, responseBody)
   567  		return
   568  	}
   569  
   570  	err = databaseObj.DeleteContactPoint(contact.ContactId)
   571  	if err != nil {
   572  		log.Errorf("ProcessDeleteContactRequest: could not delete contact=%+v, err=%+v", contact.ContactId, err)
   573  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   574  		responseBody["error"] = err.Error()
   575  		utils.WriteJsonResponse(ctx, responseBody)
   576  		return
   577  	}
   578  
   579  	responseBody["message"] = "Contact point deleted successfully"
   580  	utils.WriteJsonResponse(ctx, responseBody)
   581  	ctx.SetStatusCode(fasthttp.StatusOK)
   582  }
   583  
   584  func InitAlertingService(getMyIds func() []uint64) {
   585  	if databaseObj == nil {
   586  		log.Errorf("InitAlertingService, err = %+v", invalidDatabaseProvider)
   587  		return
   588  	}
   589  	myids := getMyIds()
   590  	for _, myid := range myids {
   591  
   592  		//get all alerts from database
   593  		allAlerts, err := databaseObj.GetAllAlerts(myid)
   594  		if err != nil {
   595  			log.Errorf("InitAlertingService: unable to GetAllAlerts: ,err: %+v", err)
   596  		}
   597  		for _, alertInfo := range allAlerts {
   598  			alertDataObj, err := databaseObj.GetAlert(alertInfo.AlertId)
   599  			if err != nil {
   600  				log.Errorf("InitAlertingService: unable to GetAlert with alertId %v: ,err: %+v", alertInfo.AlertId, err)
   601  			}
   602  			if alertDataObj != nil {
   603  				_, err = AddCronJob(alertDataObj)
   604  				if err != nil {
   605  					log.Errorf("InitAlertingService: could not add a new CronJob corresponding to alert=%+v, err=%+v", alertDataObj.AlertName, err)
   606  					return
   607  				}
   608  			}
   609  		}
   610  	}
   611  }
   612  
   613  func InitMinionSearchService(getMyIds func() []uint64) {
   614  	if databaseObj == nil {
   615  		log.Errorf("InitMinionSearchService, err = %+v", invalidDatabaseProvider)
   616  		return
   617  	}
   618  	myids := getMyIds()
   619  	for _, myid := range myids {
   620  
   621  		//get all alerts from database
   622  		allMinionSearches, err := databaseObj.GetAllMinionSearches(myid)
   623  		if err != nil {
   624  			log.Errorf("InitMinionSearchService: unable to GetAllAlerts: ,err: %+v", err)
   625  		}
   626  		for _, minionSearch := range allMinionSearches {
   627  			_, err = AddMinionSearchCronJob(&minionSearch)
   628  			if err != nil {
   629  				log.Errorf("InitMinionSearchService: could not add a new CronJob corresponding to alert=%+v, err=%+v", minionSearch.AlertName, err)
   630  				return
   631  			}
   632  
   633  		}
   634  	}
   635  }
   636  
   637  func ProcessCreateLogMinionSearchRequest(ctx *fasthttp.RequestCtx, org_id uint64) {
   638  	if databaseObj == nil {
   639  		responseBody := make(map[string]interface{})
   640  		log.Errorf("ProcessCreateLogMinionSearchRequest: failed to create alert, err = %+v", invalidDatabaseProvider)
   641  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   642  		responseBody["error"] = invalidDatabaseProvider
   643  		utils.WriteJsonResponse(ctx, responseBody)
   644  		return
   645  	}
   646  	responseBody := make(map[string]interface{})
   647  	var LogLinesEntry alertutils.LogLinesFile
   648  
   649  	rawJSON := ctx.PostBody()
   650  	if len(rawJSON) == 0 {
   651  		log.Errorf("ProcessCreateLogMinionSearchRequest: empty json body received")
   652  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   653  		responseBody["error"] = "empty json body received"
   654  		utils.WriteJsonResponse(ctx, responseBody)
   655  		return
   656  	}
   657  	err := json.Unmarshal(rawJSON, &LogLinesEntry)
   658  	if err != nil {
   659  		log.Errorf("ProcessCreateLogMinionSearchRequest: could not unmarshal json body, err=%v", err)
   660  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   661  		responseBody["error"] = err.Error()
   662  		utils.WriteJsonResponse(ctx, responseBody)
   663  		return
   664  	}
   665  	minionSearches := convertToSiglensAlert(LogLinesEntry)
   666  	for _, searchToBeCreated := range minionSearches {
   667  		searchToBeCreated.OrgId = org_id
   668  		searchDataObj, err := databaseObj.CreateMinionSearch(searchToBeCreated)
   669  		if err != nil {
   670  			log.Errorf("ProcessCreateLogMinionSearchRequest: could not create alert=%v, err=%v", searchToBeCreated.AlertName, err)
   671  			ctx.SetStatusCode(fasthttp.StatusBadRequest)
   672  			responseBody["error"] = err.Error()
   673  			utils.WriteJsonResponse(ctx, responseBody)
   674  			return
   675  		}
   676  		_, err = AddMinionSearchCronJob(&searchDataObj)
   677  		if err != nil {
   678  			log.Errorf("ProcessCreateLogMinionSearchRequest: could not add a new CronJob corresponding to alert=%+v, err=%+v", searchDataObj.AlertName, err)
   679  			ctx.SetStatusCode(fasthttp.StatusBadRequest)
   680  			responseBody["error"] = err.Error()
   681  			utils.WriteJsonResponse(ctx, responseBody)
   682  			return
   683  		}
   684  	}
   685  
   686  	ctx.SetStatusCode(fasthttp.StatusOK)
   687  	responseBody["message"] = "Successfully created an minion search"
   688  	utils.WriteJsonResponse(ctx, responseBody)
   689  }
   690  
   691  func convertToSiglensAlert(lmDetails alertutils.LogLinesFile) []*alertutils.MinionSearch {
   692  	var minionSearches []*alertutils.MinionSearch
   693  	for _, entry := range lmDetails.LogAlerts {
   694  		alert_id := uuid.New().String()
   695  		alert_name := entry.LogTextHash
   696  
   697  		queryParams := alertutils.QueryParams{
   698  			DataSource:    "Logs",
   699  			QueryLanguage: entry.QueryLanguage,
   700  			StartTime:     time.Now().Add(time.Duration(-15) * time.Minute).String(),
   701  			EndTime:       time.Now().String(),
   702  			QueryText:     entry.Query,
   703  		}
   704  		siglensAlert := &alertutils.MinionSearch{
   705  			AlertName:       alert_name,
   706  			AlertId:         alert_id,
   707  			State:           alertutils.Inactive,
   708  			CreateTimestamp: time.Now(),
   709  			QueryParams:     queryParams,
   710  			Repository:      entry.Repository,
   711  			Filename:        entry.Filename,
   712  			LineNumber:      entry.LineNumber,
   713  			LogText:         entry.LogText,
   714  			LogTextHash:     entry.LogTextHash,
   715  			LogLevel:        entry.LogLevel,
   716  			Condition:       alertutils.IsAbove,
   717  			Value:           float32(entry.Value),
   718  			EvalFor:         0,
   719  			EvalInterval:    1,
   720  			Message:         "Minion search " + alert_name,
   721  		}
   722  		minionSearches = append(minionSearches, siglensAlert)
   723  	}
   724  	return minionSearches
   725  }
   726  
   727  func ProcessGetMinionSearchRequest(ctx *fasthttp.RequestCtx) {
   728  	if databaseObj == nil {
   729  		responseBody := make(map[string]interface{})
   730  		log.Errorf("ProcessGetMinionSearchRequest: failed to get alert, err = %+v", invalidDatabaseProvider)
   731  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   732  		responseBody["error"] = invalidDatabaseProvider
   733  		utils.WriteJsonResponse(ctx, responseBody)
   734  		return
   735  	}
   736  
   737  	responseBody := make(map[string]interface{})
   738  	alert_id := utils.ExtractParamAsString(ctx.UserValue("alertID"))
   739  	msearch, err := databaseObj.GetMinionSearch(alert_id)
   740  	if err != nil {
   741  		log.Errorf("ProcessGetMinionSearchRequest: failed to get alert with alertId = %+v, err = %+v", alert_id, err.Error())
   742  		ctx.SetStatusCode(fasthttp.StatusBadRequest)
   743  		responseBody["error"] = err.Error()
   744  		utils.WriteJsonResponse(ctx, responseBody)
   745  		return
   746  	}
   747  
   748  	responseBody["minionsearch"] = msearch
   749  	ctx.SetStatusCode(fasthttp.StatusOK)
   750  	utils.WriteJsonResponse(ctx, responseBody)
   751  }