// Parse writes a csv entry for each line in the kernel log file, and returns whether the format was valid. func Parse(f string) (bool, string, []error) { var errs []error var buf bytes.Buffer csvState := csv.NewState(&buf, false) activeMap := make(map[string]*entry) curTime := int64(0) startTime := int64(0) matched := false for _, l := range strings.Split(f, "\n") { if matches, result := historianutils.SubexpNames(WakeSourceRE, l); matches { timestamp, err := bugreportutils.TimeStampToMs(result["timeStamp"], result["remainder"], time.UTC) if err != nil { errs = append(errs, err) continue } matched = true if startTime == 0 { startTime = timestamp } curTime = timestamp t := result["transitionType"] v := result["value"] e, alreadyActive := activeMap[v] switch t { case PositiveTransition: if !alreadyActive { e = &entry{timestamp, v} activeMap[v] = e } else { // Double positive transition. Ignore the event. errs = append(errs, fmt.Errorf("two positive transitions for %q, wakesource %q", KernelWakeSource, v)) continue } case NegativeTransition: if !alreadyActive { errs = append(errs, fmt.Errorf("negative transition without positive transition for %q, wakesource %q", KernelWakeSource, v)) continue } delete(activeMap, v) default: errs = append(errs, fmt.Errorf("unknown transition for %q %q", KernelWakeSource, t)) continue } csvState.AddEntry(KernelWakeSource, e, curTime) } } csvState.PrintAllReset(curTime) return matched, buf.String(), errs }
// fullTimestamp constructs the unix ms timestamp from the given date and time information. // Since event log events have no corresponding year, we reconstruct the full timestamp using // the stored reference year and month extracted from the dumpstate line of the bug report. func (p *parser) fullTimestamp(month, day, partialTimestamp, remainder string) (int64, error) { parsedMonth, err := strconv.Atoi(month) if err != nil { return 0, err } if !validMonth(parsedMonth) { return 0, fmt.Errorf("invalid month: %d", parsedMonth) } year := p.referenceYear // The reference month and year represents the time the bugreport was taken. // If the bug report event log begins near the end of a year, and rolls over to the next year, // the events will be in either the previous year to the reference year or in the reference year. // Bug reports are assumed to span at most a month, but we leave a slightly larger margin here // in case we get a slightly longer bug report. if p.referenceMonth < time.March && time.Month(parsedMonth) > time.October { year-- // Some events may still occur after the given reference date, so we check for a year rollover. } else if p.referenceMonth > time.October && time.Month(parsedMonth) < time.March { year++ } return bugreportutils.TimeStampToMs(fmt.Sprintf("%d-%s-%s %s", year, month, day, partialTimestamp), remainder, p.loc) }