chore(logs): standardize application logging (#20731) (#21442)

Signed-off-by: Louis Gérard <louis.gerard.pro@proton.me>
This commit is contained in:
dhawos
2025-05-20 21:48:09 +02:00
committed by GitHub
parent f4e12ad2d6
commit 7d58ca3ef7
12 changed files with 87 additions and 83 deletions

View File

@@ -51,6 +51,7 @@ import (
"github.com/argoproj/argo-cd/v3/applicationset/status"
"github.com/argoproj/argo-cd/v3/applicationset/utils"
"github.com/argoproj/argo-cd/v3/common"
applog "github.com/argoproj/argo-cd/v3/util/app/log"
"github.com/argoproj/argo-cd/v3/util/db"
argov1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
@@ -577,7 +578,7 @@ func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context,
var firstError error
// Creates or updates the application in appList
for _, generatedApp := range desiredApplications {
appLog := logCtx.WithFields(log.Fields{"app": generatedApp.QualifiedName()})
appLog := logCtx.WithFields(applog.GetAppLogFields(&generatedApp))
// Normalize to avoid fighting with the application controller.
generatedApp.Spec = *argoutil.NormalizeApplicationSpec(&generatedApp.Spec)
@@ -740,7 +741,7 @@ func (r *ApplicationSetReconciler) deleteInCluster(ctx context.Context, logCtx *
// Delete apps that are not in m[string]bool
var firstError error
for _, app := range current {
logCtx = logCtx.WithField("app", app.QualifiedName())
logCtx = logCtx.WithFields(applog.GetAppLogFields(&app))
_, exists := m[app.Name]
if !exists {
@@ -1462,23 +1463,23 @@ func getApplicationOwnsHandler(enableProgressiveSyncs bool) predicate.Funcs {
// if we are the owner and there is a create event, we most likely created it and do not need to
// re-reconcile
if log.IsLevelEnabled(log.DebugLevel) {
var appName string
logFields := log.Fields{"app": ""}
app, isApp := e.Object.(*argov1alpha1.Application)
if isApp {
appName = app.QualifiedName()
logFields = applog.GetAppLogFields(app)
}
log.WithField("app", appName).Debugln("received create event from owning an application")
log.WithFields(logFields).Debugln("received create event from owning an application")
}
return false
},
DeleteFunc: func(e event.DeleteEvent) bool {
if log.IsLevelEnabled(log.DebugLevel) {
var appName string
logFields := log.Fields{"app": ""}
app, isApp := e.Object.(*argov1alpha1.Application)
if isApp {
appName = app.QualifiedName()
logFields = applog.GetAppLogFields(app)
}
log.WithField("app", appName).Debugln("received delete event from owning an application")
log.WithFields(logFields).Debugln("received delete event from owning an application")
}
return true
},
@@ -1487,7 +1488,7 @@ func getApplicationOwnsHandler(enableProgressiveSyncs bool) predicate.Funcs {
if !isApp {
return false
}
logCtx := log.WithField("app", appOld.QualifiedName())
logCtx := log.WithFields(applog.GetAppLogFields(appOld))
logCtx.Debugln("received update event from owning an application")
appNew, isApp := e.ObjectNew.(*argov1alpha1.Application)
if !isApp {
@@ -1499,12 +1500,12 @@ func getApplicationOwnsHandler(enableProgressiveSyncs bool) predicate.Funcs {
},
GenericFunc: func(e event.GenericEvent) bool {
if log.IsLevelEnabled(log.DebugLevel) {
var appName string
logFields := log.Fields{}
app, isApp := e.Object.(*argov1alpha1.Application)
if isApp {
appName = app.QualifiedName()
logFields = applog.GetAppLogFields(app)
}
log.WithField("app", appName).Debugln("received generic event from owning an application")
log.WithFields(logFields).Debugln("received generic event from owning an application")
}
return true
},

View File

@@ -36,6 +36,7 @@ import (
argocommon "github.com/argoproj/argo-cd/v3/common"
"github.com/argoproj/argo-cd/v3/pkg/apis/application"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
applog "github.com/argoproj/argo-cd/v3/util/app/log"
"github.com/argoproj/argo-cd/v3/util/db"
"github.com/argoproj/argo-cd/v3/util/settings"
)
@@ -1210,7 +1211,7 @@ func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) {
clusterList, err := utils.ListClusters(t.Context(), kubeclientset, "namespace")
require.NoError(t, err)
appLog := log.WithFields(log.Fields{"app": app.Name, "appSet": ""})
appLog := log.WithFields(applog.GetAppLogFields(&app)).WithField("appSet", "")
appInputParam := app.DeepCopy()
@@ -1366,7 +1367,7 @@ func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) {
clusterList, err := utils.ListClusters(t.Context(), kubeclientset, "argocd")
require.NoError(t, err)
appLog := log.WithFields(log.Fields{"app": app.Name, "appSet": ""})
appLog := log.WithFields(applog.GetAppLogFields(&app)).WithField("appSet", "")
appInputParam := app.DeepCopy()

View File

@@ -54,6 +54,7 @@ import (
"github.com/argoproj/argo-cd/v3/pkg/client/informers/externalversions/application/v1alpha1"
applisters "github.com/argoproj/argo-cd/v3/pkg/client/listers/application/v1alpha1"
"github.com/argoproj/argo-cd/v3/reposerver/apiclient"
applog "github.com/argoproj/argo-cd/v3/util/app/log"
"github.com/argoproj/argo-cd/v3/util/argo"
argodiff "github.com/argoproj/argo-cd/v3/util/argo/diff"
"github.com/argoproj/argo-cd/v3/util/argo/normalizers"
@@ -98,15 +99,6 @@ func (a CompareWith) Pointer() *CompareWith {
return &a
}
func getAppLog(app *appv1.Application) *log.Entry {
return log.WithFields(log.Fields{
"application": app.Name,
"app-namespace": app.Namespace,
"app-qualified-name": app.QualifiedName(),
"project": app.Spec.Project,
})
}
// ApplicationController is the controller for application resources.
type ApplicationController struct {
cache *appstatecache.Cache
@@ -465,7 +457,7 @@ func (ctrl *ApplicationController) handleObjectUpdated(managedByApp map[string]b
continue
}
logCtx := getAppLog(app)
logCtx := log.WithFields(applog.GetAppLogFields(app))
// Enforce application's permission for the source namespace
_, err = ctrl.getAppProj(app)
if err != nil {
@@ -501,7 +493,7 @@ func (ctrl *ApplicationController) handleObjectUpdated(managedByApp map[string]b
func (ctrl *ApplicationController) setAppManagedResources(destCluster *appv1.Cluster, a *appv1.Application, comparisonResult *comparisonResult) (*appv1.ApplicationTree, error) {
ts := stats.NewTimingStats()
defer func() {
logCtx := getAppLog(a)
logCtx := log.WithFields(applog.GetAppLogFields(a))
for k, v := range ts.Timings() {
logCtx = logCtx.WithField(k, v.Milliseconds())
}
@@ -558,7 +550,7 @@ func isKnownOrphanedResourceExclusion(key kube.ResourceKey, proj *appv1.AppProje
func (ctrl *ApplicationController) getResourceTree(destCluster *appv1.Cluster, a *appv1.Application, managedResources []*appv1.ResourceDiff) (*appv1.ApplicationTree, error) {
ts := stats.NewTimingStats()
defer func() {
logCtx := getAppLog(a)
logCtx := log.WithFields(applog.GetAppLogFields(a))
for k, v := range ts.Timings() {
logCtx = logCtx.WithField(k, v.Milliseconds())
}
@@ -688,7 +680,7 @@ func (ctrl *ApplicationController) getResourceTree(destCluster *appv1.Cluster, a
func (ctrl *ApplicationController) getAppHosts(destCluster *appv1.Cluster, a *appv1.Application, appNodes []appv1.ResourceNode) ([]appv1.HostInfo, error) {
ts := stats.NewTimingStats()
defer func() {
logCtx := getAppLog(a)
logCtx := log.WithFields(applog.GetAppLogFields(a))
for k, v := range ts.Timings() {
logCtx = logCtx.WithField(k, v.Milliseconds())
}
@@ -1016,7 +1008,7 @@ func (ctrl *ApplicationController) processAppOperationQueueItem() (processNext b
return
}
app := origApp.DeepCopy()
logCtx := getAppLog(app)
logCtx := log.WithFields(applog.GetAppLogFields(app))
ts := stats.NewTimingStats()
defer func() {
for k, v := range ts.Timings() {
@@ -1180,7 +1172,7 @@ func (ctrl *ApplicationController) getPermittedAppLiveObjects(destCluster *appv1
}
func (ctrl *ApplicationController) finalizeApplicationDeletion(app *appv1.Application, projectClusters func(project string) ([]*appv1.Cluster, error)) error {
logCtx := getAppLog(app)
logCtx := log.WithFields(applog.GetAppLogFields(app))
// Get refreshed application info, since informer app copy might be stale
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(app.Namespace).Get(context.Background(), app.Name, metav1.GetOptions{})
if err != nil {
@@ -1338,7 +1330,7 @@ func (ctrl *ApplicationController) updateFinalizers(app *appv1.Application) erro
}
func (ctrl *ApplicationController) setAppCondition(app *appv1.Application, condition appv1.ApplicationCondition) {
logCtx := getAppLog(app)
logCtx := log.WithFields(applog.GetAppLogFields(app))
// do nothing if app already has same condition
for _, c := range app.Status.Conditions {
if c.Message == condition.Message && c.Type == condition.Type {
@@ -1363,7 +1355,7 @@ func (ctrl *ApplicationController) setAppCondition(app *appv1.Application, condi
}
func (ctrl *ApplicationController) processRequestedAppOperation(app *appv1.Application) {
logCtx := getAppLog(app)
logCtx := log.WithFields(applog.GetAppLogFields(app))
var state *appv1.OperationState
// Recover from any unexpected panics and automatically set the status to be failed
defer func() {
@@ -1501,7 +1493,7 @@ func (ctrl *ApplicationController) processRequestedAppOperation(app *appv1.Appli
}
func (ctrl *ApplicationController) setOperationState(app *appv1.Application, state *appv1.OperationState) {
logCtx := getAppLog(app)
logCtx := log.WithFields(applog.GetAppLogFields(app))
if state.Phase == "" {
// expose any bugs where we neglect to set phase
panic("no phase was set")
@@ -1579,7 +1571,7 @@ func (ctrl *ApplicationController) setOperationState(app *appv1.Application, sta
// writeBackToInformer writes a just recently updated App back into the informer cache.
// This prevents the situation where the controller operates on a stale app and repeats work
func (ctrl *ApplicationController) writeBackToInformer(app *appv1.Application) {
logCtx := getAppLog(app).WithField("informer-writeBack", true)
logCtx := log.WithFields(applog.GetAppLogFields(app)).WithField("informer-writeBack", true)
err := ctrl.appInformer.GetStore().Update(app)
if err != nil {
logCtx.Errorf("failed to update informer store: %v", err)
@@ -1636,7 +1628,7 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
return
}
app := origApp.DeepCopy()
logCtx := getAppLog(app).WithFields(log.Fields{
logCtx := log.WithFields(applog.GetAppLogFields(app)).WithFields(log.Fields{
"comparison-level": comparisonLevel,
"dest-server": origApp.Spec.Destination.Server,
"dest-name": origApp.Spec.Destination.Name,
@@ -1845,7 +1837,7 @@ func (ctrl *ApplicationController) processAppHydrateQueueItem() (processNext boo
ctrl.hydrator.ProcessAppHydrateQueueItem(origApp)
getAppLog(origApp).Debug("Successfully processed app hydrate queue item")
log.WithFields(applog.GetAppLogFields(origApp)).Debug("Successfully processed app hydrate queue item")
return
}
@@ -1894,7 +1886,7 @@ func currentSourceEqualsSyncedSource(app *appv1.Application) bool {
// Additionally, it returns whether full refresh was requested or not.
// If full refresh is requested then target and live state should be reconciled, else only live state tree should be updated.
func (ctrl *ApplicationController) needRefreshAppStatus(app *appv1.Application, statusRefreshTimeout, statusHardRefreshTimeout time.Duration) (bool, appv1.RefreshType, CompareWith) {
logCtx := getAppLog(app)
logCtx := log.WithFields(applog.GetAppLogFields(app))
var reason string
compareWith := CompareWithLatest
refreshType := appv1.RefreshTypeNormal
@@ -1972,7 +1964,7 @@ func (ctrl *ApplicationController) refreshAppConditions(app *appv1.Application)
// normalizeApplication normalizes an application.spec and additionally persists updates if it changed
func (ctrl *ApplicationController) normalizeApplication(orig, app *appv1.Application) {
app.Spec = *argo.NormalizeApplicationSpec(&app.Spec)
logCtx := getAppLog(app)
logCtx := log.WithFields(applog.GetAppLogFields(app))
patch, modified, err := diff.CreateTwoWayMergePatch(orig, app, appv1.Application{})
@@ -2006,7 +1998,7 @@ func createMergePatch(orig, new any) ([]byte, bool, error) {
// persistAppStatus persists updates to application status. If no changes were made, it is a no-op
func (ctrl *ApplicationController) persistAppStatus(orig *appv1.Application, newStatus *appv1.ApplicationStatus) (patchDuration time.Duration) {
logCtx := getAppLog(orig)
logCtx := log.WithFields(applog.GetAppLogFields(orig))
if orig.Status.Sync.Status != newStatus.Sync.Status {
message := fmt.Sprintf("Updated sync status: %s -> %s", orig.Status.Sync.Status, newStatus.Sync.Status)
ctrl.logAppEvent(context.TODO(), orig, argo.EventInfo{Reason: argo.EventReasonResourceUpdated, Type: corev1.EventTypeNormal}, message)
@@ -2059,7 +2051,7 @@ func (ctrl *ApplicationController) persistAppStatus(orig *appv1.Application, new
// autoSync will initiate a sync operation for an application configured with automated sync
func (ctrl *ApplicationController) autoSync(app *appv1.Application, syncStatus *appv1.SyncStatus, resources []appv1.ResourceStatus, revisionUpdated bool) (*appv1.ApplicationCondition, time.Duration) {
logCtx := getAppLog(app)
logCtx := log.WithFields(applog.GetAppLogFields(app))
ts := stats.NewTimingStats()
defer func() {
for k, v := range ts.Timings() {
@@ -2224,16 +2216,16 @@ func alreadyAttemptedSync(app *appv1.Application, commitSHA string, commitSHAsMS
return false, ""
}
} else {
log.WithField("application", app.Name).Debugf("Skipping auto-sync: commitSHA %s has no changes", commitSHA)
log.WithFields(applog.GetAppLogFields(app)).Debugf("Skipping auto-sync: commitSHA %s has no changes", commitSHA)
}
} else {
if revisionUpdated {
log.WithField("application", app.Name).Infof("Executing compare of syncResult.Revision and commitSha because manifest changed: %v", commitSHA)
log.WithFields(applog.GetAppLogFields(app)).Infof("Executing compare of syncResult.Revision and commitSha because manifest changed: %v", commitSHA)
if app.Status.OperationState.SyncResult.Revision != commitSHA {
return false, ""
}
} else {
log.WithField("application", app.Name).Debugf("Skipping auto-sync: commitSHA %s has no changes", commitSHA)
log.WithFields(applog.GetAppLogFields(app)).Debugf("Skipping auto-sync: commitSHA %s has no changes", commitSHA)
}
}
@@ -2297,7 +2289,7 @@ func (ctrl *ApplicationController) canProcessApp(obj any) bool {
if annotations := app.GetAnnotations(); annotations != nil {
if skipVal, ok := annotations[common.AnnotationKeyAppSkipReconcile]; ok {
logCtx := getAppLog(app)
logCtx := log.WithFields(applog.GetAppLogFields(app))
if skipReconcile, err := strconv.ParseBool(skipVal); err == nil {
if skipReconcile {
logCtx.Debugf("Skipping Application reconcile based on annotation %s", common.AnnotationKeyAppSkipReconcile)
@@ -2424,7 +2416,7 @@ func (ctrl *ApplicationController) newApplicationInformerAndLister() (cache.Shar
newApp, newOK := new.(*appv1.Application)
if oldOK && newOK {
if automatedSyncEnabled(oldApp, newApp) {
getAppLog(newApp).Info("Enabled automated sync")
log.WithFields(applog.GetAppLogFields(newApp)).Info("Enabled automated sync")
compareWith = CompareWithLatest.Pointer()
}
if ctrl.statusRefreshJitter != 0 && oldApp.ResourceVersion == newApp.ResourceVersion {

View File

@@ -13,6 +13,7 @@ import (
"github.com/argoproj/argo-cd/v3/common"
"github.com/argoproj/argo-cd/v3/pkg/apis/application"
appv1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
applog "github.com/argoproj/argo-cd/v3/util/app/log"
"github.com/argoproj/argo-cd/v3/util/lua"
)
@@ -50,7 +51,7 @@ func setApplicationHealth(resources []managedResource, statuses []appv1.Resource
errCount++
savedErr = fmt.Errorf("failed to get resource health for %q with name %q in namespace %q: %w", res.Live.GetKind(), res.Live.GetName(), res.Live.GetNamespace(), err)
// also log so we don't lose the message
log.WithField("application", app.QualifiedName()).Warn(savedErr)
log.WithFields(applog.GetAppLogFields(app)).Warn(savedErr)
}
}

View File

@@ -11,9 +11,9 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
commitclient "github.com/argoproj/argo-cd/v3/commitserver/apiclient"
"github.com/argoproj/argo-cd/v3/controller/utils"
appv1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v3/reposerver/apiclient"
applog "github.com/argoproj/argo-cd/v3/util/app/log"
argoio "github.com/argoproj/argo-cd/v3/util/io"
)
@@ -55,7 +55,7 @@ func (h *Hydrator) ProcessAppHydrateQueueItem(origApp *appv1.Application) {
return
}
logCtx := utils.GetAppLog(app)
logCtx := log.WithFields(applog.GetAppLogFields(app))
logCtx.Debug("Processing app hydrate queue item")
@@ -130,7 +130,7 @@ func (h *Hydrator) ProcessHydrationQueueItem(hydrationKey HydrationQueueKey) (pr
// in case we did.
app.Status.SourceHydrator.CurrentOperation.DrySHA = drySHA
h.dependencies.PersistAppHydratorStatus(origApp, &app.Status.SourceHydrator)
logCtx = logCtx.WithField("app", app.QualifiedName())
logCtx = logCtx.WithFields(applog.GetAppLogFields(app))
logCtx.Errorf("Failed to hydrate app: %v", err)
}
return

View File

@@ -34,6 +34,7 @@ import (
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/v3/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/v3/reposerver/apiclient"
applog "github.com/argoproj/argo-cd/v3/util/app/log"
"github.com/argoproj/argo-cd/v3/util/app/path"
"github.com/argoproj/argo-cd/v3/util/argo"
argodiff "github.com/argoproj/argo-cd/v3/util/argo/diff"
@@ -314,7 +315,7 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp
}
ts.AddCheckpoint("manifests_ms")
logCtx := log.WithField("application", app.QualifiedName())
logCtx := log.WithFields(applog.GetAppLogFields(app))
for k, v := range ts.Timings() {
logCtx = logCtx.WithField(k, v.Milliseconds())
}
@@ -550,8 +551,8 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
return nil, err
}
logCtx := log.WithField("application", app.QualifiedName())
logCtx.Infof("Comparing app state (cluster: %s, namespace: %s)", destCluster.Server, app.Spec.Destination.Namespace)
logCtx := log.WithFields(applog.GetAppLogFields(app))
logCtx.Infof("Comparing app state (cluster: %s, namespace: %s)", app.Spec.Destination.Server, app.Spec.Destination.Namespace)
var targetObjs []*unstructured.Unstructured
now := metav1.Now()

View File

@@ -31,6 +31,7 @@ import (
"github.com/argoproj/argo-cd/v3/controller/metrics"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
listersv1alpha1 "github.com/argoproj/argo-cd/v3/pkg/client/listers/application/v1alpha1"
applog "github.com/argoproj/argo-cd/v3/util/app/log"
"github.com/argoproj/argo-cd/v3/util/argo"
"github.com/argoproj/argo-cd/v3/util/argo/diff"
"github.com/argoproj/argo-cd/v3/util/glob"
@@ -256,7 +257,7 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
}
syncId := fmt.Sprintf("%05d-%s", syncIdPrefix, randSuffix)
logEntry := log.WithFields(log.Fields{"application": app.QualifiedName(), "syncId": syncId})
logEntry := log.WithFields(applog.GetAppLogFields(app)).WithField("syncId", syncId)
initialResourcesRes := make([]common.ResourceSyncResult, len(syncRes.Resources))
for i, res := range syncRes.Resources {
key := kube.ResourceKey{Group: res.Group, Kind: res.Kind, Namespace: res.Namespace, Name: res.Name}

View File

@@ -1,17 +0,0 @@
package utils
import (
"github.com/sirupsen/logrus"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
// GetAppLog returns a logrus entry with fields set for the given application.
func GetAppLog(app *v1alpha1.Application) *logrus.Entry {
return logrus.WithFields(logrus.Fields{
"application": app.Name,
"app-namespace": app.Namespace,
"app-qualified-name": app.QualifiedName(),
"project": app.Spec.Project,
})
}

View File

@@ -238,6 +238,14 @@ can be found in [server/server.go](https://github.com/argoproj/argo-cd/blob/abba
Argo CD does not log IP addresses of clients requesting API endpoints, since the API server is typically behind a proxy. Instead, it is recommended
to configure IP addresses logging in the proxy server that sits in front of the API server.
### Standard Application log fields
For logs related to an Application, Argo CD will log the following standard fields :
* *application*: the Application name, without the namespace
* *app-namespace*: the Application's namespace
* *project*: the Application's project
## ApplicationSets
Argo CD's ApplicationSets feature has its own [security considerations](./applicationset/Security.md). Be aware of those

View File

@@ -48,6 +48,7 @@ import (
"github.com/argoproj/argo-cd/v3/reposerver/apiclient"
servercache "github.com/argoproj/argo-cd/v3/server/cache"
"github.com/argoproj/argo-cd/v3/server/deeplinks"
applog "github.com/argoproj/argo-cd/v3/util/app/log"
"github.com/argoproj/argo-cd/v3/util/argo"
"github.com/argoproj/argo-cd/v3/util/collections"
"github.com/argoproj/argo-cd/v3/util/db"
@@ -337,7 +338,7 @@ func (s *Server) Create(ctx context.Context, q *application.ApplicationCreateReq
validate = *q.Validate
}
proj, err := s.getAppProject(ctx, a, log.WithField("application", a.Name))
proj, err := s.getAppProject(ctx, a, log.WithFields(applog.GetAppLogFields(a)))
if err != nil {
return nil, err
}
@@ -355,10 +356,10 @@ func (s *Server) Create(ctx context.Context, q *application.ApplicationCreateReq
// Don't let the app creator set the operation explicitly. Those requests should always go through the Sync API.
if a.Operation != nil {
log.WithFields(log.Fields{
"application": a.Name,
argocommon.SecurityField: argocommon.SecurityLow,
}).Warn("User attempted to set operation on application creation. This could have allowed them to bypass branch protection rules by setting manifests directly. Ignoring the set operation.")
log.WithFields(applog.GetAppLogFields(a)).
WithFields(log.Fields{
argocommon.SecurityField: argocommon.SecurityLow,
}).Warn("User attempted to set operation on application creation. This could have allowed them to bypass branch protection rules by setting manifests directly. Ignoring the set operation.")
a.Operation = nil
}
@@ -931,7 +932,7 @@ var informerSyncTimeout = 2 * time.Second
// after a mutating API call (create/update). This function should be called after a creates &
// update to give a probable (but not guaranteed) chance of being up-to-date after the create/update.
func (s *Server) waitSync(app *v1alpha1.Application) {
logCtx := log.WithField("application", app.Name)
logCtx := log.WithFields(applog.GetAppLogFields(app))
deadline := time.Now().Add(informerSyncTimeout)
minVersion, err := strconv.Atoi(app.ResourceVersion)
if err != nil {
@@ -2189,11 +2190,10 @@ func (s *Server) getObjectsForDeepLinks(ctx context.Context, app *v1alpha1.Appli
destCluster, err := argo.GetDestinationCluster(ctx, app.Spec.Destination, s.db)
if err != nil {
log.WithFields(map[string]any{
"application": app.GetName(),
"ns": app.GetNamespace(),
"destination": app.Spec.Destination,
}).Warnf("cannot validate cluster, error=%v", err.Error())
log.WithFields(applog.GetAppLogFields(app)).
WithFields(map[string]any{
"destination": app.Spec.Destination,
}).Warnf("cannot validate cluster, error=%v", err.Error())
return nil, nil, nil
}
@@ -2229,7 +2229,7 @@ func (s *Server) ListResourceLinks(ctx context.Context, req *application.Applica
return nil, err
}
proj, err := s.getAppProject(ctx, app, log.WithField("application", app.GetName()))
proj, err := s.getAppProject(ctx, app, log.WithFields(applog.GetAppLogFields(app)))
if err != nil {
return nil, err
}
@@ -2483,7 +2483,7 @@ func (s *Server) RunResourceAction(ctx context.Context, q *application.ResourceA
}
}
proj, err := s.getAppProject(ctx, a, log.WithField("application", a.Name))
proj, err := s.getAppProject(ctx, a, log.WithFields(applog.GetAppLogFields(a)))
if err != nil {
return nil, err
}

View File

@@ -7,6 +7,7 @@ import (
"k8s.io/apimachinery/pkg/watch"
appv1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
applog "github.com/argoproj/argo-cd/v3/util/app/log"
)
type subscriber struct {
@@ -50,7 +51,7 @@ func (b *broadcasterHandler) notify(event *appv1.ApplicationWatchEvent) {
case s.ch <- event:
default:
// drop event if cannot send right away
log.WithField("application", event.Application.Name).Warn("unable to send event notification")
log.WithFields(applog.GetAppLogFields(&event.Application)).Warn("unable to send event notification")
}
}
}

15
util/app/log/log.go Normal file
View File

@@ -0,0 +1,15 @@
package log
import (
log "github.com/sirupsen/logrus"
appv1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
func GetAppLogFields(app *appv1.Application) log.Fields {
return log.Fields{
"application": app.Name,
"app-namespace": app.Namespace,
"project": app.Spec.Project,
}
}