Skip to content

Commit 05c5292

Browse files
feat(mount id): Support custom mount ID and rationalize only-dir early (#4991)
Adding support for specifying a custom Mount ID to be included in mount instance id and refactors only-dir path rationalization so that it is normalized early during configuration processing.
1 parent 20de2f9 commit 05c5292

13 files changed

Lines changed: 131 additions & 54 deletions

cfg/config.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,8 @@ type Config struct {
523523

524524
Metrics MetricsConfig `yaml:"metrics"`
525525

526+
MountId string `yaml:"mount-id"`
527+
526528
Mrd MrdConfig `yaml:"mrd"`
527529

528530
OnlyDir string `yaml:"only-dir"`
@@ -1340,6 +1342,12 @@ func BuildFlagSet(flagSet *pflag.FlagSet) error {
13401342
return err
13411343
}
13421344

1345+
flagSet.StringP("mount-id", "", "", "Custom identifier to be appended to the mount ID and printed in all logs.")
1346+
1347+
if err := flagSet.MarkHidden("mount-id"); err != nil {
1348+
return err
1349+
}
1350+
13431351
flagSet.IntP("mrd-pool-size", "", 4, "Specifies the MRD pool size to be used for zonal buckets. The value should be more than 0.")
13441352

13451353
if err := flagSet.MarkHidden("mrd-pool-size"); err != nil {
@@ -1975,6 +1983,10 @@ func BindFlags(v *viper.Viper, flagSet *pflag.FlagSet) error {
19751983
return err
19761984
}
19771985

1986+
if err := v.BindPFlag("mount-id", flagSet.Lookup("mount-id")); err != nil {
1987+
return err
1988+
}
1989+
19781990
if err := v.BindPFlag("mrd.pool-size", flagSet.Lookup("mrd-pool-size")); err != nil {
19791991
return err
19801992
}

cfg/params.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,13 @@ params:
11651165
default: "3"
11661166
hide-flag: true
11671167

1168+
- config-path: "mount-id"
1169+
flag-name: "mount-id"
1170+
type: "string"
1171+
usage: "Custom identifier to be appended to the mount ID and printed in all logs."
1172+
default: ""
1173+
hide-flag: true
1174+
11681175
- config-path: "mrd.pool-size"
11691176
flag-name: "mrd-pool-size"
11701177
type: "int"

cfg/rationalize.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"log"
1919
"math"
2020
"net/url"
21+
"path"
2122
"slices"
2223
"strings"
2324

@@ -166,6 +167,15 @@ func resolveGCSRetriesConfig(c *GcsRetriesConfig) {
166167
}
167168
}
168169

170+
// resolveOnlyDir normalizes OnlyDir to a clean relative path without leading
171+
// or trailing slashes (e.g., "foo/bar/.." -> "foo", "/foo/bar/" -> "foo/bar").
172+
func resolveOnlyDir(c *Config) {
173+
if c.OnlyDir != "" {
174+
clean := strings.TrimPrefix(path.Clean("/"+c.OnlyDir), "/")
175+
c.OnlyDir = clean
176+
}
177+
}
178+
169179
// Rationalize updates the config fields based on the values of other fields.
170180
func Rationalize(v *viper.Viper, c *Config, optimizedFlags []string) error {
171181
var err error
@@ -187,6 +197,7 @@ func Rationalize(v *viper.Viper, c *Config, optimizedFlags []string) error {
187197
resolveParallelDownloadsValue(v, &c.FileCache, c)
188198
resolveFileCacheAndBufferedReadConflict(v, c)
189199
resolveGCSRetriesConfig(&c.GcsRetries)
200+
resolveOnlyDir(c)
190201

191202
return nil
192203
}

cfg/rationalize_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,3 +901,31 @@ func TestRationalize_MetadataCacheConfig(t *testing.T) {
901901
})
902902
}
903903
}
904+
905+
func TestResolveOnlyDir(t *testing.T) {
906+
testCases := []struct {
907+
name string
908+
input string
909+
expected string
910+
}{
911+
{"Clean relative path", "foo/bar", "foo/bar"},
912+
{"Trailing slash", "foo/bar/", "foo/bar"},
913+
{"Leading slash", "/foo/bar", "foo/bar"},
914+
{"Leading and trailing slashes", "/foo/bar/", "foo/bar"},
915+
{"Relative parent segment", "foo/../bar/", "bar"},
916+
{"Root slash", "/", ""},
917+
{"Root dot", "/.", ""},
918+
{"Parent directory", "..", ""},
919+
{"Root parent directory", "/..", ""},
920+
{"Current directory prefix", "./foo", "foo"},
921+
{"Parent directory prefix", "../foo", "foo"},
922+
{"Empty string", "", ""},
923+
}
924+
for _, tc := range testCases {
925+
t.Run(tc.name, func(t *testing.T) {
926+
c := &Config{OnlyDir: tc.input}
927+
resolveOnlyDir(c)
928+
assert.Equal(t, tc.expected, c.OnlyDir)
929+
})
930+
}
931+
}

