categraf/logs/input/journald/tailer_util.go

66 lines
2.1 KiB
Go

// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.
//go:build systemd
// +build systemd
package journald
import (
"fmt"
"math/rand"
"strings"
"time"
"flashcat.cloud/categraf/pkg/cache"
)
const (
tagSeparator = ":"
imageTagKey = "short_image" + tagSeparator
baseCacheExpiration = 20 * time.Minute
expirationSpreadSeconds = 120
)
// Get docker image short from dockerId and list of tags
// In case of miss in cache, we parse from tag list.
// We could use the util/Docker.Inspect + ImageID resolution or Regexp on config.Image
// But this way is simple and probably fast enough (~300ns for 100 items) on miss
func getDockerImageShortName(containerID string, tags []string) (string, bool) {
cacheKey := getImageCacheKey(containerID)
if cacheContent, hit := cache.Cache.Get(cacheKey); hit {
// Even if we don't get the right type from the cache, we will override it anyway
// The key is normally specific enough that only this process r/w the cache
if value, castOk := cacheContent.(string); castOk {
return value, true
}
}
// Cache miss
var shortName string
for _, tag := range tags {
if strings.HasPrefix(tag, imageTagKey) {
tagParts := strings.Split(tag, tagSeparator)
if len(tagParts) == 2 {
shortName = tagParts[1]
}
break
}
}
if shortName != "" {
// We are using a cache as this function will be called for each entry in journald. On busy systems, looping to parse among a significant number of tags
// could make the agent use a lot of CPU for nothing. To avoid CPU spikes when keys reach TTL all at the same time, we spread the TTL on several minutes
cache.Cache.Set(cacheKey, shortName, baseCacheExpiration+time.Duration(rand.Intn(expirationSpreadSeconds))*time.Second)
return shortName, true
}
return shortName, false
}
func getImageCacheKey(containerID string) string {
return fmt.Sprintf("logger.tailer.imagefor.%s", containerID)
}