// 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
}
Beispiel #2
0
// 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)
}