diff --git a/applicationset/controllers/applicationset_controller.go b/applicationset/controllers/applicationset_controller.go index b9fed82e394a0..83dfce2b9d2a4 100644 --- a/applicationset/controllers/applicationset_controller.go +++ b/applicationset/controllers/applicationset_controller.go @@ -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 }, diff --git a/applicationset/controllers/applicationset_controller_test.go b/applicationset/controllers/applicationset_controller_test.go index 5ce8d6b3e3180..51f190f89422c 100644 --- a/applicationset/controllers/applicationset_controller_test.go +++ b/applicationset/controllers/applicationset_controller_test.go @@ -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() diff --git a/controller/appcontroller.go b/controller/appcontroller.go index deea6d7656087..3b3e71c0dd3a1 100644 --- a/controller/appcontroller.go +++ b/controller/appcontroller.go @@ -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, @@ -1846,7 +1838,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 } @@ -1895,7 +1887,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 @@ -1973,7 +1965,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{}) @@ -2007,7 +1999,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) @@ -2052,7 +2044,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() { @@ -2217,16 +2209,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) } } @@ -2290,7 +2282,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) @@ -2417,7 +2409,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 { diff --git a/controller/health.go b/controller/health.go index fd04b823895ff..05804bc7da801 100644 --- a/controller/health.go +++ b/controller/health.go @@ -14,6 +14,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" ) @@ -51,7 +52,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) } } diff --git a/controller/hydrator/hydrator.go b/controller/hydrator/hydrator.go index a8ba19a58d694..b919bc6fd9a8e 100644 --- a/controller/hydrator/hydrator.go +++ b/controller/hydrator/hydrator.go @@ -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 diff --git a/controller/state.go b/controller/state.go index 1a2345f470a0a..1d25df18fbf3b 100644 --- a/controller/state.go +++ b/controller/state.go @@ -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()) } @@ -551,8 +552,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() diff --git a/controller/sync.go b/controller/sync.go index e2d89678f674e..c1bacdafb957f 100644 --- a/controller/sync.go +++ b/controller/sync.go @@ -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} diff --git a/controller/utils/log.go b/controller/utils/log.go deleted file mode 100644 index 20c6e7f094c1c..0000000000000 --- a/controller/utils/log.go +++ /dev/null @@ -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, - }) -} diff --git a/docs/operator-manual/security.md b/docs/operator-manual/security.md index 9d05c45cb7c74..afee322551480 100644 --- a/docs/operator-manual/security.md +++ b/docs/operator-manual/security.md @@ -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 diff --git a/server/application/application.go b/server/application/application.go index 77513d4fe18d1..d7c279d6dd05d 100644 --- a/server/application/application.go +++ b/server/application/application.go @@ -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 } diff --git a/server/application/broadcaster.go b/server/application/broadcaster.go index ec18f4b9fbbae..2c29787d34bac 100644 --- a/server/application/broadcaster.go +++ b/server/application/broadcaster.go @@ -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") } } } diff --git a/util/app/log/log.go b/util/app/log/log.go new file mode 100644 index 0000000000000..819d317e5efaa --- /dev/null +++ b/util/app/log/log.go @@ -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, + } +}