zap icon indicating copy to clipboard operation
zap copied to clipboard

Windows paths not supported by default file sink

Open Apeopex opened this issue 5 years ago • 16 comments

When using absolute Windows paths, url.Parse does not retreieve the "file" scheme.

panic: couldn't open sink "C:\\Users\\...\\AppData\\Roaming\\...\\info.log.json": no sink found for scheme "c"

Appending, "file:///" (https://github.com/golang/go/issues/6027#issuecomment-66083310) does not work as expected. (Ref: https://github.com/golang/go/issues/13276 )

https://github.com/uber-go/zap/blob/ff33455a0e382e8a81d14dd7c922020b6b5e7982/sink.go#L99

Ref: https://github.com/golang/go/issues/13276#issuecomment-157074191 Changed by PR: #606

Temporary workaround:

func newWinFileSink(u *url.URL) (zap.Sink, error) {
    // Remove leading slash left by url.Parse()
    return os.OpenFile(u.Path[1:], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
}
zap.RegisterSink("winfile", newWinFileSink)
zap.Config{
    OutputPaths: []string{"stdout", "winfile:///" + filepath.Join(GlobalConfigDir.Path, "info.log.json")},
}

Apeopex avatar Aug 13 '18 21:08 Apeopex

yes, in windows file:///d:/a/wen88.log is not supported. Because, in this scene, url.Path is /d:/a/wen88.log, in windows you can't create file start with /, so in windows, you will strip the /.

wenzhihong2003 avatar Aug 20 '18 10:08 wenzhihong2003

I have pull a request in https://github.com/uber-go/zap/pull/624

wenzhihong2003 avatar Aug 20 '18 10:08 wenzhihong2003

The reason file:///d:/a/wen88.log doesn't work is that the path is /d:/a/..., can you replace the 3 / with 2 /, e.g., file://d:/a/wen88.log?

prashantv avatar Aug 23 '18 05:08 prashantv

I did try that and ran into the same issue listed here: https://github.com/golang/go/issues/13276

With backslashes: panic: couldn't open sink "file://C:\\Users\\~~\\Documents\\Web Development\\~~\\build\\info.log.json": can't parse "file://C:\\Users\\~~\\Documents\\Web Development\\~~\\build\\info.log.json" as a URL: parse file://C:\Users\~~\Documents\Web Development\~~\build\info.log.json: invalid character "\\" in host name

With forward slashes: panic: couldn't open sink "file://C:/Users/~~/Documents/Web Development/~~/build/info.log.json": file URLs must leave host empty or use localhost: got file://C:/Users/~~/Documents/Web%20Development/~~/build/info.log.json

Apeopex avatar Aug 23 '18 06:08 Apeopex

@prashantv , if use file://d:/a/wen88.log , it will paic with message

couldn't open sink "file://d:/a/wen88.log": file URLs must leave host empty or use localhost: got file://d:/a/wen88.log

because, file://d:/a/wen88.log parse to url.URL,

Host = "d:"
Path = "/a/wen88.log"

it will panic in https://github.com/uber-go/zap/blob/master/sink.go#L130

if hn := u.Hostname(); hn != "" && hn != "localhost" {
    return nil, fmt.Errorf("file URLs must leave host empty or use localhost: got %v", u)
}

wenzhihong2003 avatar Aug 24 '18 05:08 wenzhihong2003

That makes sense, thanks. It looks like it has to be 3 slashes, and is covered here: https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/

Is there any other examples of Go libraries that parse Windows file URIs?

prashantv avatar Aug 24 '18 22:08 prashantv

Any update on this one, i'm running into this issue right now on windows

sethkor avatar May 19 '19 10:05 sethkor

I just had the same problem. Might need to look into dimrocs pr and add those changes manually.

whatsadebugger avatar May 20 '19 00:05 whatsadebugger

https://github.com/smartcontractkit/chainlink/pull/977 copy logger_unix and _windows. Call the the registerOSSinks method to register the sink and you're good to go.

whatsadebugger avatar May 20 '19 00:05 whatsadebugger

+1

izikorgad avatar Sep 18 '19 07:09 izikorgad

+1, it still didn't work

Againster avatar Sep 27 '19 01:09 Againster

Dear maintainers, 3 years later this issue is still open and is breaking logging in https://github.com/open-telemetry/opentelemetry-collector

Is there any workaround yet that does not involve source changes? (which is not possible because we use otelcol release)

PR #624 was unfortunately never finished.

Mario-Hofstaetter avatar Apr 29 '22 20:04 Mario-Hofstaetter

@Mario-Hofstaetter Unfortunately, this has been a pretty low priority issue because we don't use Windows at work, and none of the active maintainers have Windows machines at home to be able to debug and fix this.

My feeling is that is that some mix of filepath.ToSlash/FromSlash will help solve this (I made an attempt in #999 last year), but the edit-test-debug loop was slow enough that I stopped trying.

abhinav avatar Apr 29 '22 22:04 abhinav

@Mario-Hofstaetter Unfortunately, this has been a pretty low priority issue because we don't use Windows at work, and none of the active maintainers have Windows machines at home to be able to debug and fix this.

My feeling is that is that some mix of filepath.ToSlash/FromSlash will help solve this (I made an attempt in #999 last year), but the edit-test-debug loop was slow enough that I stopped trying.

I understand that this issue is low-priority since you never use Windows at work. Golang is shipped with cross-platform ability, this issue really make users exhausted.

kmahyyg avatar Nov 22 '22 08:11 kmahyyg

There is some limited Windows support as of https://github.com/uber-go/zap/pull/1159

I think that change should have made v1.24 (@sywhang I don't see it in the release changelog, my PR didn't update the CHANGELOG, so it may have been missed?)

prashantv avatar Mar 14 '23 06:03 prashantv

funny, my zap logger is breaking on windows and i guess this is why.

Is the below still the recommended fix?

When using absolute Windows paths, url.Parse does not retreieve the "file" scheme.

panic: couldn't open sink "C:\\Users\\...\\AppData\\Roaming\\...\\info.log.json": no sink found for scheme "c"

Appending, "file:///" (golang/go#6027 (comment)) does not work as expected. (Ref: golang/go#13276 )

https://github.com/uber-go/zap/blob/ff33455a0e382e8a81d14dd7c922020b6b5e7982/sink.go#L99

Ref: golang/go#13276 (comment) Changed by PR: #606

Temporary workaround:

func newWinFileSink(u *url.URL) (zap.Sink, error) {
    // Remove leading slash left by url.Parse()
    return os.OpenFile(u.Path[1:], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
}
zap.RegisterSink("winfile", newWinFileSink)
zap.Config{
    OutputPaths: []string{"stdout", "winfile:///" + filepath.Join(GlobalConfigDir.Path, "info.log.json")},
}

yehudamakarov avatar Feb 21 '24 18:02 yehudamakarov