Tp 28766 (#69)
* TP-28766 | Houston summary * TP-28766 | cron changes * TP-28766 | update * TP-28766 | changes in format * TP-28766 | Team metric * TP-28766 | change config * TP-28766 | change config * TP-28766 | team metric interval change
This commit is contained in:
committed by
GitHub Enterprise
parent
cab34d6379
commit
1945df5fa5
@@ -20,6 +20,19 @@ func GetColorBySeverity(severityId uint) string {
|
||||
}
|
||||
}
|
||||
|
||||
func GetColourByOpenIncidents(openIncidents int) string {
|
||||
switch {
|
||||
case openIncidents <= 5:
|
||||
return "#50C878"
|
||||
case openIncidents <= 10:
|
||||
return "#FDDA0D"
|
||||
case openIncidents > 10:
|
||||
return "#FF0000"
|
||||
default:
|
||||
return "#808080"
|
||||
}
|
||||
}
|
||||
|
||||
func PostIncidentStatusUpdateMessage(userId, updatedStatus, channelId string, client *socketmode.Client) error {
|
||||
msgOption := slack.MsgOptionText(fmt.Sprintf("<@%s> > set status to %s", userId, updatedStatus), false)
|
||||
_, _, errMessage := client.PostMessage(channelId, msgOption)
|
||||
@@ -54,4 +67,4 @@ func RemoveDuplicateStr(strSlice []string) []string {
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,9 @@ cron.job.update.incident.interval=CRON_JOB_UPDATE_INCIDENT_INTERVAL
|
||||
cron.job.lock.default.time.in.sec=CRON_JOB_LOCK_DEFAULT_TIME_IN_SEC
|
||||
cron.job.lock.ticker.time.in.sec=CRON_JOB_LOCK_TICKER_TIME_IN_SEC
|
||||
cron.job.name=CRON_JOB_NAME
|
||||
cron.job.team.metric=CRON_JOB_TEAM_METRIC
|
||||
cron.job.team.metric.interval=CRON_JOB_TEAM_METRIC_INTERVAL
|
||||
team.metric.update.channel=TEAM_METRIC_UPDATE_CHANNEL_ID
|
||||
|
||||
#incidents
|
||||
incidents.show.limit=INCIDENTS_SHOW_LIMIT
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"houston/common/util"
|
||||
"houston/internal/processor/action"
|
||||
"houston/model/incident"
|
||||
"houston/model/severity"
|
||||
@@ -21,14 +22,24 @@ import (
|
||||
|
||||
func RunJob(socketModeClient *socketmode.Client, db *gorm.DB, logger *zap.Logger, incidentService *incident.Repository, severityService *severity.Repository, teamService *team.Repository, shedlockService *shedlock.Repository) {
|
||||
|
||||
//HOUSTON ESCALATE
|
||||
shedlockConfig := NewLockerDbWithLockTime(viper.GetInt("cron.job.lock.default.time.in.sec"))
|
||||
|
||||
err := shedlockConfig.AddFun(viper.GetString("cron.job.name"), viper.GetString("cron.job.update.incident.interval"), shedlockService, func() {
|
||||
UpdateIncidentByCronJob(socketModeClient, db, logger, incidentService, teamService, severityService, viper.GetString("cron.job.name"))
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
logger.Error("HOUSTON_ESCALATE error: " + err.Error())
|
||||
}
|
||||
|
||||
//HOUSTON DAILY TEAM UPDATE
|
||||
err = shedlockConfig.AddFun(viper.GetString("cron.job.team.metric"), viper.GetString("cron.job.team.metric.interval"), shedlockService, func() {
|
||||
postTeamMetrics(socketModeClient, db, logger, incidentService, teamService, severityService, viper.GetString("cron.job.team.metric"))
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("HOUSTON_TEAM_METRICS error :" + err.Error())
|
||||
}
|
||||
|
||||
shedlockConfig.Start()
|
||||
|
||||
}
|
||||
@@ -128,3 +139,142 @@ func updatingSevForEachInc(logger *zap.Logger, incidents []incident.IncidentEnti
|
||||
logger.Error("PostMessage failed for cronJob ", zap.Error(errMessage), zap.Int("incidentId", int(incidents[i].ID)))
|
||||
}
|
||||
}
|
||||
|
||||
func postTeamMetrics(socketModeClient *socketmode.Client, db *gorm.DB, logger *zap.Logger, incidentService *incident.Repository, teamService *team.Repository, severityService *severity.Repository, name string) {
|
||||
fmt.Println("Running Team Metrics cron at", time.Now().Format(time.RFC3339))
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logger.Error(fmt.Sprintf("Exception occurred in cron: %v", r.(error)))
|
||||
}
|
||||
}()
|
||||
|
||||
teams, err := teamService.GetAllActiveTeams()
|
||||
if err != nil {
|
||||
logger.Error("GetAllActiveTeams error", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
teamsList := *teams
|
||||
//Do not need to fetch Severity every time, hence keeping a map outside.
|
||||
incidentSeverityList, err := severityService.GetAllActiveSeverity()
|
||||
if err != nil || incidentSeverityList == nil {
|
||||
logger.Error("GetAllActiveSeverity error in cron Job",
|
||||
zap.String("cron_name", name), zap.Error(err))
|
||||
return
|
||||
}
|
||||
severityMap := convertSeverityListToMap(*incidentSeverityList)
|
||||
|
||||
for i := 0; i < len(teamsList); i++ {
|
||||
incidents, err := incidentService.GetIncidentsByTeamIdAndNotResolved(teamsList[i].ID)
|
||||
if err != nil {
|
||||
logger.Error("GetIncidentsByTeamIdAndNotResolved error in cron Job",
|
||||
zap.String("cron_name", name), zap.Error(err))
|
||||
continue
|
||||
}
|
||||
incidentsList := *incidents
|
||||
|
||||
list := make([]incident.SlackChannelWithResponderId, 0, len(incidentsList))
|
||||
for j := 0; j < len(incidentsList); j++ {
|
||||
//RESPONDER
|
||||
incidentRole, err := incidentService.GetIncidentRoleByIncidentIdAndRole(incidentsList[j].ID, incident.Responder)
|
||||
if err != nil {
|
||||
logger.Error("GetIncidentRoleByIncidentIdAndRole error in cron Job",
|
||||
zap.String("cron_name", name), zap.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
// map to pojo and to list
|
||||
obj := incident.SlackChannelWithResponderId{
|
||||
SlackChannel: incidentsList[j].SlackChannel,
|
||||
ResponderId: incidentRole.AssignedTo,
|
||||
CreatedAt: incidentsList[j].CreatedAt,
|
||||
Severity: severityMap[incidentsList[j].SeverityId],
|
||||
ManagerId: teamsList[i].ManagerHandle,
|
||||
}
|
||||
// Appending the obj to the list
|
||||
list = append(list, obj)
|
||||
}
|
||||
//Post message
|
||||
teamName := builderTeamNameHeader(teamsList[i].Name)
|
||||
openIncidentCount := buildOpenIncidentText(len(incidentsList))
|
||||
onCallAndManagerBlock := buildOnCallAndManagerBlock(teamsList[i].OncallHandle, teamsList[i].ManagerHandle)
|
||||
blocks := IncidentMetricBlock(teamName, openIncidentCount, onCallAndManagerBlock)
|
||||
//On the basis of no of incidents, change colour
|
||||
color := util.GetColourByOpenIncidents(len(incidentsList))
|
||||
att := slack.Attachment{Blocks: blocks, Color: color}
|
||||
_, _, err = socketModeClient.PostMessage(viper.GetString("team.metric.update.channel"), slack.MsgOptionAttachments(att))
|
||||
|
||||
text := ""
|
||||
for index := 0; index < len(list); index++ {
|
||||
// Calculate the time difference
|
||||
currentTime := time.Now()
|
||||
duration := 5*time.Hour + 30*time.Minute
|
||||
newTime := currentTime.Add(duration)
|
||||
timeDiff := newTime.Sub(list[index].CreatedAt)
|
||||
|
||||
// Convert the duration into days and hours
|
||||
days := int(timeDiff.Hours() / 24)
|
||||
hours := int(timeDiff.Hours()) % 24
|
||||
if list[index].ResponderId == "" && list[index].ManagerId != "" {
|
||||
text += fmt.Sprintf("<#%s>'s *Severity* is `%s` assigned to *Manager* <@%s>. *Open Since*- `%dd%dhr` \n", list[index].SlackChannel, list[index].Severity, list[index].ManagerId, days, hours)
|
||||
} else if list[index].ResponderId != "" {
|
||||
text += fmt.Sprintf("<#%s>'s *Severity* is `%s` assigned to *Responder* <@%s>. *Open Since*- `%dd%dhr` \n", list[index].SlackChannel, list[index].Severity, list[index].ResponderId, days, hours)
|
||||
} else if list[index].ResponderId == "" && list[index].ManagerId == "" {
|
||||
text += fmt.Sprintf("<#%s>'s *Severity* is `%s` assigned to *No-One*. *Open Since*- `%dd%dhr` \n", list[index].SlackChannel, list[index].Severity, days, hours)
|
||||
}
|
||||
}
|
||||
|
||||
if text != "" {
|
||||
msgOption := slack.MsgOptionText(text, false)
|
||||
_, _, errMessage := socketModeClient.PostMessage(viper.GetString("team.metric.update.channel"), msgOption)
|
||||
if errMessage != nil {
|
||||
logger.Error("PostMessage failed for cronJob ", zap.Error(errMessage))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func convertSeverityListToMap(severities []severity.SeverityEntity) map[uint]string {
|
||||
severityMap := make(map[uint]string)
|
||||
|
||||
for _, severity := range severities {
|
||||
severityMap[severity.ID] = severity.Name
|
||||
}
|
||||
|
||||
return severityMap
|
||||
}
|
||||
|
||||
func IncidentMetricBlock(teamName *slack.HeaderBlock, incidentOpenCount *slack.SectionBlock, onCallAndManagerBlock *slack.SectionBlock) slack.Blocks {
|
||||
return slack.Blocks{
|
||||
BlockSet: []slack.Block{
|
||||
teamName,
|
||||
incidentOpenCount,
|
||||
onCallAndManagerBlock,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func builderTeamNameHeader(teamName string) *slack.HeaderBlock {
|
||||
headerText := slack.NewTextBlockObject(slack.PlainTextType, teamName, true, false)
|
||||
headerSection := slack.NewHeaderBlock(headerText)
|
||||
|
||||
return headerSection
|
||||
}
|
||||
|
||||
func buildOpenIncidentText(count int) *slack.SectionBlock {
|
||||
sectionBlock := slack.NewTextBlockObject(slack.PlainTextType, fmt.Sprintf("Open Incidents: %d", count), true, false)
|
||||
headerSection := slack.NewSectionBlock(sectionBlock, nil, nil)
|
||||
|
||||
return headerSection
|
||||
}
|
||||
|
||||
func buildOnCallAndManagerBlock(onCallHandle string, managerHandle string) *slack.SectionBlock {
|
||||
fields := []*slack.TextBlockObject{
|
||||
slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("*OnCall*\n<@%s>", onCallHandle), false, false),
|
||||
slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("*Manager*\n<@%s>", managerHandle), false, false),
|
||||
}
|
||||
block := slack.NewSectionBlock(nil, fields, nil)
|
||||
|
||||
return block
|
||||
}
|
||||
|
||||
@@ -380,3 +380,25 @@ func (r *Repository) FindIncidentsByNotResolvedStatusAndGreaterSeverityTatThanCu
|
||||
|
||||
return incidentEntity, nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetIncidentsByTeamIdAndNotResolved(team_id uint) (*[]IncidentEntity, error) {
|
||||
var incidentEntity []IncidentEntity
|
||||
|
||||
result := r.gormClient.Order("severity_id").Find(&incidentEntity, "team_id = ? and status <> ?", team_id, 4)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
return &incidentEntity, nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetIncidentRoleByIncidentIdAndRole(incident_id uint, role string) (*IncidentRoleEntity, error) {
|
||||
var incidentRoleEntity IncidentRoleEntity
|
||||
|
||||
result := r.gormClient.Find(&incidentRoleEntity, "incident_id = ? and role = ? and deleted_at IS NULL", incident_id, role)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
return &incidentRoleEntity, nil
|
||||
}
|
||||
|
||||
@@ -50,3 +50,11 @@ type AddIncidentStatusRequest struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
type SlackChannelWithResponderId struct {
|
||||
SlackChannel string `json:"slack_channel,omitempty"`
|
||||
ResponderId string `json:"responder_id,omitempty"`
|
||||
CreatedAt time.Time
|
||||
Severity string
|
||||
ManagerId string
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ type TeamEntity struct {
|
||||
OncallHandle string `gorm:"column:oncall_handle"`
|
||||
Active bool `gorm:"column:active"`
|
||||
WebhookSlackChannel string `gorm:"column:webhook_slack_channel"`
|
||||
ManagerHandle string `gorm:"column:manager_handle"`
|
||||
}
|
||||
|
||||
func (TeamEntity) TableName() string {
|
||||
|
||||
Reference in New Issue
Block a user