blob: b694f1f8368c1c26d32207802ded956de7ecb371 [file] [log] [blame]
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package processlog
import (
"strings"
"time"
)
import (
"github.com/apache/dubbo-go-pixiu/tools/bug-report/pkg/config"
"github.com/apache/dubbo-go-pixiu/tools/bug-report/pkg/util/match"
)
const (
levelFatal = "fatal"
levelError = "error"
levelWarn = "warn"
levelInfo = "info"
levelDebug = "debug"
levelTrace = "trace"
)
// Stats represents log statistics.
type Stats struct {
numFatals int
numErrors int
numWarnings int
}
// Importance returns an integer that indicates the importance of the log, based on the given Stats in s.
// Larger numbers are more important.
func (s *Stats) Importance() int {
if s == nil {
return 0
}
return 1000*s.numFatals + 100*s.numErrors + 10*s.numWarnings
}
// Process processes logStr based on the supplied config and returns the processed log along with statistics on it.
func Process(config *config.BugReportConfig, logStr string) (string, *Stats) {
out := getTimeRange(logStr, config.StartTime, config.EndTime)
return out, getStats(config, out)
}
// getTimeRange returns the log lines that fall inside the start to end time range, inclusive.
func getTimeRange(logStr string, start, end time.Time) string {
var sb strings.Builder
write := false
for _, l := range strings.Split(logStr, "\n") {
t, _, _, valid := processLogLine(l)
if valid {
write = false
if (t.Equal(start) || t.After(start)) && (t.Equal(end) || t.Before(end)) {
write = true
}
}
if write {
sb.WriteString(l)
sb.WriteString("\n")
}
}
return sb.String()
}
// getStats returns statistics for the given log string.
func getStats(config *config.BugReportConfig, logStr string) *Stats {
out := &Stats{}
for _, l := range strings.Split(logStr, "\n") {
_, level, text, valid := processLogLine(l)
if !valid {
continue
}
switch level {
case levelFatal, levelError, levelWarn:
if match.MatchesGlobs(text, config.IgnoredErrors) {
continue
}
switch level {
case levelFatal:
out.numFatals++
case levelError:
out.numErrors++
case levelWarn:
out.numWarnings++
}
default:
}
}
return out
}
func processLogLine(line string) (timeStamp *time.Time, level string, text string, valid bool) {
lv := strings.Split(line, "\t")
if len(lv) < 3 {
return nil, "", "", false
}
ts, err := time.Parse(time.RFC3339Nano, lv[0])
if err != nil {
return nil, "", "", false
}
timeStamp = &ts
switch lv[1] {
case levelFatal, levelError, levelWarn, levelInfo, levelDebug, levelTrace:
level = lv[1]
default:
return nil, "", "", false
}
text = strings.Join(lv[2:], "\t")
valid = true
return
}