view current month of logs

This commit is contained in:
mappu 2017-08-13 15:47:03 +12:00
parent ca39609fef
commit 9e070d269b
4 changed files with 93 additions and 12 deletions

View File

@ -1,6 +1,7 @@
package archive
import (
"errors"
"fmt"
"regexp"
"time"
@ -48,3 +49,17 @@ func NewArchiveServer(cfg *Config) (*ArchiveServer, error) {
rxSearchRx: regexp.MustCompile(`^/([^/]+)/rx/(.*)$`),
}, nil
}
var ErrNoLogForMonth = errors.New("No logs for the selected month.")
func (this *ArchiveServer) LogFile(ls *LogSource, ym YearMonth) (string, error) {
ymIndex := ym.Index()
for _, fl := range ls.FileLocation {
if fl.StartMonth.Index() <= ymIndex && (fl.EndMonth == nil || fl.EndMonth.Index() >= ymIndex) {
return time.Date(ym.Year, ym.Month, 1, 0, 0, 0, 0, this.timezone).Format(fl.LogFilePath), nil
}
}
return "", ErrNoLogForMonth
}

View File

@ -3,7 +3,14 @@ package archive
import (
"fmt"
"html/template"
"io/ioutil"
"math"
"net/http"
"strings"
)
const (
pageNotSet int = -1
)
type ArchiveState struct {
@ -18,18 +25,60 @@ type ArchiveState struct {
}
func NewArchiveState(svr *ArchiveServer) *ArchiveState {
return &ArchiveState{svr: svr}
return &ArchiveState{
svr: svr,
page: pageNotSet,
}
}
func (this *ArchiveState) selectSource(log *LogSource) error {
logBestSlug, err := this.svr.bestSlugFor(log)
if err != nil {
return err
func (this *ArchiveState) selectSource(log *LogSource, slug string) {
this.log = log
this.logBestSlug = slug
}
// renderView renders a single page of log entries.
// - Mandatory: log, ym
// - Optional: page
func (this *ArchiveState) renderView(w http.ResponseWriter) {
if this.log == nil {
this.renderError(w, "Invalid log source selected")
return
}
this.log = log
this.logBestSlug = logBestSlug
return nil
fname, err := this.svr.LogFile(this.log, this.ym)
if err != nil {
this.renderError(w, err.Error())
return
}
fc, err := ioutil.ReadFile(fname)
if err != nil {
this.renderError(w, err.Error())
return
}
lines := strings.Split(string(fc), "\n")
this.highestPage = int(math.Ceil(float64(len(lines))/float64(this.svr.cfg.LinesPerPage))) - 1
if this.page == pageNotSet || this.page > this.highestPage {
this.page = this.highestPage
}
if this.page < 0 {
this.page = 0
}
startLine := this.svr.cfg.LinesPerPage * this.page
endLine := this.svr.cfg.LinesPerPage * (this.page + 1)
if endLine > len(lines) {
endLine = len(lines)
}
output := ""
for i := startLine; i < endLine; i += 1 {
output += template.HTMLEscapeString(lines[i]) + "<br>\n"
}
this.renderTemplate(w, []byte(output))
}
func (this *ArchiveState) renderError(w http.ResponseWriter, msg string) {
@ -105,12 +154,13 @@ func (this *ArchiveState) renderTemplateHead(w http.ResponseWriter) {
// Generate month dropdown options
lastY := -1
for ympair := this.log.EarliestDate(); !ympair.Equals(this.log.LatestDate()); ympair = ympair.Next() {
limit := this.log.LatestDate().Next() // one off the end
for ympair := this.log.EarliestDate(); !ympair.Equals(limit); ympair = ympair.Next() {
if ympair.Year != lastY {
if lastY != -1 {
w.Write([]byte(`</optgroup>`))
}
w.Write([]byte(`<optgroup label="` + fmt.Sprintf("%s", ympair.Year) + `">`))
w.Write([]byte(`<optgroup label="` + fmt.Sprintf("%d", ympair.Year) + `">`))
lastY = ympair.Year
}

View File

@ -7,6 +7,7 @@ import (
"net/http"
"net/url"
"strconv"
"time"
)
func (this *ArchiveServer) lookupSourceByNumericString(slug string) *LogSource {
@ -92,8 +93,17 @@ func (this *ArchiveServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} else if r.URL.Path == `/download` {
arc.renderError(w, "Not implemented.") // FIXME
} else if this.rxViewRoot.MatchString(r.URL.Path) {
arc.renderError(w, "Not implemented.") // FIXME
} else if matches := this.rxViewRoot.FindStringSubmatch(r.URL.Path); len(matches) > 0 {
if ls := this.lookupSource(matches[1]); ls != nil {
arc.selectSource(ls, matches[1])
y, _ := strconv.Atoi(matches[2])
m, _ := strconv.Atoi(matches[3])
arc.ym = YearMonth{Year: y, Month: time.Month(m)} // 1-based months
arc.renderView(w)
} else {
arc.renderError(w, fmt.Sprintf("Unknown source '%s'", matches[1]))
}
} else if this.rxViewPage.MatchString(r.URL.Path) {
arc.renderError(w, "Not implemented.") // FIXME

View File

@ -26,3 +26,9 @@ func (ym YearMonth) Next() YearMonth {
return YearMonth{Year: ym.Year, Month: ym.Month + 1}
}
}
// Index returns a single int that can be used to compare this YearMonth with
// other YearMonth objects.
func (ym YearMonth) Index() int {
return (ym.Year * 12) + (int(ym.Month) - 1)
}