cmd/legacy_main.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ func mountWithArgs(bucketName string, mountPoint string, newConfig *cfg.Config,
203203
// connection.
204204
var storageHandle storage.StorageHandle
205205
if bucketName != canned.FakeBucketName {
206-
userAgent := getUserAgent(newConfig.AppName, getConfigForUserAgent(newConfig), logger.MountInstanceID(fsName(bucketName)))
206+
userAgent := getUserAgent(newConfig.AppName, getConfigForUserAgent(newConfig), logger.MountInstanceID(fsName(bucketName), newConfig.MountId))
207207
logger.Info("Creating Storage handle...")
208208
storageHandle, err = createStorageHandle(newConfig, userAgent, metricHandle, isGKE, isDynamicMount(bucketName))
209209
if err != nil {
@@ -388,7 +388,7 @@ func Mount(mountInfo *mountInfo, bucketName, mountPoint string) (err error) {
388388

389389
var logExporterShutdownFn common.ShutdownFn
390390
if newConfig.Foreground {
391-
err = logger.InitLogFile(newConfig.Logging, fsName(bucketName))
391+
err = logger.InitLogFile(newConfig.Logging, fsName(bucketName), newConfig.MountId)
392392
if err != nil {
393393
return fmt.Errorf("init log file: %w", err)
394394
}
@@ -397,14 +397,14 @@ func Mount(mountInfo *mountInfo, bucketName, mountPoint string) (err error) {
397397
// startup configs and mount flags are captured. This is intentionally skipped
398398
// in the ephemeral parent process to avoid double-initialization overhead.
399399
// TODO: Update mount-id to use directory name as well in only dir mounting.
400-
logExporterShutdownFn, err = monitor.SetupOTelLogExporter(context.Background(), newConfig.Logging.ExperimentalOtelLoggingEndpoint, logger.MountInstanceID(fsName(bucketName)), newConfig.GcsAuth, newConfig.Logging.ExperimentalOtelLoggingProjectId)
400+
logExporterShutdownFn, err = monitor.SetupOTelLogExporter(context.Background(), newConfig.Logging.ExperimentalOtelLoggingEndpoint, logger.MountInstanceID(fsName(bucketName), newConfig.MountId), newConfig.GcsAuth, newConfig.Logging.ExperimentalOtelLoggingProjectId)
401401
if err != nil {
402402
logger.Errorf("Failed to setup OTel log exporter: %v", err)
403403
}
404404
}
405405
}
406406

407-
logger.UpdateDefaultLogger(newConfig.Logging.Format, fsName(bucketName))
407+
logger.UpdateDefaultLogger(newConfig.Logging.Format, fsName(bucketName), newConfig.MountId)
408408

409409
logger.Infof("Start gcsfuse/%s for app %q using mount point: %s\n", common.GetVersion(), newConfig.AppName, mountPoint)
410410

@@ -475,12 +475,12 @@ func Mount(mountInfo *mountInfo, bucketName, mountPoint string) (err error) {
475475
var metricExporterShutdownFn common.ShutdownFn
476476
metricHandle := metrics.NewNoopMetrics()
477477
if cfg.IsMetricsEnabled(&newConfig.Metrics) {
478-
metricExporterShutdownFn = monitor.SetupOTelMetricExporters(ctx, newConfig, logger.MountInstanceID(fsName(bucketName)))
478+
metricExporterShutdownFn = monitor.SetupOTelMetricExporters(ctx, newConfig, logger.MountInstanceID(fsName(bucketName), newConfig.MountId))
479479
if metricHandle, err = metrics.NewOTelMetrics(ctx, int(newConfig.Metrics.Workers), int(newConfig.Metrics.BufferSize)); err != nil {
480480
metricHandle = metrics.NewNoopMetrics()
481481
}
482482
}
483-
shutdownTracingFn := monitor.SetupTracing(ctx, newConfig, logger.MountInstanceID(fsName(bucketName)))
483+
shutdownTracingFn := monitor.SetupTracing(ctx, newConfig, logger.MountInstanceID(fsName(bucketName), newConfig.MountId))
484484
traceHandle := tracing.NewNoopTracer()
485485
if cfg.IsTracingEnabled(newConfig) {
486486
traceHandle = tracing.NewOTELTracer()

cmd/mount.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,10 @@ func getFuseMountConfig(fsName string, newConfig *cfg.Config) *fuse.MountConfig
232232
// DEBUG ERROR
233233
// TRACE TRACE
234234
if newConfig.Logging.Severity.Rank() <= cfg.ErrorLogSeverity.Rank() {
235-
mountCfg.ErrorLogger = logger.NewLegacyLogger(logger.LevelError, "fuse: ", fsName)
235+
mountCfg.ErrorLogger = logger.NewLegacyLogger(logger.LevelError, "fuse: ", fsName, newConfig.MountId)
236236
}
237237
if newConfig.Logging.Severity.Rank() <= cfg.TraceLogSeverity.Rank() {
238-
mountCfg.DebugLogger = logger.NewLegacyLogger(logger.LevelTrace, "fuse_debug: ", fsName)
238+
mountCfg.DebugLogger = logger.NewLegacyLogger(logger.LevelTrace, "fuse_debug: ", fsName, newConfig.MountId)
239239
}
240240
return mountCfg
241241
}

internal/fs/fs_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,11 @@ func (t *fsTest) SetUpTestSuite() {
196196

197197
// Initialize Fuse Loggers.
198198
if mountCfg.ErrorLogger == nil {
199-
mountCfg.ErrorLogger = logger.NewLegacyLogger(logger.LevelError, "fuse_errors: ", mountCfg.FSName)
199+
mountCfg.ErrorLogger = logger.NewLegacyLogger(logger.LevelError, "fuse_errors: ", mountCfg.FSName, "")
200200
}
201201

202202
if *fDebug {
203-
mountCfg.DebugLogger = logger.NewLegacyLogger(logger.LevelDebug, "fuse: ", mountCfg.FSName)
203+
mountCfg.DebugLogger = logger.NewLegacyLogger(logger.LevelDebug, "fuse: ", mountCfg.FSName, "")
204204
}
205205
// Mount the file system.
206206
mfs, err = fuse.Mount(mntDir, server, &mountCfg)

internal/gcsx/bucket_manager.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"context"
1919
"errors"
2020
"fmt"
21-
"path"
2221
"time"
2322

2423
"github.com/googlecloudplatform/gcsfuse/v3/cfg"
@@ -208,7 +207,7 @@ func (bm *bucketManager) SetUpBucket(
208207

209208
// Limit to a requested prefix of the bucket, if any.
210209
if bm.config.OnlyDir != "" {
211-
b, err = NewPrefixBucket(path.Clean(bm.config.OnlyDir)+"/", b)
210+
b, err = NewPrefixBucket(bm.config.OnlyDir+"/", b)
212211
if err != nil {
213212
err = fmt.Errorf("NewPrefixBucket: %w", err)
214213
return

internal/logger/legacy_logger.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ import (
2727
// individual log messages.
2828
// This method is created to support jacobsa/fuse loggers and will be removed
2929
// after slog support is added.
30-
func NewLegacyLogger(level slog.Level, prefix, fsName string) *log.Logger {
31-
handler := defaultLoggerFactory.handler(programLevel, prefix).WithAttrs(loggerAttr(fsName))
30+
func NewLegacyLogger(level slog.Level, prefix, fsName, customID string) *log.Logger {
31+
handler := defaultLoggerFactory.handler(programLevel, prefix).WithAttrs(loggerAttr(fsName, customID))
3232
logger := slog.NewLogLogger(handler, level)
3333
setLoggingLevel(defaultLoggerFactory.level)
3434
return logger

internal/logger/logger.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ var (
6262
// config.
6363
// Here, background true means, this InitLogFile has been called for the
6464
// background daemon.
65-
func InitLogFile(newLogConfig cfg.LoggingConfig, fsName string) error {
65+
func InitLogFile(newLogConfig cfg.LoggingConfig, fsName, customID string) error {
6666
var f *os.File
6767
var sysWriter *syslog.Writer
6868
var fileWriter *lumberjack.Logger
@@ -106,7 +106,7 @@ func InitLogFile(newLogConfig cfg.LoggingConfig, fsName string) error {
106106
logRotate: newLogConfig.LogRotate,
107107
enableOtelLogging: newLogConfig.ExperimentalEnableOtelLogging,
108108
}
109-
defaultLogger = defaultLoggerFactory.newLoggerWithMountInstanceID(string(newLogConfig.Severity), fsName)
109+
defaultLogger = defaultLoggerFactory.newLoggerWithMountInstanceID(string(newLogConfig.Severity), fsName, customID)
110110

111111
return nil
112112
}
@@ -164,17 +164,20 @@ func MountUUID() string {
164164
}
165165

166166
// MountInstanceID returns the InstanceID of current gcsfuse mount.
167-
// This is combination of `fsName` + MountUUID.
168-
// Note: fsName is passed here explicitly, as logger package doesn't know about fsName
167+
// This is combination of `fsName` + optional `customID` + MountUUID.
168+
// Note: fsName and customID are passed here explicitly, as logger package doesn't know about them
169169
// when MountInstanceID method is invoked.
170-
func MountInstanceID(fsName string) string {
170+
func MountInstanceID(fsName, customID string) string {
171+
if customID != "" {
172+
return fmt.Sprintf("%s-%s-%s", fsName, customID, MountUUID())
173+
}
171174
return fmt.Sprintf("%s-%s", fsName, MountUUID())
172175
}
173176

174177
// UpdateDefaultLogger updates the log format and creates a new logger with MountInstanceID set as custom attribute.
175-
func UpdateDefaultLogger(format, fsName string) {
178+
func UpdateDefaultLogger(format, fsName, customID string) {
176179
defaultLoggerFactory.format = format
177-
defaultLogger = defaultLoggerFactory.newLoggerWithMountInstanceID(defaultLoggerFactory.level, fsName)
180+
defaultLogger = defaultLoggerFactory.newLoggerWithMountInstanceID(defaultLoggerFactory.level, fsName, customID)
178181
}
179182

180183
// Tracef prints the message with TRACE severity in the specified format.
@@ -279,13 +282,13 @@ func (f *loggerFactory) newLogger(level string) *slog.Logger {
279282
return logger
280283
}
281284

282-
func loggerAttr(fsName string) []slog.Attr {
283-
return []slog.Attr{slog.String(MountIDKey, MountInstanceID(fsName))}
285+
func loggerAttr(fsName, customID string) []slog.Attr {
286+
return []slog.Attr{slog.String(MountIDKey, MountInstanceID(fsName, customID))}
284287
}
285288

286289
// create a new logger with mountInstanceID set as custom attribute on logger.
287-
func (f *loggerFactory) newLoggerWithMountInstanceID(level, fsName string) *slog.Logger {
288-
logger := slog.New(f.handler(programLevel, "").WithAttrs(loggerAttr(fsName)))
290+
func (f *loggerFactory) newLoggerWithMountInstanceID(level, fsName, customID string) *slog.Logger {
291+
logger := slog.New(f.handler(programLevel, "").WithAttrs(loggerAttr(fsName, customID)))
289292
slog.SetDefault(logger)
290293
setLoggingLevel(level)
291294
return logger

0 commit comments

Comments
 (0)