From 44aebdf3a70abbe07eaa1e7cc15c2f59d441ab3c Mon Sep 17 00:00:00 2001 From: Victor Lyuboslavsky <2685025+getvictor@users.noreply.github.com> Date: Fri, 13 Feb 2026 08:45:28 -0600 Subject: [PATCH] Switched Android from go-kit/log to slog (#39785) **Related issue:** Resolves #39785 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. - Changes file already updated. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually ## Summary by CodeRabbit * **Chores** * Updated internal logging infrastructure across Android MDM services and background jobs to use standard Go logging. * Enhanced test coverage for access control and permission enforcement across various endpoints and user roles. --- cmd/fleet/cron.go | 6 +- cmd/fleet/serve.go | 2 +- .../service/androidmgmt/google_client.go | 30 +++---- .../service/androidmgmt/proxy_client.go | 20 +++-- .../android/service/certificate_renewal.go | 7 +- .../mdm/android/service/enterprises_test.go | 30 +++---- server/mdm/android/service/profiles.go | 8 +- server/mdm/android/service/profiles_test.go | 7 +- server/mdm/android/service/pubsub.go | 80 +++++++++---------- server/mdm/android/service/pubsub_test.go | 7 +- .../mdm/android/service/reconcile_devices.go | 13 ++- server/mdm/android/service/service.go | 53 ++++++------ server/mdm/android/tests/testing_utils.go | 12 +-- ...tion_android_certificate_templates_test.go | 7 +- server/service/integration_mdm_test.go | 6 +- .../service/integrationtest/android/suite.go | 2 +- server/worker/software_worker.go | 5 +- 17 files changed, 143 insertions(+), 152 deletions(-) diff --git a/cmd/fleet/cron.go b/cmd/fleet/cron.go index d8b255ef1f..65cca59f16 100644 --- a/cmd/fleet/cron.go +++ b/cmd/fleet/cron.go @@ -991,7 +991,7 @@ func newCleanupsAndAggregationSchedule( return ds.RenewMDMManagedCertificates(ctx) }), schedule.WithJob("renew_android_certificate_templates", func(ctx context.Context) error { - return android_svc.RenewCertificateTemplates(ctx, ds, logger) + return android_svc.RenewCertificateTemplates(ctx, ds, logger.SlogLogger()) }), schedule.WithJob("query_results_cleanup", func(ctx context.Context) error { config, err := ds.AppConfig(ctx) @@ -1412,7 +1412,7 @@ func newAndroidMDMProfileManagerSchedule( ctx, name, instanceID, defaultInterval, ds, ds, schedule.WithLogger(logger), schedule.WithJob("manage_android_profiles", func(ctx context.Context) error { - return android_svc.ReconcileProfiles(ctx, ds, logger, licenseKey, androidAgentConfig) + return android_svc.ReconcileProfiles(ctx, ds, logger.SlogLogger(), licenseKey, androidAgentConfig) }), ) @@ -1848,7 +1848,7 @@ func newAndroidMDMDeviceReconcilerSchedule( ctx, name, instanceID, defaultInterval, ds, ds, schedule.WithLogger(logger), schedule.WithJob("reconcile_android_devices", func(ctx context.Context) error { - return android_svc.ReconcileAndroidDevices(ctx, ds, logger, licenseKey) + return android_svc.ReconcileAndroidDevices(ctx, ds, logger.SlogLogger(), licenseKey) }), ) diff --git a/cmd/fleet/serve.go b/cmd/fleet/serve.go index 3d9e5df7c6..010158f84f 100644 --- a/cmd/fleet/serve.go +++ b/cmd/fleet/serve.go @@ -850,7 +850,7 @@ the way that the Fleet server works. config.MDM.AndroidAgent.Validate(initFatal) androidSvc, err := android_service.NewService( ctx, - logger, + logger.SlogLogger(), ds, config.License.Key, config.Server.PrivateKey, diff --git a/server/mdm/android/service/androidmgmt/google_client.go b/server/mdm/android/service/androidmgmt/google_client.go index 12dbc2e430..f00c26327f 100644 --- a/server/mdm/android/service/androidmgmt/google_client.go +++ b/server/mdm/android/service/androidmgmt/google_client.go @@ -5,7 +5,6 @@ import ( "fmt" "log/slog" "net/http" - "os" "reflect" "strings" "time" @@ -16,8 +15,6 @@ import ( "github.com/fleetdm/fleet/v4/server/fleet" "github.com/fleetdm/fleet/v4/server/mdm/android" "github.com/go-json-experiment/json" - kitlog "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/google/uuid" "google.golang.org/api/androidmanagement/v1" "google.golang.org/api/googleapi" @@ -27,7 +24,7 @@ import ( // GoogleClient connects directly to Google's Android Management API. It is intended to be used for development/debugging. // To enable, set the following env vars: FLEET_DEV_ANDROID_GOOGLE_CLIENT=1 and FLEET_DEV_ANDROID_GOOGLE_SERVICE_CREDENTIALS=$(cat credentials.json) type GoogleClient struct { - logger kitlog.Logger + logger *slog.Logger mgmt *androidmanagement.Service androidServiceCredentials string androidProjectID string @@ -36,7 +33,7 @@ type GoogleClient struct { // Compile-time check to ensure that ProxyClient implements Client. var _ Client = &GoogleClient{} -func NewGoogleClient(ctx context.Context, logger kitlog.Logger, getenv dev_mode.GetEnv) Client { +func NewGoogleClient(ctx context.Context, logger *slog.Logger, getenv dev_mode.GetEnv) Client { androidServiceCredentials := getenv("FLEET_DEV_ANDROID_GOOGLE_SERVICE_CREDENTIALS") if androidServiceCredentials == "" { return nil @@ -49,17 +46,16 @@ func NewGoogleClient(ctx context.Context, logger kitlog.Logger, getenv dev_mode. var creds credentials err := json.Unmarshal([]byte(androidServiceCredentials), &creds) if err != nil { - level.Error(logger).Log("msg", "unmarshaling android service credentials", "err", err) + logger.ErrorContext(ctx, "unmarshaling android service credentials", "err", err) return nil } - slogLogger := slog.New(slog.NewTextHandler(os.Stdout, nil)) mgmt, err := androidmanagement.NewService(ctx, option.WithCredentialsJSON([]byte(androidServiceCredentials)), - option.WithLogger(slogLogger), + option.WithLogger(logger), ) if err != nil { - level.Error(logger).Log("msg", "creating android management service", "err", err) + logger.ErrorContext(ctx, "creating android management service", "err", err) return nil } return &GoogleClient{ @@ -202,7 +198,7 @@ func (g *GoogleClient) EnterprisesPoliciesPatch(ctx context.Context, policyName switch { case googleapi.IsNotModified(err): - g.logger.Log("msg", "Android policy not modified", "policy_name", policyName) + g.logger.InfoContext(ctx, "Android policy not modified", "policy_name", policyName) return nil, err case err != nil: return nil, fmt.Errorf("patching policy %s: %w", policyName, err) @@ -214,7 +210,7 @@ func (g *GoogleClient) EnterprisesDevicesPatch(ctx context.Context, deviceName s ret, err := g.mgmt.Enterprises.Devices.Patch(deviceName, device).Context(ctx).Do() switch { case googleapi.IsNotModified(err): - g.logger.Log("msg", "Android device not modified", "device_name", deviceName) + g.logger.InfoContext(ctx, "Android device not modified", "device_name", deviceName) return nil, err case err != nil: return nil, fmt.Errorf("patching device %s: %w", deviceName, err) @@ -234,7 +230,7 @@ func (g *GoogleClient) EnterprisesDevicesDelete(ctx context.Context, deviceName _, err := g.mgmt.Enterprises.Devices.Delete(deviceName).Context(ctx).Do() switch { case googleapi.IsNotModified(err): - g.logger.Log("msg", "Android device already deleted", "device_name", deviceName) + g.logger.InfoContext(ctx, "Android device already deleted", "device_name", deviceName) return nil case err != nil: return fmt.Errorf("deleting device %s: %w", deviceName, err) @@ -264,14 +260,14 @@ func (g *GoogleClient) EnterpriseDelete(ctx context.Context, enterpriseName stri // We can also pull the topic from the DB, but this way is more reliable. enterprise, err := g.mgmt.Enterprises.Get(enterpriseName).Context(ctx).Do() if err != nil { - level.Error(g.logger).Log("msg", "getting enterprise; perhaps it was already deleted?", "err", err, "enterprise_name", enterpriseName) + g.logger.ErrorContext(ctx, "getting enterprise; perhaps it was already deleted?", "err", err, "enterprise_name", enterpriseName) return nil } _, err = g.mgmt.Enterprises.Delete(enterpriseName).Do() switch { case googleapi.IsNotModified(err): - level.Info(g.logger).Log("msg", "enterprise was already deleted", "enterprise_name", enterpriseName) + g.logger.InfoContext(ctx, "enterprise was already deleted", "enterprise_name", enterpriseName) return nil case err != nil: return fmt.Errorf("deleting enterprise %s: %w", enterpriseName, err) @@ -284,7 +280,7 @@ func (g *GoogleClient) EnterpriseDelete(ctx context.Context, enterpriseName stri // PubSub topic and subscription have the same ID (but not name) by convention. topicAndSubscriptionID, err := getLastPart(ctx, enterprise.PubsubTopic) if err != nil || len(topicAndSubscriptionID) == 0 { - level.Error(g.logger).Log("msg", "getting last part of PubSub topic", "err", err, "topic", enterprise.PubsubTopic) + g.logger.ErrorContext(ctx, "getting last part of PubSub topic", "err", err, "topic", enterprise.PubsubTopic) return nil } @@ -370,7 +366,7 @@ func (g *GoogleClient) EnterprisesPoliciesModifyPolicyApplications(ctx context.C ret, err := g.mgmt.Enterprises.Policies.ModifyPolicyApplications(policyName, &req).Context(ctx).Do() switch { case googleapi.IsNotModified(err): - g.logger.Log("msg", "Android application policy not modified", "policy_name", policyName) + g.logger.InfoContext(ctx, "Android application policy not modified", "policy_name", policyName) return nil, err case err != nil: return nil, ctxerr.Wrapf(ctx, err, "modifying application policy %s", policyName) @@ -385,7 +381,7 @@ func (g *GoogleClient) EnterprisesPoliciesRemovePolicyApplications(ctx context.C ret, err := g.mgmt.Enterprises.Policies.RemovePolicyApplications(policyName, &req).Context(ctx).Do() switch { case googleapi.IsNotModified(err): - g.logger.Log("msg", "Android application policy not modified", "policy_name", policyName) + g.logger.InfoContext(ctx, "Android application policy not modified", "policy_name", policyName) return nil, err case err != nil: return nil, ctxerr.Wrapf(ctx, err, "removing packages from application policy %s", policyName) diff --git a/server/mdm/android/service/androidmgmt/proxy_client.go b/server/mdm/android/service/androidmgmt/proxy_client.go index a8f6144cd9..15fae68785 100644 --- a/server/mdm/android/service/androidmgmt/proxy_client.go +++ b/server/mdm/android/service/androidmgmt/proxy_client.go @@ -16,8 +16,6 @@ import ( "github.com/fleetdm/fleet/v4/server/dev_mode" "github.com/fleetdm/fleet/v4/server/mdm/android" "github.com/go-json-experiment/json" - kitlog "github.com/go-kit/log" - "github.com/go-kit/log/level" "google.golang.org/api/androidmanagement/v1" "google.golang.org/api/googleapi" "google.golang.org/api/option" @@ -27,7 +25,7 @@ const defaultProxyEndpoint = "https://fleetdm.com/api/android/" // ProxyClient connects to Google's Android Management API via a proxy, which is hosted at fleetdm.com by default. type ProxyClient struct { - logger kitlog.Logger + logger *slog.Logger mgmt *androidmanagement.Service licenseKey string proxyEndpoint string @@ -37,7 +35,7 @@ type ProxyClient struct { // Compile-time check to ensure that ProxyClient implements Client. var _ Client = &ProxyClient{} -func NewProxyClient(ctx context.Context, logger kitlog.Logger, licenseKey string, getenv dev_mode.GetEnv) Client { +func NewProxyClient(ctx context.Context, logger *slog.Logger, licenseKey string, getenv dev_mode.GetEnv) Client { proxyEndpoint := getenv("FLEET_DEV_ANDROID_PROXY_ENDPOINT") if proxyEndpoint == "" { proxyEndpoint = defaultProxyEndpoint @@ -62,7 +60,7 @@ func NewProxyClient(ctx context.Context, logger kitlog.Logger, licenseKey string option.WithHTTPClient(fleethttp.NewClient()), ) if err != nil { - level.Error(logger).Log("msg", "creating android management service", "err", err) + logger.ErrorContext(ctx, "creating android management service", "err", err) return nil } return &ProxyClient{ @@ -180,7 +178,7 @@ func (p *ProxyClient) EnterprisesPoliciesPatch(ctx context.Context, policyName s ret, err := call.Do() switch { case googleapi.IsNotModified(err): - p.logger.Log("msg", "Android policy not modified", "policy_name", policyName) + p.logger.InfoContext(ctx, "Android policy not modified", "policy_name", policyName) return nil, err case err != nil: return nil, fmt.Errorf("patching policy %s: %w", policyName, err) @@ -194,7 +192,7 @@ func (p *ProxyClient) EnterprisesDevicesPatch(ctx context.Context, deviceName st ret, err := call.Do() switch { case googleapi.IsNotModified(err): - p.logger.Log("msg", "Android device not modified", "device_name", deviceName) + p.logger.InfoContext(ctx, "Android device not modified", "device_name", deviceName) return nil, err case err != nil: return nil, fmt.Errorf("patching device %s: %w", deviceName, err) @@ -218,7 +216,7 @@ func (p *ProxyClient) EnterprisesDevicesDelete(ctx context.Context, deviceName s _, err := call.Do() switch { case googleapi.IsNotModified(err) || isErrorCode(err, http.StatusNotFound): - p.logger.Log("msg", "Android device already deleted", "device_name", deviceName) + p.logger.InfoContext(ctx, "Android device already deleted", "device_name", deviceName) return nil case err != nil: return fmt.Errorf("deleting device %s: %w", deviceName, err) @@ -254,7 +252,7 @@ func (p *ProxyClient) EnterpriseDelete(ctx context.Context, enterpriseName strin _, err := call.Do() switch { case googleapi.IsNotModified(err) || isErrorCode(err, http.StatusNotFound): - level.Info(p.logger).Log("msg", "enterprise was already deleted", "enterprise_name", enterpriseName) + p.logger.InfoContext(ctx, "enterprise was already deleted", "enterprise_name", enterpriseName) return nil case err != nil: return fmt.Errorf("deleting enterprise %s: %w", enterpriseName, err) @@ -334,7 +332,7 @@ func (p *ProxyClient) EnterprisesPoliciesModifyPolicyApplications(ctx context.Co ret, err := call.Do() switch { case googleapi.IsNotModified(err): - p.logger.Log("msg", "Android application policy not modified", "policy_name", policyName) + p.logger.InfoContext(ctx, "Android application policy not modified", "policy_name", policyName) return nil, err case err != nil: return nil, ctxerr.Wrapf(ctx, err, "modifying application policy %s", policyName) @@ -352,7 +350,7 @@ func (p *ProxyClient) EnterprisesPoliciesRemovePolicyApplications(ctx context.Co ret, err := call.Do() switch { case googleapi.IsNotModified(err): - p.logger.Log("msg", "Android application policy not modified", "policy_name", policyName) + p.logger.InfoContext(ctx, "Android application policy not modified", "policy_name", policyName) return nil, err case err != nil: return nil, ctxerr.Wrapf(ctx, err, "removing packages from application policy %s", policyName) diff --git a/server/mdm/android/service/certificate_renewal.go b/server/mdm/android/service/certificate_renewal.go index f6f35072d1..efe7a7a822 100644 --- a/server/mdm/android/service/certificate_renewal.go +++ b/server/mdm/android/service/certificate_renewal.go @@ -2,16 +2,15 @@ package service import ( "context" + "log/slog" "github.com/fleetdm/fleet/v4/server/contexts/ctxerr" "github.com/fleetdm/fleet/v4/server/fleet" - kitlog "github.com/go-kit/log" - "github.com/go-kit/log/level" ) // RenewCertificateTemplates identifies Android certificate templates that are approaching // expiration and marks them for renewal by updating their status. -func RenewCertificateTemplates(ctx context.Context, ds fleet.Datastore, logger kitlog.Logger) error { +func RenewCertificateTemplates(ctx context.Context, ds fleet.Datastore, logger *slog.Logger) error { const batchSize = 1000 templates, err := ds.GetAndroidCertificateTemplatesForRenewal(ctx, batchSize) if err != nil { @@ -23,6 +22,6 @@ func RenewCertificateTemplates(ctx context.Context, ds fleet.Datastore, logger k if err := ds.SetAndroidCertificateTemplatesForRenewal(ctx, templates); err != nil { return ctxerr.Wrap(ctx, err, "set android certificate templates for renewal") } - level.Info(logger).Log("msg", "marked android certificate templates for renewal", "count", len(templates)) + logger.InfoContext(ctx, "marked android certificate templates for renewal", "count", len(templates)) return nil } diff --git a/server/mdm/android/service/enterprises_test.go b/server/mdm/android/service/enterprises_test.go index e8930bc53e..1891f4d20f 100644 --- a/server/mdm/android/service/enterprises_test.go +++ b/server/mdm/android/service/enterprises_test.go @@ -15,9 +15,9 @@ import ( "github.com/fleetdm/fleet/v4/server/mdm/android" android_mock "github.com/fleetdm/fleet/v4/server/mdm/android/mock" ds_mock "github.com/fleetdm/fleet/v4/server/mock" + "github.com/fleetdm/fleet/v4/server/platform/logging" "github.com/fleetdm/fleet/v4/server/ptr" "github.com/fleetdm/fleet/v4/server/service/modules/activities" - kitlog "github.com/go-kit/log" "github.com/jmoiron/sqlx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -28,10 +28,10 @@ import ( func TestEnterprisesAuth(t *testing.T) { androidAPIClient := android_mock.Client{} androidAPIClient.InitCommonMocks() - logger := kitlog.NewLogfmtLogger(os.Stdout) + logger := logging.NewLogfmtLogger(os.Stdout) fleetDS := InitCommonDSMocks() activityModule := activities.NewActivityModule(fleetDS, logger) - svc, err := NewServiceWithClient(logger, fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) + svc, err := NewServiceWithClient(logger.SlogLogger(), fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) testCases := []struct { @@ -126,11 +126,11 @@ func TestEnterprisesAuth(t *testing.T) { func TestEnterpriseSignupMissingPrivateKey(t *testing.T) { androidAPIClient := android_mock.Client{} androidAPIClient.InitCommonMocks() - logger := kitlog.NewLogfmtLogger(os.Stdout) + logger := logging.NewLogfmtLogger(os.Stdout) fleetDS := InitCommonDSMocks() activityModule := activities.NewActivityModule(fleetDS, logger) - svc, err := NewServiceWithClient(logger, fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) + svc, err := NewServiceWithClient(logger.SlogLogger(), fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) user := &fleet.User{ID: 1, GlobalRole: ptr.String(fleet.RoleAdmin)} @@ -237,7 +237,7 @@ func (e *notFoundError) Error() string { return "not found" } func (e *notFoundError) IsNotFound() bool { return true } func TestGetEnterprise(t *testing.T) { - logger := kitlog.NewLogfmtLogger(os.Stdout) + logger := logging.NewLogfmtLogger(os.Stdout) user := &fleet.User{ID: 1, GlobalRole: ptr.String(fleet.RoleAdmin)} ctx := viewer.NewContext(context.Background(), viewer.Viewer{User: user}) @@ -247,7 +247,7 @@ func TestGetEnterprise(t *testing.T) { fleetDS := InitCommonDSMocks() activityModule := activities.NewActivityModule(fleetDS, logger) - svc, err := NewServiceWithClient(logger, fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) + svc, err := NewServiceWithClient(logger.SlogLogger(), fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) enterprise, err := svc.GetEnterprise(ctx) @@ -267,7 +267,7 @@ func TestGetEnterprise(t *testing.T) { } activityModule := activities.NewActivityModule(fleetDS, logger) - svc, err := NewServiceWithClient(logger, fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) + svc, err := NewServiceWithClient(logger.SlogLogger(), fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) enterprise, err := svc.GetEnterprise(ctx) @@ -281,7 +281,7 @@ func TestGetEnterprise(t *testing.T) { } func TestVerifyExistingEnterpriseIfAny(t *testing.T) { - logger := kitlog.NewLogfmtLogger(os.Stdout) + logger := logging.NewLogfmtLogger(os.Stdout) user := &fleet.User{ID: 1, GlobalRole: ptr.String(fleet.RoleAdmin)} ctx := viewer.NewContext(context.Background(), viewer.Viewer{User: user}) @@ -313,7 +313,7 @@ func TestVerifyExistingEnterpriseIfAny(t *testing.T) { } activityModule := activities.NewActivityModule(fleetDS, logger) - svc, err := NewServiceWithClient(logger, fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) + svc, err := NewServiceWithClient(logger.SlogLogger(), fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) err = svc.VerifyExistingEnterpriseIfAny(ctx) @@ -362,7 +362,7 @@ func TestVerifyExistingEnterpriseIfAny(t *testing.T) { } activityModule := activities.NewActivityModule(fleetDS, logger) - svc, err := NewServiceWithClient(logger, fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) + svc, err := NewServiceWithClient(logger.SlogLogger(), fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) err = svc.VerifyExistingEnterpriseIfAny(ctx) @@ -403,7 +403,7 @@ func TestVerifyExistingEnterpriseIfAny(t *testing.T) { } activityModule := activities.NewActivityModule(fleetDS, logger) - svc, err := NewServiceWithClient(logger, fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) + svc, err := NewServiceWithClient(logger.SlogLogger(), fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) err = svc.VerifyExistingEnterpriseIfAny(ctx) @@ -444,7 +444,7 @@ func TestVerifyExistingEnterpriseIfAny(t *testing.T) { } activityModule := activities.NewActivityModule(fleetDS, logger) - svc, err := NewServiceWithClient(logger, fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) + svc, err := NewServiceWithClient(logger.SlogLogger(), fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) err = svc.VerifyExistingEnterpriseIfAny(ctx) @@ -511,7 +511,7 @@ func TestVerifyExistingEnterpriseIfAny(t *testing.T) { } activityModule := activities.NewActivityModule(fleetDS, logger) - svc, err := NewServiceWithClient(logger, fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) + svc, err := NewServiceWithClient(logger.SlogLogger(), fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) err = svc.VerifyExistingEnterpriseIfAny(ctx) @@ -541,7 +541,7 @@ func TestVerifyExistingEnterpriseIfAny(t *testing.T) { } activityModule := activities.NewActivityModule(fleetDS, logger) - svc, err := NewServiceWithClient(logger, fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) + svc, err := NewServiceWithClient(logger.SlogLogger(), fleetDS, &androidAPIClient, "test-private-key", &fleetDS.DataStore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) err = svc.VerifyExistingEnterpriseIfAny(ctx) diff --git a/server/mdm/android/service/profiles.go b/server/mdm/android/service/profiles.go index 7ac50ea6bd..d528618eb0 100644 --- a/server/mdm/android/service/profiles.go +++ b/server/mdm/android/service/profiles.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "log/slog" "maps" "net/http" "slices" @@ -15,17 +16,16 @@ import ( "github.com/fleetdm/fleet/v4/server/fleet" "github.com/fleetdm/fleet/v4/server/mdm/android" "github.com/fleetdm/fleet/v4/server/mdm/android/service/androidmgmt" - kitlog "github.com/go-kit/log" "google.golang.org/api/androidmanagement/v1" ) -func ReconcileProfiles(ctx context.Context, ds fleet.Datastore, logger kitlog.Logger, licenseKey string, androidAgentConfig config.AndroidAgentConfig) error { +func ReconcileProfiles(ctx context.Context, ds fleet.Datastore, logger *slog.Logger, licenseKey string, androidAgentConfig config.AndroidAgentConfig) error { return ReconcileProfilesWithClient(ctx, ds, logger, licenseKey, nil, androidAgentConfig) } // ReconcileProfilesWithClient is like ReconcileProfiles but allows injecting a custom client for testing. // If client is nil, a new AMAPI client will be created. -func ReconcileProfilesWithClient(ctx context.Context, ds fleet.Datastore, logger kitlog.Logger, licenseKey string, client androidmgmt.Client, androidAgentConfig config.AndroidAgentConfig) error { +func ReconcileProfilesWithClient(ctx context.Context, ds fleet.Datastore, logger *slog.Logger, licenseKey string, client androidmgmt.Client, androidAgentConfig config.AndroidAgentConfig) error { appConfig, err := ds.AppConfig(ctx) if err != nil { return ctxerr.Wrap(ctx, err, "get app config") @@ -71,7 +71,7 @@ type profileReconciler struct { Enterprise *android.Enterprise Client androidmgmt.Client AndroidAgentConfig config.AndroidAgentConfig - Logger kitlog.Logger + Logger *slog.Logger } func getClientAuthenticationSecret(ctx context.Context, ds fleet.Datastore) (string, error) { diff --git a/server/mdm/android/service/profiles_test.go b/server/mdm/android/service/profiles_test.go index c8f8937c8e..8682b62eea 100644 --- a/server/mdm/android/service/profiles_test.go +++ b/server/mdm/android/service/profiles_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "log/slog" "strings" "testing" "time" @@ -16,9 +17,9 @@ import ( "github.com/fleetdm/fleet/v4/server/mdm/android" "github.com/fleetdm/fleet/v4/server/mdm/android/mock" "github.com/fleetdm/fleet/v4/server/mdm/android/service/androidmgmt" + "github.com/fleetdm/fleet/v4/server/platform/logging" "github.com/fleetdm/fleet/v4/server/ptr" "github.com/fleetdm/fleet/v4/server/test" - kitlog "github.com/go-kit/log" "github.com/google/uuid" "github.com/jmoiron/sqlx" "github.com/stretchr/testify/require" @@ -100,7 +101,7 @@ func TestReconcileProfiles(t *testing.T) { Package: "com.fleetdm.agent", SigningSHA256: "abc123def456", }, - Logger: kitlog.NewNopLogger(), + Logger: slog.New(logging.DiscardHandler{}), } c.fn(t, ds, client, reconciler) @@ -1007,7 +1008,7 @@ func testBuildAndSendFleetAgentConfigForEnrollment(t *testing.T, ds fleet.Datast // Create service and call BuildAndSendFleetAgentConfig with skipHostsWithoutNewCerts=false // This simulates the enrollment flow from software_worker.go svc := &Service{ - logger: kitlog.NewNopLogger(), + logger: slog.New(logging.DiscardHandler{}), fleetDS: ds, ds: ds.(fleet.AndroidDatastore), androidAPIClient: client, diff --git a/server/mdm/android/service/pubsub.go b/server/mdm/android/service/pubsub.go index 3cf8e8a2ca..2584a9a93b 100644 --- a/server/mdm/android/service/pubsub.go +++ b/server/mdm/android/service/pubsub.go @@ -16,7 +16,6 @@ import ( "github.com/fleetdm/fleet/v4/server/ptr" "github.com/fleetdm/fleet/v4/server/worker" "github.com/go-json-experiment/json" - "github.com/go-kit/log/level" "golang.org/x/text/cases" "golang.org/x/text/language" "google.golang.org/api/androidmanagement/v1" @@ -45,7 +44,7 @@ func (svc *Service) ProcessPubSubPush(ctx context.Context, token string, message svc.authz.SkipAuthorization(ctx) return nil } - level.Debug(svc.logger).Log("msg", "Received PubSub message", "notification", notificationType) + svc.logger.DebugContext(ctx, "Received PubSub message", "notification", notificationType) if android.NotificationType(notificationType) == android.PubSubTest { // Nothing to process svc.authz.SkipAuthorization(ctx) @@ -69,7 +68,7 @@ func (svc *Service) ProcessPubSubPush(ctx context.Context, token string, message return svc.handlePubSubStatusReport(ctx, token, rawData) default: // Ignore unknown notification types - level.Debug(svc.logger).Log("msg", "Ignoring PubSub notification type", "notification", notificationType) + svc.logger.DebugContext(ctx, "Ignoring PubSub notification type", "notification", notificationType) svc.authz.SkipAuthorization(ctx) return nil } @@ -151,7 +150,7 @@ func (svc *Service) handlePubSubStatusReport(ctx context.Context, token string, } if isDeleted { - level.Debug(svc.logger).Log("msg", "Android device deleted from MDM", "device.name", device.Name, + svc.logger.DebugContext(ctx, "Android device deleted from MDM", "device.name", device.Name, "device.enterpriseSpecificId", device.HardwareInfo.EnterpriseSpecificId) // User-initiated unenroll (work profile removed) or device deleted via AMAPI. @@ -203,18 +202,18 @@ func (svc *Service) handlePubSubStatusReport(ctx context.Context, token string, return ctxerr.Wrap(ctx, err, "getting existing Android host") } if host == nil { - level.Debug(svc.logger).Log("msg", "Device not found in Fleet. Perhaps it was deleted, "+ + svc.logger.DebugContext(ctx, "Device not found in Fleet. Perhaps it was deleted, "+ "but it is still connected via Android MDM. Re-enrolling", "device.name", device.Name, "device.enterpriseSpecificId", device.HardwareInfo.EnterpriseSpecificId) err = svc.enrollHost(ctx, &device) if err != nil { - level.Debug(svc.logger).Log("msg", "Error re-enrolling Android host", "data", rawData) + svc.logger.DebugContext(ctx, "Error re-enrolling Android host", "data", rawData) return ctxerr.Wrap(ctx, err, "re-enrolling deleted Android host") } } err = svc.updateHost(ctx, &device, host, false) if err != nil { - level.Debug(svc.logger).Log("msg", "Error updating Android host", "data", rawData) + svc.logger.DebugContext(ctx, "Error updating Android host", "data", rawData) return ctxerr.Wrap(ctx, err, "enrolling Android host") } err = svc.updateHostSoftware(ctx, &device, host) @@ -327,7 +326,7 @@ func (svc *Service) handlePubSubEnrollment(ctx context.Context, token string, ra err = svc.enrollHost(ctx, &device) if err != nil { - level.Debug(svc.logger).Log("msg", "Error enrolling Android host", "data", rawData) + svc.logger.DebugContext(ctx, "Error enrolling Android host", "data", rawData) return ctxerr.Wrap(ctx, err, "enrolling Android host") } return nil @@ -360,7 +359,7 @@ func (svc *Service) enrollHost(ctx context.Context, device *androidmanagement.De } if host != nil { - level.Debug(svc.logger).Log("msg", "The enrolling Android host is already present in Fleet. Updating team if needed", + svc.logger.DebugContext(ctx, "The enrolling Android host is already present in Fleet. Updating team if needed", "device.name", device.Name, "device.enterpriseSpecificId", device.HardwareInfo.EnterpriseSpecificId) enrollSecret, err := svc.ds.VerifyEnrollSecret(ctx, enrollmentTokenRequest.EnrollSecret) if err != nil && !fleet.IsNotFound(err) { @@ -466,7 +465,7 @@ func (svc *Service) updateHost(ctx context.Context, device *androidmanagement.De teamID = *host.Host.TeamID } if _, err := svc.fleetDS.CreatePendingCertificateTemplatesForNewHost(ctx, host.Host.UUID, teamID); err != nil { - level.Error(svc.logger).Log("msg", "failed to create pending certificate templates for re-enrolled host", "host_uuid", host.Host.UUID, "err", err) + svc.logger.ErrorContext(ctx, "failed to create pending certificate templates for re-enrolled host", "host_uuid", host.Host.UUID, "err", err) return ctxerr.Wrap(ctx, err, "creating pending certificate templates for re-enrolled host") } @@ -574,7 +573,7 @@ func (svc *Service) addNewHost(ctx context.Context, device *androidmanagement.De } if enrollmentTokenRequest.IdpUUID != "" { - level.Info(svc.logger).Log("msg", "associating android host with idp account", "host_uuid", host.UUID, "idp_uuid", enrollmentTokenRequest.IdpUUID) + svc.logger.InfoContext(ctx, "associating android host with idp account", "host_uuid", host.UUID, "idp_uuid", enrollmentTokenRequest.IdpUUID) err := svc.ds.AssociateHostMDMIdPAccount(ctx, host.UUID, enrollmentTokenRequest.IdpUUID) if err != nil { return ctxerr.Wrap(ctx, err, "associating host with idp account") @@ -591,7 +590,7 @@ func (svc *Service) addNewHost(ctx context.Context, device *androidmanagement.De teamID = *enrollSecret.GetTeamID() } if _, err := svc.fleetDS.CreatePendingCertificateTemplatesForNewHost(ctx, fleetHost.Host.UUID, teamID); err != nil { - level.Error(svc.logger).Log("msg", "failed to create pending certificate templates for new host", "host_uuid", fleetHost.Host.UUID, "err", err) + svc.logger.ErrorContext(ctx, "failed to create pending certificate templates for new host", "host_uuid", fleetHost.Host.UUID, "err", err) return ctxerr.Wrap(ctx, err, "creating pending certificate templates for new host") } @@ -640,7 +639,7 @@ func (svc *Service) getPolicyID(ctx context.Context, device *androidmanagement.D return nil, ctxerr.Errorf(ctx, "invalid Android policy name: %s", device.AppliedPolicyName) } if len(nameParts[3]) == 0 { - level.Error(svc.logger).Log("msg", "Empty Android policy ID", "device.name", device.Name, + svc.logger.ErrorContext(ctx, "Empty Android policy ID", "device.name", device.Name, "device.enterpriseSpecificID", device.HardwareInfo.EnterpriseSpecificId, "device.AppliedPolicyName", device.AppliedPolicyName) return nil, nil @@ -651,7 +650,7 @@ func (svc *Service) getPolicyID(ctx context.Context, device *androidmanagement.D func (svc *Service) verifyDevicePolicy(ctx context.Context, hostUUID string, device *androidmanagement.Device) { appliedPolicyVersion := device.AppliedPolicyVersion - level.Debug(svc.logger).Log("msg", "Verifying Android device policy", "host_uuid", hostUUID, "applied_policy_version", appliedPolicyVersion) + svc.logger.DebugContext(ctx, "Verifying Android device policy", "host_uuid", hostUUID, "applied_policy_version", appliedPolicyVersion) // Get all host_mdm_android_profiles that are pending or failed due to non compliance reasons, // and included_in_policy_version <= device.AppliedPolicyVersion. That way we can either fully @@ -660,7 +659,7 @@ func (svc *Service) verifyDevicePolicy(ctx context.Context, hostUUID string, dev // Get all profiles that are pending or failed install pendingInstallProfiles, err := svc.ds.ListHostMDMAndroidProfilesPendingOrFailedInstallWithVersion(ctx, hostUUID, appliedPolicyVersion) if err != nil { - level.Error(svc.logger).Log("msg", "error getting pending profiles", "err", err) + svc.logger.ErrorContext(ctx, "error getting pending profiles", "err", err) return } @@ -684,7 +683,7 @@ func (svc *Service) verifyDevicePolicy(ctx context.Context, hostUUID string, dev err = svc.ds.BulkUpsertMDMAndroidHostProfiles(ctx, verifiedProfiles) if err != nil { - level.Error(svc.logger).Log("msg", "error verifying pending install profiles", "err", err) + svc.logger.ErrorContext(ctx, "error verifying pending install profiles", "err", err) } } else { @@ -700,19 +699,19 @@ func (svc *Service) verifyDevicePolicy(ctx context.Context, hostUUID string, dev // Then re-use the map above, so we can iterate over it again, but now the payload is already unmarshalled. policyRequest, err := svc.ds.GetAndroidPolicyRequestByUUID(ctx, policyRequestUUID) if err != nil && !fleet.IsNotFound(err) { - level.Error(svc.logger).Log("msg", "error getting policy request", "err", err, "policy_request_uuid", policyRequestUUID, "host_uuid", hostUUID) + svc.logger.ErrorContext(ctx, "error getting policy request", "err", err, "policy_request_uuid", policyRequestUUID, "host_uuid", hostUUID) return } if fleet.IsNotFound(err) { - level.Error(svc.logger).Log("msg", "policy request not found", "policy_request_uuid", policyRequestUUID, "host_uuid", hostUUID) + svc.logger.ErrorContext(ctx, "policy request not found", "policy_request_uuid", policyRequestUUID, "host_uuid", hostUUID) return } var policyRequestPayload fleet.AndroidPolicyRequestPayload err = json.Unmarshal(policyRequest.Payload, &policyRequestPayload) if err != nil { - level.Error(svc.logger).Log("msg", "error unmarshalling policy request payload", "err", err, "policy_request_uuid", policyRequestUUID, "host_uuid", hostUUID) + svc.logger.ErrorContext(ctx, "error unmarshalling policy request payload", "err", err, "policy_request_uuid", policyRequestUUID, "host_uuid", hostUUID) return } @@ -758,7 +757,7 @@ func (svc *Service) verifyDevicePolicy(ctx context.Context, hostUUID string, dev err = svc.ds.BulkUpsertMDMAndroidHostProfiles(ctx, profiles) if err != nil { - level.Error(svc.logger).Log("msg", "error upserting android profiles", "err", err, "host_uuid", hostUUID) + svc.logger.ErrorContext(ctx, "error upserting android profiles", "err", err, "host_uuid", hostUUID) return } } @@ -766,7 +765,7 @@ func (svc *Service) verifyDevicePolicy(ctx context.Context, hostUUID string, dev // Bulk delete any pending or failed remove profiles. err = svc.ds.BulkDeleteMDMAndroidHostProfiles(ctx, hostUUID, appliedPolicyVersion) if err != nil { - level.Error(svc.logger).Log("msg", "error deleting pending or failed remove profiles", "err", err, "host_uuid", hostUUID) + svc.logger.ErrorContext(ctx, "error deleting pending or failed remove profiles", "err", err, "host_uuid", hostUUID) } } @@ -774,14 +773,14 @@ func (svc *Service) verifyDeviceSoftware(ctx context.Context, host *fleet.Host, appliedPolicyVersion := device.AppliedPolicyVersion hostUUID := host.UUID - level.Debug(svc.logger).Log("msg", "Verifying Android device software", "host_uuid", hostUUID, "applied_policy_version", appliedPolicyVersion) + svc.logger.DebugContext(ctx, "Verifying Android device software", "host_uuid", hostUUID, "applied_policy_version", appliedPolicyVersion) // Get all host_vpp_software_installs that are pending, and set in a policy version <= device.AppliedPolicyVersion. // That way we can either fully verify the app install, or mark as failed if the app is not compliant. pendingInstallApps, err := svc.ds.ListHostMDMAndroidVPPAppsPendingInstallWithVersion(ctx, hostUUID, appliedPolicyVersion) if err != nil { - level.Error(svc.logger).Log("msg", "error getting pending vpp installs", "err", err) + svc.logger.ErrorContext(ctx, "error getting pending vpp installs", "err", err) return } if len(pendingInstallApps) == 0 { @@ -820,11 +819,11 @@ func (svc *Service) verifyDeviceSoftware(ctx context.Context, host *fleet.Host, if appReport.State == "INSTALLED" { // definitely installed successfully markVerified[appReport.PackageName] = true - level.Debug(svc.logger).Log("msg", "Software marked as verified", "host_uuid", hostUUID, "package_name", appReport.PackageName) + svc.logger.DebugContext(ctx, "Software marked as verified", "host_uuid", hostUUID, "package_name", appReport.PackageName) continue } } - level.Debug(svc.logger).Log("msg", "Software not marked as verified, checking if failed", "host_uuid", hostUUID, "package_name", appReport.PackageName) + svc.logger.DebugContext(ctx, "Software not marked as verified, checking if failed", "host_uuid", hostUUID, "package_name", appReport.PackageName) } // for the remaining apps, mark as failed if non-conformant @@ -838,7 +837,7 @@ func (svc *Service) verifyDeviceSoftware(ctx context.Context, host *fleet.Host, if report.NonComplianceReason == "PENDING" || report.InstallationFailureReason == "IN_PROGRESS" { // keep as pending, the understanding is that another pub-sub will follow when the app's state // chances to installed or failed. - level.Debug(svc.logger).Log("msg", "Software not reported as installed yet, will remain pending", "host_uuid", hostUUID, "package_name", packageName, + svc.logger.DebugContext(ctx, "Software not reported as installed yet, will remain pending", "host_uuid", hostUUID, "package_name", packageName, "non_compliance_reason", report.NonComplianceReason, "installation_failure_reason", report.InstallationFailureReason) continue @@ -846,7 +845,7 @@ func (svc *Service) verifyDeviceSoftware(ctx context.Context, host *fleet.Host, // otherwise it has failed to install, mark as failed markVerified[packageName] = false - level.Error(svc.logger).Log("msg", "Software failed to install", "host_uuid", hostUUID, "package_name", packageName, + svc.logger.ErrorContext(ctx, "Software failed to install", "host_uuid", hostUUID, "package_name", packageName, "non_compliance_reason", report.NonComplianceReason, "installation_failure_reason", report.InstallationFailureReason, "specific_non_compliance_reason", report.SpecificNonComplianceReason) @@ -858,7 +857,7 @@ func (svc *Service) verifyDeviceSoftware(ctx context.Context, host *fleet.Host, // failed, we don't know how long it might take for the device to receive another // policy, it may never happen. markVerified[packageName] = false - level.Error(svc.logger).Log("msg", "Software failed to install without non-compliance report", "host_uuid", hostUUID, "package_name", packageName, + svc.logger.ErrorContext(ctx, "Software failed to install without non-compliance report", "host_uuid", hostUUID, "package_name", packageName, "installation_failure_reason", "unknown - no non-compliance report received") } @@ -875,11 +874,11 @@ func (svc *Service) verifyDeviceSoftware(ctx context.Context, host *fleet.Host, } } if err := svc.ds.BulkSetVPPInstallsAsVerified(ctx, host.ID, toVerifyUUIDs); err != nil { - level.Error(svc.logger).Log("msg", "error marking vpp installs as verified", "err", err, "host_uuid", hostUUID) + svc.logger.ErrorContext(ctx, "error marking vpp installs as verified", "err", err, "host_uuid", hostUUID) return } if err := svc.ds.BulkSetVPPInstallsAsFailed(ctx, host.ID, toFailUUIDs); err != nil { - level.Error(svc.logger).Log("msg", "error marking vpp installs as failed", "err", err, "host_uuid", hostUUID) + svc.logger.ErrorContext(ctx, "error marking vpp installs as failed", "err", err, "host_uuid", hostUUID) return } @@ -891,17 +890,17 @@ func (svc *Service) verifyDeviceSoftware(ctx context.Context, host *fleet.Host, return false } // otherwise it's a DB error and we should fail - level.Error(svc.logger).Log("msg", "error getting past activity for installed software", "err", err, "host_uuid", hostUUID) + svc.logger.ErrorContext(ctx, "error getting past activity for installed software", "err", err, "host_uuid", hostUUID) return true } if act == nil { // could happen if command is not found, but shouldn't - level.Debug(svc.logger).Log("msg", "getting past activity for installed software did not find the command", "host_uuid", hostUUID) + svc.logger.DebugContext(ctx, "getting past activity for installed software did not find the command", "host_uuid", hostUUID) return false } act.FromSetupExperience = true // currently, all Android app installs are from setup experience if err := svc.activityModule.NewActivity(ctx, user, act); err != nil { - level.Error(svc.logger).Log("msg", "error creating past activity for installed software", "err", err, "host_uuid", hostUUID) + svc.logger.ErrorContext(ctx, "error creating past activity for installed software", "err", err, "host_uuid", hostUUID) return true } return false @@ -969,8 +968,7 @@ func (svc *Service) calculateAndroidStorageMetrics( } // Log memory events for debugging - level.Debug(svc.logger).Log( - "msg", logPrefix+logSuffix, + svc.logger.DebugContext(ctx, logPrefix+logSuffix, "device_id", device.HardwareInfo.EnterpriseSpecificId, "total_internal_storage", totalStorageBytes, "memory_events_count", len(device.MemoryEvents), @@ -990,8 +988,7 @@ func (svc *Service) calculateAndroidStorageMetrics( var latestExternalMeasuredTime time.Time for _, event := range device.MemoryEvents { - level.Debug(svc.logger).Log( - "msg", "Android memory event"+logSuffix, + svc.logger.DebugContext(ctx, "Android memory event"+logSuffix, "event_type", event.EventType, "byte_count", event.ByteCount, "create_time", event.CreateTime, @@ -1000,8 +997,7 @@ func (svc *Service) calculateAndroidStorageMetrics( eventTime, err := time.Parse(time.RFC3339, event.CreateTime) if err != nil { // Log parse error but continue processing - level.Debug(svc.logger).Log( - "msg", "Failed to parse event time"+logSuffix, + svc.logger.DebugContext(ctx, "Failed to parse event time"+logSuffix, "event_type", event.EventType, "create_time", event.CreateTime, "error", err, @@ -1051,8 +1047,7 @@ func (svc *Service) calculateAndroidStorageMetrics( gigsDiskSpaceAvailable = -1 percentDiskSpaceAvailable = -1 - level.Debug(svc.logger).Log( - "msg", "Android storage measurement not supported"+logSuffix, + svc.logger.DebugContext(ctx, "Android storage measurement not supported"+logSuffix, "device_id", device.HardwareInfo.EnterpriseSpecificId, "total_storage_bytes", totalStorageBytes, "reason", "Only DETECTED events, no MEASURED events", @@ -1061,8 +1056,7 @@ func (svc *Service) calculateAndroidStorageMetrics( gigsDiskSpaceAvailable = float64(totalAvailableBytes) / (1024 * 1024 * 1024) percentDiskSpaceAvailable = (float64(totalAvailableBytes) / float64(totalStorageBytes)) * 100 - level.Debug(svc.logger).Log( - "msg", "Android storage calculation complete"+logSuffix, + svc.logger.DebugContext(ctx, "Android storage calculation complete"+logSuffix, "total_storage_bytes", totalStorageBytes, "total_available_bytes", totalAvailableBytes, "gigs_total", gigsTotalDiskSpace, diff --git a/server/mdm/android/service/pubsub_test.go b/server/mdm/android/service/pubsub_test.go index c4d93d3a5d..b291e405df 100644 --- a/server/mdm/android/service/pubsub_test.go +++ b/server/mdm/android/service/pubsub_test.go @@ -5,6 +5,7 @@ import ( "encoding/base64" "encoding/json" "errors" + "log/slog" "net/http" "os" "strconv" @@ -16,10 +17,10 @@ import ( "github.com/fleetdm/fleet/v4/server/fleet" "github.com/fleetdm/fleet/v4/server/mdm/android" android_mock "github.com/fleetdm/fleet/v4/server/mdm/android/mock" + "github.com/fleetdm/fleet/v4/server/platform/logging" common_mysql "github.com/fleetdm/fleet/v4/server/platform/mysql" "github.com/fleetdm/fleet/v4/server/ptr" "github.com/fleetdm/fleet/v4/server/service/modules/activities" - kitlog "github.com/go-kit/log" "github.com/google/uuid" "github.com/stretchr/testify/require" "google.golang.org/api/androidmanagement/v1" @@ -31,9 +32,9 @@ const testBrandTestSerialHashed = "9c311e05af14f958bd65188796e41fcc8a7b0ff913bfe func createAndroidService(t *testing.T) (android.Service, *AndroidMockDS) { androidAPIClient := android_mock.Client{} androidAPIClient.InitCommonMocks() - logger := kitlog.NewLogfmtLogger(os.Stdout) + logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) mockDS := InitCommonDSMocks() - activityModule := activities.NewActivityModule(mockDS, logger) + activityModule := activities.NewActivityModule(mockDS, logging.NewLogger(logger)) svc, err := NewServiceWithClient(logger, mockDS, &androidAPIClient, "test-private-key", &mockDS.DataStore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) diff --git a/server/mdm/android/service/reconcile_devices.go b/server/mdm/android/service/reconcile_devices.go index 12fb52954f..90c43eb88b 100644 --- a/server/mdm/android/service/reconcile_devices.go +++ b/server/mdm/android/service/reconcile_devices.go @@ -3,18 +3,17 @@ package service import ( "context" "fmt" + "log/slog" "time" "github.com/fleetdm/fleet/v4/server/contexts/ctxerr" "github.com/fleetdm/fleet/v4/server/fleet" - kitlog "github.com/go-kit/log" - "github.com/go-kit/log/level" ) // ReconcileAndroidDevices polls AMAPI for devices that Fleet still considers enrolled // and flips them to unenrolled if Google reports them missing (404). // This complements (does not replace) Pub/Sub DELETED handling. -func ReconcileAndroidDevices(ctx context.Context, ds fleet.Datastore, logger kitlog.Logger, licenseKey string) error { +func ReconcileAndroidDevices(ctx context.Context, ds fleet.Datastore, logger *slog.Logger, licenseKey string) error { appConfig, err := ds.AppConfig(ctx) if err != nil { return ctxerr.Wrap(ctx, err, "get app config") @@ -80,7 +79,7 @@ func ReconcileAndroidDevices(ctx context.Context, ds fleet.Datastore, logger kit continue case !ok: if _, derr := ds.SetAndroidHostUnenrolled(ctx, dev.HostID); derr != nil { - level.Error(logger).Log("msg", "failed to mark android host unenrolled during reconcile", "host_id", dev.HostID, "err", derr) + logger.ErrorContext(ctx, "failed to mark android host unenrolled during reconcile", "host_id", dev.HostID, "err", derr) continue } // Emit system activity to mirror Pub/Sub DELETED handling. @@ -95,13 +94,13 @@ func ReconcileAndroidDevices(ctx context.Context, ds fleet.Datastore, logger kit InstalledFromDEP: false, Platform: "android", }, nil, time.Now()); aerr != nil { - level.Debug(logger).Log("msg", "failed to create mdm_unenrolled activity during android reconcile", "host_id", dev.HostID, "err", aerr) + logger.DebugContext(ctx, "failed to create mdm_unenrolled activity during android reconcile", "host_id", dev.HostID, "err", aerr) } unenrolled++ - level.Debug(logger).Log("msg", "android device missing in Google; marked unenrolled", "host_id", dev.HostID, "device", deviceName) + logger.DebugContext(ctx, "android device missing in Google; marked unenrolled", "host_id", dev.HostID, "device", deviceName) } } - level.Debug(logger).Log("msg", "android reconcile complete", "checked", checked, "unenrolled", unenrolled) + logger.DebugContext(ctx, "android reconcile complete", "checked", checked, "unenrolled", unenrolled) return nil } diff --git a/server/mdm/android/service/service.go b/server/mdm/android/service/service.go index b222165238..a47f8877e9 100644 --- a/server/mdm/android/service/service.go +++ b/server/mdm/android/service/service.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "log/slog" "net/http" "net/url" "strings" @@ -23,8 +24,6 @@ import ( "github.com/fleetdm/fleet/v4/server/mdm/android" "github.com/fleetdm/fleet/v4/server/mdm/android/service/androidmgmt" "github.com/fleetdm/fleet/v4/server/service/modules/activities" - kitlog "github.com/go-kit/log" - "github.com/go-kit/log/level" "google.golang.org/api/androidmanagement/v1" "google.golang.org/api/googleapi" ) @@ -38,7 +37,7 @@ const ( ) type Service struct { - logger kitlog.Logger + logger *slog.Logger authz *authz.Authorizer ds fleet.AndroidDatastore fleetDS fleet.Datastore @@ -57,7 +56,7 @@ type Service struct { func NewService( ctx context.Context, - logger kitlog.Logger, + logger *slog.Logger, ds fleet.AndroidDatastore, licenseKey string, serverPrivateKey string, @@ -70,7 +69,7 @@ func NewService( } func NewServiceWithClient( - logger kitlog.Logger, + logger *slog.Logger, ds fleet.AndroidDatastore, client androidmgmt.Client, serverPrivateKey string, @@ -108,7 +107,7 @@ func NewServiceWithClient( return svc, nil } -func newAMAPIClient(ctx context.Context, logger kitlog.Logger, licenseKey string) androidmgmt.Client { +func newAMAPIClient(ctx context.Context, logger *slog.Logger, licenseKey string) androidmgmt.Client { var client androidmgmt.Client getEnv := dev_mode.Env if getEnv("FLEET_DEV_ANDROID_GOOGLE_CLIENT") == "1" || strings.ToUpper(getEnv("FLEET_DEV_ANDROID_GOOGLE_CLIENT")) == "ON" { @@ -372,7 +371,7 @@ func (svc *Service) EnterpriseSignupCallback(ctx context.Context, signupToken st switch { case fleet.IsNotFound(err): // This should never happen. - level.Error(svc.logger).Log("msg", "User that created the Android enterprise was not found", "user_id", enterprise.UserID) + svc.logger.ErrorContext(ctx, "User that created the Android enterprise was not found", "user_id", enterprise.UserID) case err != nil: return ctxerr.Wrap(ctx, err, "getting user") } @@ -692,7 +691,7 @@ func (svc *Service) EnterpriseSignupSSE(ctx context.Context) (chan string, error for { select { case <-ctx.Done(): - level.Debug(svc.logger).Log("msg", "Context cancelled during Android signup SSE") + svc.logger.DebugContext(ctx, "Context cancelled during Android signup SSE") return case <-time.After(svc.SignupSSEInterval): if svc.signupSSECheck(ctx, done) { @@ -743,24 +742,24 @@ func (svc *Service) verifyEnterpriseExistsWithGoogle(ctx context.Context, enterp case http.StatusNotFound: // Special case: 404 from proxy with deletion confirmation if strings.Contains(gerr.Message, "PROXY_VERIFIED_DELETED:") { - level.Info(svc.logger).Log("msg", "enterprise confirmed deleted by proxy", "enterpriseID", enterprise.EnterpriseID) + svc.logger.InfoContext(ctx, "enterprise confirmed deleted by proxy", "enterpriseID", enterprise.EnterpriseID) svc.cleanupDeletedEnterprise(ctx, enterprise, enterprise.EnterpriseID) return fleet.NewInvalidArgumentError("enterprise", "Android Enterprise has been deleted").WithStatus(http.StatusNotFound) } case http.StatusBadRequest: // Bad request might indicate missing headers or invalid request format // Don't delete the enterprise in this case - level.Error(svc.logger).Log("msg", "bad request when verifying enterprise", "error", err) + svc.logger.ErrorContext(ctx, "bad request when verifying enterprise", "error", err) return fmt.Errorf("verifying enterprise with Google: %s (check request headers and format)", err.Error()) case http.StatusUnauthorized, http.StatusForbidden: // Authentication/authorization issues - don't delete the enterprise - level.Error(svc.logger).Log("msg", "authentication/authorization error when verifying enterprise", "error", err) + svc.logger.ErrorContext(ctx, "authentication/authorization error when verifying enterprise", "error", err) return fmt.Errorf("verifying enterprise with Google: authentication error: %w", err) } } // LIST failed - this is likely a technical issue, not deletion // Log the error but don't delete the enterprise - level.Error(svc.logger).Log("msg", "failed to list enterprises", "error", err) + svc.logger.ErrorContext(ctx, "failed to list enterprises", "error", err) return fmt.Errorf("verifying enterprise with Google: %s", err.Error()) } @@ -774,7 +773,7 @@ func (svc *Service) verifyEnterpriseExistsWithGoogle(ctx context.Context, enterp } // Enterprise NOT in list - it's deleted - perform cleanup - level.Info(svc.logger).Log("msg", "enterprise confirmed deleted via LIST API", "enterpriseID", enterpriseID) + svc.logger.InfoContext(ctx, "enterprise confirmed deleted via LIST API", "enterpriseID", enterpriseID) svc.cleanupDeletedEnterprise(ctx, enterprise, enterpriseID) return fleet.NewInvalidArgumentError("enterprise", "Android Enterprise has been deleted").WithStatus(http.StatusNotFound) } @@ -799,26 +798,26 @@ func (svc *Service) cleanupDeletedEnterprise(ctx context.Context, enterprise *an // Clean up proxy database records by calling proxy DELETE endpoint // This ensures the proxy won't return conflicts when creating new signup URLs if deleteErr := svc.androidAPIClient.EnterpriseDelete(ctx, enterprise.Name()); deleteErr != nil { - level.Warn(svc.logger).Log("msg", "failed to delete proxy records after enterprise deletion (may not exist)", "err", deleteErr) + svc.logger.WarnContext(ctx, "failed to delete proxy records after enterprise deletion (may not exist)", "err", deleteErr) } // Delete local enterprise records if deleteErr := svc.ds.DeleteAllEnterprises(ctx); deleteErr != nil { - level.Error(svc.logger).Log("msg", "failed to delete local enterprise records after deletion", "err", deleteErr) + svc.logger.ErrorContext(ctx, "failed to delete local enterprise records after deletion", "err", deleteErr) } // Turn off Android MDM if setErr := svc.ds.SetAndroidEnabledAndConfigured(ctx, false); setErr != nil { - level.Error(svc.logger).Log("msg", "failed to turn off Android MDM after enterprise deletion", "err", setErr) + svc.logger.ErrorContext(ctx, "failed to turn off Android MDM after enterprise deletion", "err", setErr) } // Unenroll Android hosts if unenrollErr := svc.ds.BulkSetAndroidHostsUnenrolled(ctx); unenrollErr != nil { - level.Error(svc.logger).Log("msg", "failed to unenroll Android hosts after enterprise deletion", "err", unenrollErr) + svc.logger.ErrorContext(ctx, "failed to unenroll Android hosts after enterprise deletion", "err", unenrollErr) } if err := svc.ds.MarkAllPendingAndroidVPPInstallsAsFailed(ctx); err != nil { - level.Error(svc.logger).Log("msg", "failed to mark pending Android VPP installs as failed after enterprise deletion", "err", err) + svc.logger.ErrorContext(ctx, "failed to mark pending Android VPP installs as failed after enterprise deletion", "err", err) } } @@ -835,7 +834,7 @@ func (svc *Service) UnenrollAndroidHost(ctx context.Context, hostID uint) error } if !fleet.IsAndroidPlatform(host.Platform) { - level.Debug(svc.logger).Log("msg", "Skipping Android unenrollment for non-Android host", "host_id", host.ID, "platform", host.Platform) + svc.logger.DebugContext(ctx, "Skipping Android unenrollment for non-Android host", "host_id", host.ID, "platform", host.Platform) return nil // no-op for non-Android hosts } @@ -1063,7 +1062,7 @@ func (svc *Service) EnableAppReportsOnDefaultPolicy(ctx context.Context) error { if err != nil { if fleet.IsNotFound(err) { // Then Android MDM isn't setup yet, so no-op - level.Info(svc.logger).Log("msg", "skipping android default policy migration, Android MDM is not turned on") + svc.logger.InfoContext(ctx, "skipping android default policy migration, Android MDM is not turned on") return nil } return ctxerr.Wrap(ctx, err, "getting android enterprise") @@ -1312,7 +1311,7 @@ func (svc *Service) BuildAndSendFleetAgentConfig(ctx context.Context, enterprise // This prevents concurrent cron runs from processing the same templates certTemplates, err := svc.fleetDS.GetAndTransitionCertificateTemplatesToDelivering(ctx, hostUUID) if err != nil { - level.Error(svc.logger).Log("msg", "failed to get and transition to delivering", "host_uuid", hostUUID, "err", err) + svc.logger.ErrorContext(ctx, "failed to get and transition to delivering", "host_uuid", hostUUID, "err", err) return ctxerr.Wrapf(ctx, err, "get and transition certificate templates to delivering for host %s", hostUUID) } @@ -1325,12 +1324,12 @@ func (svc *Service) BuildAndSendFleetAgentConfig(ctx context.Context, enterprise // There should be no other certificates either, but including them just in case. config, err := buildHostConfig(hostUUID, certTemplates.Templates) if err != nil { - level.Error(svc.logger).Log("msg", "failed to build host config without certs", "host_uuid", hostUUID, "err", err) + svc.logger.ErrorContext(ctx, "failed to build host config without certs", "host_uuid", hostUUID, "err", err) return ctxerr.Wrapf(ctx, err, "build host config without certs for host %s", hostUUID) } hostConfigs := map[string]android.AgentManagedConfiguration{hostUUID: *config} if err := svc.AddFleetAgentToAndroidPolicy(ctx, enterpriseName, hostConfigs); err != nil { - level.Error(svc.logger).Log("msg", "failed to send AMAPI config without certs", "host_uuid", hostUUID, "err", err) + svc.logger.ErrorContext(ctx, "failed to send AMAPI config without certs", "host_uuid", hostUUID, "err", err) // Not a critical failure. We will retry installing Fleet Agent when certificates are added to the host's team } continue @@ -1339,16 +1338,16 @@ func (svc *Service) BuildAndSendFleetAgentConfig(ctx context.Context, enterprise // Step 2: Build and send config to AMAPI with ALL certificate templates config, err := buildHostConfig(hostUUID, certTemplates.Templates) if err != nil { - level.Error(svc.logger).Log("msg", "failed to build host config", "host_uuid", hostUUID, "err", err) + svc.logger.ErrorContext(ctx, "failed to build host config", "host_uuid", hostUUID, "err", err) return ctxerr.Wrapf(ctx, err, "build host config for %s", hostUUID) } hostConfigs := map[string]android.AgentManagedConfiguration{hostUUID: *config} if err := svc.AddFleetAgentToAndroidPolicy(ctx, enterpriseName, hostConfigs); err != nil { // AMAPI call failed, revert to pending for retry later - level.Error(svc.logger).Log("msg", "failed to send to AMAPI", "host_uuid", hostUUID, "err", err) + svc.logger.ErrorContext(ctx, "failed to send to AMAPI", "host_uuid", hostUUID, "err", err) if revertErr := svc.fleetDS.RevertHostCertificateTemplatesToPending(ctx, hostUUID, certTemplates.DeliveringTemplateIDs); revertErr != nil { - level.Error(svc.logger).Log("msg", "failed to revert to pending after AMAPI failure", "host_uuid", hostUUID, "err", revertErr) + svc.logger.ErrorContext(ctx, "failed to revert to pending after AMAPI failure", "host_uuid", hostUUID, "err", revertErr) return ctxerr.Wrapf(ctx, revertErr, "revert certificate templates to pending after AMAPI failure for host %s", hostUUID) } continue @@ -1356,7 +1355,7 @@ func (svc *Service) BuildAndSendFleetAgentConfig(ctx context.Context, enterprise // Step 3: Transition delivering → delivered if err := svc.fleetDS.TransitionCertificateTemplatesToDelivered(ctx, hostUUID, certTemplates.DeliveringTemplateIDs); err != nil { - level.Error(svc.logger).Log("msg", "failed to transition to delivered", "host_uuid", hostUUID, "err", err) + svc.logger.ErrorContext(ctx, "failed to transition to delivered", "host_uuid", hostUUID, "err", err) return ctxerr.Wrap(ctx, err, "transition certificate templates to delivered") } } diff --git a/server/mdm/android/tests/testing_utils.go b/server/mdm/android/tests/testing_utils.go index ad3d544a90..84d299204f 100644 --- a/server/mdm/android/tests/testing_utils.go +++ b/server/mdm/android/tests/testing_utils.go @@ -2,6 +2,7 @@ package tests import ( "context" + "log/slog" "net/http" "net/http/httptest" "os" @@ -18,12 +19,12 @@ import ( "github.com/fleetdm/fleet/v4/server/mdm/android/service/androidmgmt" ds_mock "github.com/fleetdm/fleet/v4/server/mock" "github.com/fleetdm/fleet/v4/server/platform/endpointer" + "github.com/fleetdm/fleet/v4/server/platform/logging" "github.com/fleetdm/fleet/v4/server/ptr" "github.com/fleetdm/fleet/v4/server/service/middleware/auth" "github.com/fleetdm/fleet/v4/server/service/middleware/log" "github.com/fleetdm/fleet/v4/server/service/modules/activities" kithttp "github.com/go-kit/kit/transport/http" - kitlog "github.com/go-kit/log" "github.com/gorilla/mux" "github.com/jmoiron/sqlx" "github.com/stretchr/testify/assert" @@ -111,13 +112,14 @@ func (ts *WithServer) SetupSuite(t *testing.T, dbName string) { ts.AndroidAPIClient = android_mock.Client{} ts.createCommonProxyMocks(t) - logger := kitlog.NewLogfmtLogger(os.Stdout) - activityModule := activities.NewActivityModule(&ts.DS.DataStore, logger) + logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) + kitLogger := logging.NewLogger(logger) + activityModule := activities.NewActivityModule(&ts.DS.DataStore, kitLogger) svc, err := service.NewServiceWithClient(logger, &ts.DS, &ts.AndroidAPIClient, "test-private-key", ts.DS.Datastore, activityModule, config.AndroidAgentConfig{}) require.NoError(t, err) ts.Svc = svc - ts.Server = runServerForTests(t, logger, &ts.FleetSvc, svc) + ts.Server = runServerForTests(t, kitLogger, &ts.FleetSvc, svc) } func (ts *WithServer) CreateCommonDSMocks() { @@ -206,7 +208,7 @@ func (m *mockService) NewActivity(ctx context.Context, user *fleet.User, details return m.Called(ctx, user, details).Error(0) } -func runServerForTests(t *testing.T, logger kitlog.Logger, fleetSvc fleet.Service, androidSvc android.Service) *httptest.Server { +func runServerForTests(t *testing.T, logger *logging.Logger, fleetSvc fleet.Service, androidSvc android.Service) *httptest.Server { // androidErrorEncoder wraps EncodeError with nil domain encoder for android tests androidErrorEncoder := func(ctx context.Context, err error, w http.ResponseWriter) { endpointer.EncodeError(ctx, err, w, nil) diff --git a/server/service/integration_android_certificate_templates_test.go b/server/service/integration_android_certificate_templates_test.go index 41c6163d7a..4c930cdc52 100644 --- a/server/service/integration_android_certificate_templates_test.go +++ b/server/service/integration_android_certificate_templates_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "log/slog" "net/http" "strings" "testing" @@ -13,10 +14,10 @@ import ( "github.com/fleetdm/fleet/v4/server/datastore/mysql" "github.com/fleetdm/fleet/v4/server/fleet" "github.com/fleetdm/fleet/v4/server/mdm/android" + "github.com/fleetdm/fleet/v4/server/platform/logging" "github.com/fleetdm/fleet/v4/server/ptr" "github.com/fleetdm/fleet/v4/server/service/contract" "github.com/fleetdm/fleet/v4/server/worker" - "github.com/go-kit/log" "github.com/google/uuid" "github.com/jmoiron/sqlx" "github.com/stretchr/testify/require" @@ -431,7 +432,7 @@ func (s *integrationMDMTestSuite) TestCertificateTemplateSpecEndpointAndAMAPIFai // Step: Queue and run the Android setup experience worker job // Note: Pending certificate templates were created above (simulating pubsub). The worker will deliver them. enterpriseName := "enterprises/" + enterpriseID - err = worker.QueueRunAndroidSetupExperience(ctx, s.ds, log.NewNopLogger(), host.UUID, &teamID, enterpriseName) + err = worker.QueueRunAndroidSetupExperience(ctx, s.ds, slog.New(logging.DiscardHandler{}), host.UUID, &teamID, enterpriseName) require.NoError(t, err) s.runWorker() @@ -533,7 +534,7 @@ func (s *integrationMDMTestSuite) TestCertificateTemplateNoTeamWithIDPVariable() // Step: Queue and run the Android setup experience worker job // Note: Pending certificate templates were created above (simulating pubsub). The worker will deliver them. enterpriseName := "enterprises/" + enterpriseID - err = worker.QueueRunAndroidSetupExperience(ctx, s.ds, log.NewNopLogger(), host.UUID, nil, enterpriseName) + err = worker.QueueRunAndroidSetupExperience(ctx, s.ds, slog.New(logging.DiscardHandler{}), host.UUID, nil, enterpriseName) require.NoError(t, err) s.runWorker() diff --git a/server/service/integration_mdm_test.go b/server/service/integration_mdm_test.go index 937effa3dc..6534da7487 100644 --- a/server/service/integration_mdm_test.go +++ b/server/service/integration_mdm_test.go @@ -225,7 +225,7 @@ func (s *integrationMDMTestSuite) SetupSuite() { androidMockClient.SetAuthenticationSecretFunc = func(secret string) error { return nil } - androidSvc, err := android_service.NewServiceWithClient(wlog, s.ds, androidMockClient, "test-private-key", s.ds, activityModule, config.AndroidAgentConfig{ + androidSvc, err := android_service.NewServiceWithClient(wlog.SlogLogger(), s.ds, androidMockClient, "test-private-key", s.ds, activityModule, config.AndroidAgentConfig{ Package: "com.fleetdm.agent", SigningSHA256: "abc123def456", }) @@ -410,7 +410,7 @@ func (s *integrationMDMTestSuite) SetupSuite() { if s.onCleanupScheduleDone != nil { defer s.onCleanupScheduleDone() } - return android_service.RenewCertificateTemplates(ctx, ds, logger) + return android_service.RenewCertificateTemplates(ctx, ds, logger.SlogLogger()) }), ) return cleanupsSchedule, nil @@ -432,7 +432,7 @@ func (s *integrationMDMTestSuite) SetupSuite() { s.onAndroidProfileJobDone() }() } - err := android_service.ReconcileProfilesWithClient(ctx, ds, logger, "", androidMockClient, config.AndroidAgentConfig{ + err := android_service.ReconcileProfilesWithClient(ctx, ds, logger.SlogLogger(), "", androidMockClient, config.AndroidAgentConfig{ Package: "com.fleetdm.agent", SigningSHA256: "abc123def456", }) diff --git a/server/service/integrationtest/android/suite.go b/server/service/integrationtest/android/suite.go index 5ec9c9ad87..db936a9bc0 100644 --- a/server/service/integrationtest/android/suite.go +++ b/server/service/integrationtest/android/suite.go @@ -28,7 +28,7 @@ func SetUpSuite(t *testing.T, uniqueTestName string) *Suite { proxy.InitCommonMocks() activityModule := activities.NewActivityModule(ds, logger) androidSvc, err := android_service.NewServiceWithClient( - logger, + logger.SlogLogger(), ds, &proxy, "test-private-key", diff --git a/server/worker/software_worker.go b/server/worker/software_worker.go index 2d2f09859e..b8fd3a7029 100644 --- a/server/worker/software_worker.go +++ b/server/worker/software_worker.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "log/slog" "github.com/fleetdm/fleet/v4/server/contexts/ctxerr" "github.com/fleetdm/fleet/v4/server/fleet" @@ -430,7 +431,7 @@ func buildApplicationPolicyWithConfig(ctx context.Context, appIDs []string, return appPolicies, nil } -func QueueRunAndroidSetupExperience(ctx context.Context, ds fleet.Datastore, logger kitlog.Logger, +func QueueRunAndroidSetupExperience(ctx context.Context, ds fleet.Datastore, logger *slog.Logger, hostUUID string, hostEnrollTeamID *uint, enterpriseName string) error { var enrollTeamID uint @@ -449,7 +450,7 @@ func QueueRunAndroidSetupExperience(ctx context.Context, ds fleet.Datastore, log return ctxerr.Wrap(ctx, err, "queueing job") } - level.Debug(logger).Log("job_id", job.ID, "job_name", softwareWorkerJobName, "task", args.Task) + logger.DebugContext(ctx, "queued android setup experience job", "job_id", job.ID, "job_name", softwareWorkerJobName, "task", args.Task) return nil }