diff --git a/internal/snmp/translate.go b/internal/snmp/translate.go index 3af552d1b06c9..a452d0a840c9b 100644 --- a/internal/snmp/translate.go +++ b/internal/snmp/translate.go @@ -16,14 +16,43 @@ import ( // or gosmi will fail without saying why var m sync.Mutex var once sync.Once +var cache = make(map[string]bool) -func LoadMibsFromPath(paths []string, log telegraf.Logger) error { +func appendPath(path string) { + m.Lock() + defer m.Unlock() + + gosmi.AppendPath(path) +} + +func loadModule(path string) error { m.Lock() defer m.Unlock() + + _, err := gosmi.LoadModule(path) + return err +} + +func ClearCache() { + cache = make(map[string]bool) +} + +func LoadMibsFromPath(paths []string, log telegraf.Logger) error { once.Do(gosmi.Init) - var folders []string + for _, mibPath := range paths { - gosmi.AppendPath(mibPath) + folders := []string{} + + // Check if we loaded that path already and skip it if so + m.Lock() + cached := cache[mibPath] + cache[mibPath] = true + m.Unlock() + if cached { + continue + } + + appendPath(mibPath) folders = append(folders, mibPath) err := filepath.Walk(mibPath, func(path string, info os.FileInfo, err error) error { // symlinks are files so we need to double check if any of them are folders @@ -38,26 +67,25 @@ func LoadMibsFromPath(paths []string, log telegraf.Logger) error { return nil }) if err != nil { - return fmt.Errorf("Filepath could not be walked %v", err) + return fmt.Errorf("Filepath could not be walked: %v", err) } + for _, folder := range folders { err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error { // checks if file or directory if info.IsDir() { - gosmi.AppendPath(path) + appendPath(path) } else if info.Mode()&os.ModeSymlink == 0 { - _, err := gosmi.LoadModule(info.Name()) - if err != nil { - log.Warnf("Module could not be loaded %v", err) + if err := loadModule(info.Name()); err != nil { + log.Warn(err) } } return nil }) if err != nil { - return fmt.Errorf("Filepath could not be walked %v", err) + return fmt.Errorf("Filepath could not be walked: %v", err) } } - folders = []string{} } return nil } diff --git a/plugins/inputs/snmp/snmp_test.go b/plugins/inputs/snmp/snmp_test.go index 7962bede41278..4f18a458a48e2 100644 --- a/plugins/inputs/snmp/snmp_test.go +++ b/plugins/inputs/snmp/snmp_test.go @@ -1295,3 +1295,12 @@ func TestTableJoinNoIndexAsTag_walk(t *testing.T) { require.Contains(t, tb.Rows, rtr2) require.Contains(t, tb.Rows, rtr3) } + +func BenchmarkMibLoading(b *testing.B) { + log := testutil.Logger{} + path := []string{"testdata"} + for i := 0; i < b.N; i++ { + err := snmp.LoadMibsFromPath(path, log) + require.NoError(b, err) + } +}