@@ -71,6 +71,12 @@ Details: https://juicefs.com/docs/community/fault_diagnosis_and_analysis#profile
7171 Aliases : []string {"p" },
7272 Usage : "track only specified PIDs(separated by comma ,)" ,
7373 },
74+ & cli.StringFlag {
75+ Name : "paths" ,
76+ Aliases : []string {"filter-by-path" },
77+ Usage : "track only specified paths (separated by comma , Only for Windows FUSE log)" ,
78+ Hidden : true ,
79+ },
7480 & cli.Int64Flag {
7581 Name : "interval" ,
7682 Value : 2 ,
@@ -90,6 +96,7 @@ type profiler struct {
9096 uids []string
9197 gids []string
9298 pids []string
99+ paths []string
93100 entryChan chan * logEntry // one line
94101 statsChan chan map [string ]* stat
95102 pause chan bool
@@ -112,10 +119,11 @@ type logEntry struct {
112119 ts time.Time
113120 uid , gid , pid string
114121 op string
115- latency int // us
122+ latency int // us
123+ path string // only for Windows FUSE log
116124}
117125
118- func parseLine (line string ) * logEntry {
126+ func parseLine (line string , winFuseLog bool ) * logEntry {
119127 if len (line ) < 3 { // dummy line: "#"
120128 return nil
121129 }
@@ -140,20 +148,42 @@ func parseLine(line string) *logEntry {
140148 logger .Warnf ("Failed to parse log line: %s: %s" , line , err )
141149 return nil
142150 }
151+
152+ filePath := ""
153+ if winFuseLog {
154+ // Find the path in Windows log, should after the "{op} (/xxxx/bb bb/cc cc.*)"
155+ // the windows path may contain space or "(", ")"
156+ restPart := strings .Join (fields [4 :len (fields )- 1 ], " " )
157+ if strings .HasPrefix (restPart , "(" ) && strings .Contains (restPart , ")" ) {
158+ lastIndex := strings .LastIndex (restPart , ")" )
159+ if lastIndex > 1 {
160+ paths := strings .SplitN (restPart [1 :lastIndex ], "," , 2 )
161+ if len (paths ) > 0 {
162+ filePath = paths [0 ]
163+ }
164+ }
165+ }
166+
167+ if filePath == "" {
168+ logger .Warnf ("log line is invalid, cannot find path: %s" , line )
169+ }
170+ }
171+
143172 return & logEntry {
144173 ts : ts ,
145174 uid : ids [0 ],
146175 gid : ids [1 ],
147176 pid : ids [2 ],
148177 op : fields [3 ],
149178 latency : int (latFloat * 1000000.0 ),
179+ path : filePath ,
150180 }
151181}
152182
153183func (p * profiler ) reader () {
154184 scanner := bufio .NewScanner (p .file )
155185 for scanner .Scan () {
156- p .entryChan <- parseLine (scanner .Text ())
186+ p .entryChan <- parseLine (scanner .Text (), p . isWinFuseLog () )
157187 }
158188 if err := scanner .Err (); err != nil {
159189 logger .Fatalf ("Reading log file failed with error: %s" , err )
@@ -164,6 +194,10 @@ func (p *profiler) reader() {
164194 }
165195}
166196
197+ func (p * profiler ) isWinFuseLog () bool {
198+ return len (p .paths ) > 0
199+ }
200+
167201func (p * profiler ) isValid (entry * logEntry ) bool {
168202 valid := func (f []string , e string ) bool {
169203 if len (f ) == 1 && f [0 ] == "" {
@@ -176,7 +210,7 @@ func (p *profiler) isValid(entry *logEntry) bool {
176210 }
177211 return false
178212 }
179- return valid (p .uids , entry .uid ) && valid (p .gids , entry .gid ) && valid (p .pids , entry .pid )
213+ return valid (p .uids , entry .uid ) && valid (p .gids , entry .gid ) && valid (p .pids , entry .pid ) && valid ( p . paths , entry . path )
180214}
181215
182216func (p * profiler ) counter () {
@@ -376,6 +410,7 @@ func profile(ctx *cli.Context) error {
376410 uids : strings .Split (ctx .String ("uid" ), "," ),
377411 gids : strings .Split (ctx .String ("gid" ), "," ),
378412 pids : strings .Split (ctx .String ("pid" ), "," ),
413+ paths : strings .Split (ctx .String ("paths" ), "," ),
379414 entryChan : make (chan * logEntry , 16 ),
380415 statsChan : make (chan map [string ]* stat ),
381416 pause : make (chan bool ),
0 commit comments