github.com/mentimeter/morty@v1.2.2-0.20221012065510-5596adecd154/mortems/readme.go (about)

     1  package mortems
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"time"
     7  )
     8  
     9  func GenerateReadme(mortems []MortemData) string {
    10  	months := make(map[string][]MortemData)
    11  
    12  	monthYearFormat := "January 2006"
    13  
    14  	for _, mortem := range mortems {
    15  		month := mortem.Date.Format(monthYearFormat)
    16  		months[month] = append(months[month], mortem)
    17  	}
    18  
    19  	readme := "# Post-Mortems\n"
    20  
    21  	readme += "#### [How to Post-Mortem](/post-mortems)\n"
    22  	readme += "## Overall Statistics\n"
    23  	readme += metricsTable(metrics(mortems))
    24  
    25  	sortedMonths := []string{}
    26  	for month := range months {
    27  		sortedMonths = append(sortedMonths, month)
    28  	}
    29  
    30  	sort.Slice(sortedMonths, func(i, j int) bool {
    31  		timeI, _ := time.Parse(monthYearFormat, sortedMonths[i])
    32  		timeJ, _ := time.Parse(monthYearFormat, sortedMonths[j])
    33  
    34  		return timeI.After(timeJ)
    35  	})
    36  
    37  	for _, month := range sortedMonths {
    38  		readme += monthSection(month, months[month])
    39  	}
    40  
    41  	return readme
    42  }
    43  
    44  func monthSection(month string, mortems []MortemData) string {
    45  	section := "### " + month + "\n"
    46  	section += metricsTable(metrics(mortems))
    47  
    48  	for _, m := range mortems {
    49  		section += fmt.Sprintf("- [%s](%s)\n", m.Title, m.File)
    50  	}
    51  
    52  	section += "\n"
    53  
    54  	return section
    55  }
    56  
    57  func metricsTable(detect, resolve, down string) string {
    58  	return fmt.Sprintf(`| Average Detection Time | Average Resolve Time | Average Downtime |
    59  | --- | --- | --- |
    60  | %s | %s | %s |
    61  `, detect, resolve, down)
    62  }
    63  
    64  func metrics(mortems []MortemData) (string, string, string) {
    65  	if len(mortems) == 0 {
    66  		return "", "", ""
    67  	}
    68  
    69  	detectTotal := 0
    70  	resolveTotal := 0
    71  	downTotal := 0
    72  
    73  	for _, m := range mortems {
    74  		detectTotal += int(m.Detect)
    75  		resolveTotal += int(m.Resolve)
    76  		downTotal += int(m.Downtime)
    77  	}
    78  
    79  	detectAvg := detectTotal / len(mortems)
    80  	resolveAvg := resolveTotal / len(mortems)
    81  	downAvg := downTotal / len(mortems)
    82  
    83  	detect := prettyTime(detectAvg)
    84  	resolve := prettyTime(resolveAvg)
    85  	down := prettyTime(downAvg)
    86  
    87  	return detect, resolve, down
    88  }
    89  
    90  func prettyTime(t int) string {
    91  	dur := time.Duration(t)
    92  
    93  	if dur > time.Hour {
    94  		return fmt.Sprintf("%.0f hours", dur.Hours())
    95  	} else if dur > time.Minute {
    96  		return fmt.Sprintf("%.0f minutes", dur.Minutes())
    97  	} else {
    98  		return fmt.Sprintf("%.0f seconds", dur.Seconds())
    99  	}
   100  }