Commit df0f51db authored by John Jarvis's avatar John Jarvis Committed by Victor Lopez

Upload graphs as attachments.

parent eb4e3979
.settings.yaml
oncall-robot-assistant
vendor
......@@ -10,7 +10,7 @@ tasks. It's main purpose to help generate the weekly reports.
* `dep init`
* `go build`
* `go install`
* Copy `settings-example.yaml` to `.settings.yaml` and update the pagerduty and gitlab token.
* Copy `settings-example.yaml` to `.settings.yaml` and update the pagerduty, grafana and gitlab tokens.
* `./on-call-robot-assistant`
This will create an issue link, modify the issue as you see fit
......
......@@ -39,6 +39,7 @@ type Config struct {
DayOffset int `yaml:"day_offset"`
OncallLabel string `yaml:"oncall_label"`
WeeklyOps []WeeklyOps `yaml:"weekly_ops"`
GrafanaKey string `yaml:"grafana_key"`
}
// Parses the yaml configuration from a reader
......
......@@ -17,10 +17,24 @@ func main() {
if err != nil {
log.Fatalln(err)
}
desc := oncall.GenerateTemplate(config)
fmt.Println("Downloading graphs from performance ...")
start := time.Now()
graphs := oncall.DownloadGraphs(config)
secs := time.Since(start).Seconds()
fmt.Printf(" %d graphs took %.2f seconds to download\n", len(graphs), secs)
fmt.Println("Uploading graphs to Gitlab project ...")
start = time.Now()
weekly_ops_graphs := oncall.UploadGraphs(config, graphs)
secs = time.Since(start).Seconds()
fmt.Printf(" Completed upload in %.2f seconds\n", secs)
desc := oncall.GenerateTemplate(config, weekly_ops_graphs)
title := "OnCall report for period: " +
time.Now().UTC().AddDate(0, 0, -7).Format("2006-01-02") +
" - " + time.Now().UTC().Format("2006-01-02")
fmt.Println("Creating issue ...")
issue := oncall.CreateReportIssue(config, title, desc.String())
fmt.Println("Created issue ", issue.WebURL)
......
......@@ -7,18 +7,6 @@ import (
"time"
)
func CreateReportIssue(config *config.Config, title string, report string) *gitlab.Issue {
git := gitlab.NewClient(nil, config.GitLab.Token)
opts := gitlab.CreateIssueOptions{}
opts.Title = &title
opts.Description = &report
if issue, _, err := git.Issues.CreateIssue(config.ProjectId, &opts); err != nil {
panic(err)
} else {
return issue
}
}
func getIssuesClosedDuringMilestone(config *config.Config) []*gitlab.Issue {
git := gitlab.NewClient(nil, config.GitLab.Token)
labels := []string{config.OncallLabel}
......
package oncall
import (
"bytes"
"fmt"
gitlab "github.com/xanzy/go-gitlab"
config "gitlab.com/gl-infra/oncall-robot-assistant/config"
"io/ioutil"
"log"
"net/http"
"os"
"path"
"sync"
"text/template"
"time"
)
type GraphData struct {
Fname string
Name string
Url string
Info string
}
func UploadGraphs(config *config.Config, graphs <-chan GraphData) (ops_graphs []WeeklyOpsGraph) {
git := gitlab.NewClient(nil, config.GitLab.Token)
for graph := range graphs {
defer os.Remove(graph.Fname)
ops_graph := WeeklyOpsGraph{}
fmt.Println(" uploading", graph.Name)
pf, _, err := git.Projects.UploadFile(config.ProjectId, graph.Fname)
if err != nil {
panic(err)
}
ops_graph.Url = pf.URL
ops_graph.Name = graph.Name
ops_graphs = append(ops_graphs, ops_graph)
}
return ops_graphs
}
func DownloadGraphs(config *config.Config) (graphs <-chan GraphData) {
var wg sync.WaitGroup
num_graphs := len(weeklyOpsGraphs(config))
ch := make(chan GraphData, num_graphs)
wg.Add(num_graphs)
for _, graph := range weeklyOpsGraphs(config) {
go MakeRequest(graph.Url, graph.Name, ch, &wg, config.GrafanaKey)
}
wg.Wait()
close(ch)
return ch
}
func MakeRequest(url string, name string, ch chan<- GraphData, wg *sync.WaitGroup, grafana_key string) {
defer wg.Done()
start := time.Now()
file, _ := ioutil.TempFile(os.TempDir(), "oncall-graph")
graph_data := GraphData{}
client := &http.Client{}
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+grafana_key)
resp, err := client.Do(req)
defer resp.Body.Close()
if err != nil {
panic(err)
}
secs := time.Since(start).Seconds()
body, _ := ioutil.ReadAll(resp.Body)
err = ioutil.WriteFile(file.Name(), body, 0644)
if err != nil {
panic(err)
}
graph_data.Name = name
graph_data.Url = url
graph_data.Fname = file.Name()
graph_data.Info = fmt.Sprintf("%.2f elapsed with response length: %d %s", secs, len(body), url)
ch <- graph_data
}
func CreateReportIssue(config *config.Config, title string, report string) *gitlab.Issue {
git := gitlab.NewClient(nil, config.GitLab.Token)
opts := gitlab.CreateIssueOptions{}
opts.Title = &title
opts.Description = &report
if issue, _, err := git.Issues.CreateIssue(config.ProjectId, &opts); err != nil {
panic(err)
} else {
return issue
}
}
func weeklyOpsGraphs(config *config.Config) (graphs []WeeklyOpsGraph) {
for _, graph := range config.WeeklyOps {
ops_graph := WeeklyOpsGraph{}
ops_graph.Name = graph.Name
millis_to := time.Now().UnixNano() / 1000000
millis_from := millis_to - (86400000 * int64(config.DayOffset))
ops_graph.Url = graph.Url + fmt.Sprintf("&from=%d&to=%d", millis_from, millis_to)
graphs = append(graphs, ops_graph)
}
return graphs
}
func GenerateTemplate(config *config.Config, weekly_ops_graphs []WeeklyOpsGraph) *bytes.Buffer {
template_data := TemplateData{}
for _, schd := range config.PagerDuty.Schedules {
onCallUsers := getOncallPersons(config, schd.Id)
for _, u := range onCallUsers {
otm := OnCallTeamMember{}
otm.Schedule = schd.Name
otm.User = u.Name
template_data.OnCallTeamMembers = append(template_data.OnCallTeamMembers, otm)
}
}
incidents := getOncallIncidents(config)
template_data.IncidentCount = len(incidents)
// Populate list of incidents for the template
for _, p := range incidents {
inc := Incident{}
inc.Summary = p.Summary
inc.Url = p.HTMLURL
inc.CreatedAt = p.CreatedAt
template_data.Incidents = append(template_data.Incidents, inc)
}
oncall_issues := getIssuesOpenedDuringShift(config)
closed_issues := getIssuesClosedDuringMilestone(config)
all_open_issues := getIssuesOpenAll(config)
// Issue stats
template_data.IssuesOpenedDuringShift.Count = len(oncall_issues)
template_data.IssuesOpenedDuringShift.AccessRequest = len(filterIssuesByLabel("access request", oncall_issues))
template_data.IssuesOpenedDuringShift.Critical = len(filterIssuesByLabel("critical", oncall_issues))
template_data.IssuesClosedDuringMilestone.Count = len(closed_issues)
template_data.IssuesClosedDuringMilestone.AccessRequest = len(filterIssuesByLabel("access request", closed_issues))
template_data.IssuesClosedDuringMilestone.Critical = len(filterIssuesByLabel("critical", closed_issues))
template_data.IssuesOpenAll.Count = len(all_open_issues)
template_data.IssuesOpenAll.AccessRequest = len(filterIssuesByLabel("access request", all_open_issues))
template_data.IssuesOpenAll.Critical = len(filterIssuesByLabel("critical", all_open_issues))
// Populate list of issues for the template
for _, p := range all_open_issues {
issue := Issue{}
created := p.CreatedAt.Format(time.RFC822)
if p.Assignee.Username == "" {
p.Assignee.Username = "unassigned"
}
issue.CreatedAt = created
issue.Summary = p.Title
issue.Url = p.WebURL
issue.Assignee = p.Assignee.Username
template_data.Issues = append(template_data.Issues, issue)
}
// Populate weekly ops graphs for template using uploaded files
for _, graph := range weekly_ops_graphs {
template_data.WeeklyOpsGraphs = append(template_data.WeeklyOpsGraphs, graph)
}
ex, err := os.Executable()
if err != nil {
log.Fatal(err)
}
dir := path.Dir(ex)
tmpl, err := template.New("on-call-report.tmpl").
ParseFiles(path.Join(dir, "./templates/on-call-report.tmpl"))
var desc bytes.Buffer
tmpl.Execute(&desc, template_data)
return &desc
}
package oncall
import (
"bytes"
"fmt"
config "gitlab.com/gl-infra/oncall-robot-assistant/config"
"log"
"os"
"path"
"text/template"
"time"
)
type WeeklyOpsGraph struct {
Name string
Url string
......@@ -51,77 +40,3 @@ type TemplateData struct {
IssuesOpenedDuringShift IssueStats
IssuesClosedDuringMilestone IssueStats
}
func GenerateTemplate(config *config.Config) *bytes.Buffer {
template_data := TemplateData{}
for _, schd := range config.PagerDuty.Schedules {
onCallUsers := getOncallPersons(config, schd.Id)
for _, u := range onCallUsers {
otm := OnCallTeamMember{}
otm.Schedule = schd.Name
otm.User = u.Name
template_data.OnCallTeamMembers = append(template_data.OnCallTeamMembers, otm)
}
}
incidents := getOncallIncidents(config)
template_data.IncidentCount = len(incidents)
// Populate list of incidents for the template
for _, p := range incidents {
inc := Incident{}
inc.Summary = p.Summary
inc.Url = p.HTMLURL
inc.CreatedAt = p.CreatedAt
template_data.Incidents = append(template_data.Incidents, inc)
}
oncall_issues := getIssuesOpenedDuringShift(config)
closed_issues := getIssuesClosedDuringMilestone(config)
all_open_issues := getIssuesOpenAll(config)
// Issue stats
template_data.IssuesOpenedDuringShift.Count = len(oncall_issues)
template_data.IssuesOpenedDuringShift.AccessRequest = len(filterIssuesByLabel("access request", oncall_issues))
template_data.IssuesOpenedDuringShift.Critical = len(filterIssuesByLabel("critical", oncall_issues))
template_data.IssuesClosedDuringMilestone.Count = len(closed_issues)
template_data.IssuesClosedDuringMilestone.AccessRequest = len(filterIssuesByLabel("access request", closed_issues))
template_data.IssuesClosedDuringMilestone.Critical = len(filterIssuesByLabel("critical", closed_issues))
template_data.IssuesOpenAll.Count = len(all_open_issues)
template_data.IssuesOpenAll.AccessRequest = len(filterIssuesByLabel("access request", all_open_issues))
template_data.IssuesOpenAll.Critical = len(filterIssuesByLabel("critical", all_open_issues))
// Populate list of issues for the template
for _, p := range all_open_issues {
issue := Issue{}
created := p.CreatedAt.Format(time.RFC822)
if p.Assignee.Username == "" {
p.Assignee.Username = "unassigned"
}
issue.CreatedAt = created
issue.Summary = p.Title
issue.Url = p.WebURL
issue.Assignee = p.Assignee.Username
template_data.Issues = append(template_data.Issues, issue)
}
// Populate weekly ops graphs for template
for _, graph := range config.WeeklyOps {
ops_graph := WeeklyOpsGraph{}
ops_graph.Name = graph.Name
millis_to := time.Now().UnixNano() / 1000000
millis_from := millis_to - (86400000 * int64(config.DayOffset))
ops_graph.Url = graph.Url + fmt.Sprintf("&from=%d&to=%d", millis_from, millis_to)
template_data.WeeklyOpsGraphs = append(template_data.WeeklyOpsGraphs, ops_graph)
}
ex, err := os.Executable()
if err != nil {
log.Fatal(err)
}
dir := path.Dir(ex)
tmpl, err := template.New("on-call-report.tmpl").
ParseFiles(path.Join(dir, "./templates/on-call-report.tmpl"))
var desc bytes.Buffer
tmpl.Execute(&desc, template_data)
return &desc
}
......@@ -15,6 +15,9 @@ oncall_label: oncall
# issues
milestone: WoW
# API key for grafana
# 1Password oncall-robot grafana api key
grafana_key: "*** GRAFANA API KEY GOES HERE ***"
# Pagerduty configuration
pagerduty:
token: "*** PD API TOKEN GOES HERE ***"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment