| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- package configissues
- import (
- "sync"
- log "github.com/sirupsen/logrus"
- )
- var (
- storeMu sync.RWMutex
- issues []Issue
- stickyMu sync.Mutex
- sticky []Issue
- )
- // BeginConfigLoad clears sticky issues captured during config decode/include load.
- func BeginConfigLoad() {
- stickyMu.Lock()
- defer stickyMu.Unlock()
- sticky = nil
- }
- // ReportSticky records an issue that cannot be re-derived after config decode
- // (for example unset environment variables that were already expanded).
- func ReportSticky(issue Issue) {
- stickyMu.Lock()
- defer stickyMu.Unlock()
- sticky = append(sticky, issue)
- }
- func copySticky() []Issue {
- stickyMu.Lock()
- defer stickyMu.Unlock()
- out := make([]Issue, len(sticky))
- copy(out, sticky)
- return out
- }
- // CopySticky returns a copy of sticky load-time issues.
- func CopySticky() []Issue {
- return copySticky()
- }
- // Replace sets the current issue list and logs only newly appeared issues.
- func Replace(next []Issue) {
- storeMu.Lock()
- defer storeMu.Unlock()
- previous := make(map[string]struct{}, len(issues))
- for _, issue := range issues {
- previous[issueFingerprint(issue)] = struct{}{}
- }
- issues = make([]Issue, len(next))
- copy(issues, next)
- for _, issue := range issues {
- if _, exists := previous[issueFingerprint(issue)]; exists {
- continue
- }
- logNewIssue(issue)
- }
- }
- func issueFingerprint(issue Issue) string {
- return issue.Severity + "\x00" +
- issue.Code + "\x00" +
- issue.ActionID + "\x00" +
- issue.ActionTitle + "\x00" +
- issue.ArgumentName + "\x00" +
- issue.Source + "\x00" +
- issue.ConfigFile + "\x00" +
- issue.Message
- }
- func logNewIssue(issue Issue) {
- fields := log.Fields{
- "code": issue.Code,
- "actionTitle": issue.ActionTitle,
- "argumentName": issue.ArgumentName,
- "configFile": issue.ConfigFile,
- "source": issue.Source,
- }
- if issue.Severity == SeverityError {
- log.WithFields(fields).Error(issue.Message)
- return
- }
- log.WithFields(fields).Warn(issue.Message)
- }
- // Report adds a live issue if it is not already present and logs it when new.
- // Use this for runtime discoveries that happen outside Rebuild (for example
- // filesystem watcher setup failures).
- func Report(issue Issue) {
- storeMu.Lock()
- defer storeMu.Unlock()
- issueFingerprintValue := issueFingerprint(issue)
- for _, existing := range issues {
- if issueFingerprint(existing) == issueFingerprintValue {
- return
- }
- }
- issues = append(issues, issue)
- logNewIssue(issue)
- }
- // List returns a copy of the current issues.
- func List() []Issue {
- storeMu.RLock()
- defer storeMu.RUnlock()
- out := make([]Issue, len(issues))
- copy(out, issues)
- return out
- }
- // Count returns the number of current issues.
- func Count() int {
- storeMu.RLock()
- defer storeMu.RUnlock()
- return len(issues)
- }
|