{"record":{"id":"5eca79fce10f12b2","repo":"vitessio/vitess","slug":"malformed-logfile-name-v","errorCode":null,"errorMessage":"malformed logfile name: %v","messagePattern":"malformed logfile name: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"go/vt/logutil/purge.go","lineNumber":55,"sourceCode":")\n\n// RegisterFlags installs logutil flags on the given FlagSet.\n//\n// `go/cmd/*` entrypoints should either use servenv.ParseFlags(WithArgs)? which\n// calls this function, or call this function directly before parsing\n// command-line arguments.\nfunc RegisterFlags(fs *pflag.FlagSet) {\n\tutils.SetFlagDurationVar(fs, &keepLogsByCtime, \"keep-logs\", keepLogsByCtime, \"keep logs for this long (using ctime) (zero to keep forever)\")\n\tutils.SetFlagDurationVar(fs, &keepLogsByMtime, \"keep-logs-by-mtime\", keepLogsByMtime, \"keep logs for this long (using mtime) (zero to keep forever)\")\n\tutils.SetFlagDurationVar(fs, &purgeLogsInterval, \"purge-logs-interval\", purgeLogsInterval, \"how often try to remove old logs\")\n}\n\n// parse parses a file name (as used by glog) and returns its process\n// name and timestamp.\nfunc parseCreatedTimestamp(filename string) (timestamp time.Time, err error) {\n\tparts := strings.Split(filepath.Base(filename), \".\")\n\tif len(parts) < 6 {\n\t\treturn time.Time{}, fmt.Errorf(\"malformed logfile name: %v\", filename)\n\t}\n\treturn time.ParseInLocation(\"20060102-150405\", parts[len(parts)-2], time.Now().Location())\n}\n\nfunc getModifiedTimestamp(filename string) (timestamp time.Time, err error) {\n\tfileInfo, err := os.Stat(filename)\n\tif err != nil {\n\t\treturn time.Time{}, err\n\t}\n\treturn fileInfo.ModTime(), nil\n}\n\nvar levels = []string{\"INFO\", \"ERROR\", \"WARNING\", \"FATAL\"}\n\n// purgeLogsOnce removes logfiles for program for dir, if their age\n// relative to now is greater than [cm]timeDelta\nfunc purgeLogsOnce(now time.Time, dir, program string, ctimeDelta time.Duration, mtimeDelta time.Duration) {\n\tcurrent := make(map[string]bool)","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/logutil/purge.go#L37-L73","documentation":"logutil.purgeCreatedTimestamp parses glog-style log filenames, which have the form program.host.user.log.NAME.yyyymmdd-hhmmss.pid. The library throws this when the base name splits into fewer than 6 dot-separated parts, meaning the file does not follow the glog naming convention and no creation timestamp can be extracted.","triggerScenarios":"purgeLogsOnce scanning a log directory that contains non-glog files (e.g. 'app.log', rotated files renamed by logrotate, hand-created symlinks or marker files), or filenames truncated/renamed so fewer than 6 segments remain.","commonSituations":"Log directories shared with non-Vitess tooling, logrotate renaming files ('.1', '.gz'), operators manually renaming logs to keep them, tmp files created by editors in the log dir.","solutions":["Move or exclude non-glog-named files from the log directory being purged.","Restore the original glog naming (program.host.user.log.NAME.yyyymmdd-hhmmss.pid) for files you want purged.","Configure the purge tool's directory to a location containing only Vitess glog files.","Check the failing filename in the error (%v) and rename/repair it or delete it."],"exampleFix":"// before (in the purge dir)\nvttablet.log.1            // malformed, triggers error\n// after (rename to glog format)\nvttablet.host.user.log.ERROR.20260901-120000.1234","handlingStrategy":"type-guard","validationCode":"func isGlogFilename(name string) bool {\n\treturn len(strings.Split(filepath.Base(name), \".\")) >= 6\n}","typeGuard":"func looksLikeGlogLog(filename string) bool {\n\tparts := strings.Split(filepath.Base(filename), \".\")\n\tif len(parts) < 6 {\n\t\treturn false\n\t}\n\t_, err := time.ParseInLocation(\"20060102-150405\", parts[len(parts)-2], time.Local)\n\treturn err == nil\n}","tryCatchPattern":"ts, err := logutil.ParseCreatedTimestamp(f) // if exported, or guard before purge\nif err != nil {\n\tlog.Warn(\"skipping non-glog file\", slog.String(\"file\", f))\n\tcontinue\n}","preventionTips":["Keep the purge target directory exclusive to Vitess glog output","Exclude logrotate-renamed archives from the purge directory","Never manually rename glog files; copy instead if archiving"],"tags":["go","logging","file-parsing","purge"],"backgroundTag":"malformed-log-filename","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}