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 }