1// Copyright 2017 The Hugo Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package helpers
15
16import (
17	"io"
18	"strconv"
19	"sync/atomic"
20
21	"github.com/olekukonko/tablewriter"
22)
23
24// ProcessingStats represents statistics about a site build.
25type ProcessingStats struct {
26	Name string
27
28	Pages           uint64
29	PaginatorPages  uint64
30	Static          uint64
31	ProcessedImages uint64
32	Files           uint64
33	Aliases         uint64
34	Sitemaps        uint64
35	Cleaned         uint64
36}
37
38type processingStatsTitleVal struct {
39	name string
40	val  uint64
41}
42
43func (s *ProcessingStats) toVals() []processingStatsTitleVal {
44	return []processingStatsTitleVal{
45		{"Pages", s.Pages},
46		{"Paginator pages", s.PaginatorPages},
47		{"Non-page files", s.Files},
48		{"Static files", s.Static},
49		{"Processed images", s.ProcessedImages},
50		{"Aliases", s.Aliases},
51		{"Sitemaps", s.Sitemaps},
52		{"Cleaned", s.Cleaned},
53	}
54}
55
56// NewProcessingStats returns a new ProcessingStats instance.
57func NewProcessingStats(name string) *ProcessingStats {
58	return &ProcessingStats{Name: name}
59}
60
61// Incr increments a given counter.
62func (s *ProcessingStats) Incr(counter *uint64) {
63	atomic.AddUint64(counter, 1)
64}
65
66// Add adds an amount to a given counter.
67func (s *ProcessingStats) Add(counter *uint64, amount int) {
68	atomic.AddUint64(counter, uint64(amount))
69}
70
71// Table writes a table-formatted representation of the stats in a
72// ProcessingStats instance to w.
73func (s *ProcessingStats) Table(w io.Writer) {
74	titleVals := s.toVals()
75	data := make([][]string, len(titleVals))
76	for i, tv := range titleVals {
77		data[i] = []string{tv.name, strconv.Itoa(int(tv.val))}
78	}
79
80	table := tablewriter.NewWriter(w)
81
82	table.AppendBulk(data)
83	table.SetHeader([]string{"", s.Name})
84	table.SetBorder(false)
85	table.Render()
86}
87
88// ProcessingStatsTable writes a table-formatted representation of stats to w.
89func ProcessingStatsTable(w io.Writer, stats ...*ProcessingStats) {
90	names := make([]string, len(stats)+1)
91
92	var data [][]string
93
94	for i := 0; i < len(stats); i++ {
95		stat := stats[i]
96		names[i+1] = stat.Name
97
98		titleVals := stat.toVals()
99
100		if i == 0 {
101			data = make([][]string, len(titleVals))
102		}
103
104		for j, tv := range titleVals {
105			if i == 0 {
106				data[j] = []string{tv.name, strconv.Itoa(int(tv.val))}
107			} else {
108				data[j] = append(data[j], strconv.Itoa(int(tv.val)))
109			}
110		}
111
112	}
113
114	table := tablewriter.NewWriter(w)
115
116	table.AppendBulk(data)
117	table.SetHeader(names)
118	table.SetBorder(false)
119	table.Render()
120}
121