Add proper, formatted logging
This commit is contained in:
parent
1bf1c942e0
commit
9a5646ad6c
|
@ -53,7 +53,7 @@ func invokeHook(typ HookType, info tusd.FileInfo) {
|
||||||
go func() {
|
go func() {
|
||||||
_, err := invokeHookSync(typ, info, false)
|
_, err := invokeHookSync(typ, info, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stderr.Printf("Error running %s hook for %s: %s", string(typ), info.ID, err)
|
logEv("HookInvocationError", "type", string(typ), "id", info.ID, "error", err.Error())
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -61,9 +61,9 @@ func invokeHook(typ HookType, info tusd.FileInfo) {
|
||||||
func invokeHookSync(typ HookType, info tusd.FileInfo, captureOutput bool) ([]byte, error) {
|
func invokeHookSync(typ HookType, info tusd.FileInfo, captureOutput bool) ([]byte, error) {
|
||||||
switch typ {
|
switch typ {
|
||||||
case HookPostFinish:
|
case HookPostFinish:
|
||||||
stdout.Printf("Upload %s (%d bytes) finished\n", info.ID, info.Size)
|
logEv("UploadFinished", "id", info.ID, "size", strconv.FormatInt(info.Size, 10))
|
||||||
case HookPostTerminate:
|
case HookPostTerminate:
|
||||||
stdout.Printf("Upload %s terminated\n", info.ID)
|
logEv("UploadTerminated", "id", info.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !Flags.HooksInstalled {
|
if !Flags.HooksInstalled {
|
||||||
|
@ -71,7 +71,7 @@ func invokeHookSync(typ HookType, info tusd.FileInfo, captureOutput bool) ([]byt
|
||||||
}
|
}
|
||||||
|
|
||||||
name := string(typ)
|
name := string(typ)
|
||||||
stdout.Printf("Invoking %s hook…\n", name)
|
logEv("HookInvocationStart", "type", name, "id", info.ID)
|
||||||
|
|
||||||
cmd := exec.Command(Flags.HooksDir + "/" + name)
|
cmd := exec.Command(Flags.HooksDir + "/" + name)
|
||||||
env := os.Environ()
|
env := os.Environ()
|
||||||
|
@ -103,7 +103,7 @@ func invokeHookSync(typ HookType, info tusd.FileInfo, captureOutput bool) ([]byt
|
||||||
// Ignore the error, only, if the hook's file could not be found. This usually
|
// Ignore the error, only, if the hook's file could not be found. This usually
|
||||||
// means that the user is only using a subset of the available hooks.
|
// means that the user is only using a subset of the available hooks.
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
stdout.Printf("Unable to invoke %s hook: %s\n", name, err)
|
logEv("HookInvocationError", "type", string(typ), "id", info.ID, "error", err.Error())
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,13 @@ package cli
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/tus/tusd"
|
||||||
)
|
)
|
||||||
|
|
||||||
var stdout = log.New(os.Stdout, "[tusd] ", 0)
|
var stdout = log.New(os.Stdout, "[tusd] ", 0)
|
||||||
var stderr = log.New(os.Stderr, "[tusd] ", 0)
|
var stderr = log.New(os.Stderr, "[tusd] ", 0)
|
||||||
|
|
||||||
|
func logEv(eventName string, details ...string) {
|
||||||
|
tusd.LogEvent(stderr, eventName, details...)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package tusd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *UnroutedHandler) log(eventName string, details ...string) {
|
||||||
|
LogEvent(h.logger, eventName, details...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogEvent(logger *log.Logger, eventName string, details ...string) {
|
||||||
|
result := make([]byte, 0, 100)
|
||||||
|
|
||||||
|
result = append(result, `event="`...)
|
||||||
|
result = append(result, eventName...)
|
||||||
|
result = append(result, `" `...)
|
||||||
|
|
||||||
|
for i := 0; i < len(details); i += 2 {
|
||||||
|
result = append(result, details[i]...)
|
||||||
|
result = append(result, `="`...)
|
||||||
|
result = append(result, details[i+1]...)
|
||||||
|
result = append(result, `" `...)
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, "\n"...)
|
||||||
|
logger.Output(2, string(result))
|
||||||
|
}
|
|
@ -126,10 +126,9 @@ func (handler *UnroutedHandler) Middleware(h http.Handler) http.Handler {
|
||||||
r.Method = newMethod
|
r.Method = newMethod
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
handler.log("RequestIncoming", "method", r.Method, "path", r.URL.Path)
|
||||||
handler.logger.Println(r.Method, r.URL.Path)
|
|
||||||
handler.Metrics.incRequestsTotal(r.Method)
|
go handler.Metrics.incRequestsTotal(r.Method)
|
||||||
}()
|
|
||||||
|
|
||||||
header := w.Header()
|
header := w.Header()
|
||||||
|
|
||||||
|
@ -171,7 +170,7 @@ func (handler *UnroutedHandler) Middleware(h http.Handler) http.Handler {
|
||||||
// will be ignored or interpreted as a rejection.
|
// will be ignored or interpreted as a rejection.
|
||||||
// For example, the Presto engine, which is used in older versions of
|
// For example, the Presto engine, which is used in older versions of
|
||||||
// Opera, Opera Mobile and Opera Mini, handles CORS this way.
|
// Opera, Opera Mobile and Opera Mini, handles CORS this way.
|
||||||
w.WriteHeader(http.StatusOK)
|
handler.sendResp(w, r, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,6 +267,7 @@ func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request)
|
||||||
w.Header().Set("Location", url)
|
w.Header().Set("Location", url)
|
||||||
|
|
||||||
go handler.Metrics.incUploadsCreated()
|
go handler.Metrics.incUploadsCreated()
|
||||||
|
handler.log("UploadCreated", "id", id, "size", i64toa(size), "url", url)
|
||||||
|
|
||||||
if isFinal {
|
if isFinal {
|
||||||
if err := handler.composer.Concater.ConcatUploads(id, partialUploads); err != nil {
|
if err := handler.composer.Concater.ConcatUploads(id, partialUploads); err != nil {
|
||||||
|
@ -299,7 +299,7 @@ func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
handler.sendResp(w, r, http.StatusCreated)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HeadFile returns the length and offset for the HEAD request
|
// HeadFile returns the length and offset for the HEAD request
|
||||||
|
@ -347,7 +347,7 @@ func (handler *UnroutedHandler) HeadFile(w http.ResponseWriter, r *http.Request)
|
||||||
w.Header().Set("Cache-Control", "no-store")
|
w.Header().Set("Cache-Control", "no-store")
|
||||||
w.Header().Set("Upload-Length", strconv.FormatInt(info.Size, 10))
|
w.Header().Set("Upload-Length", strconv.FormatInt(info.Size, 10))
|
||||||
w.Header().Set("Upload-Offset", strconv.FormatInt(info.Offset, 10))
|
w.Header().Set("Upload-Offset", strconv.FormatInt(info.Offset, 10))
|
||||||
w.WriteHeader(http.StatusOK)
|
handler.sendResp(w, r, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PatchFile adds a chunk to an upload. Only allowed enough space is left.
|
// PatchFile adds a chunk to an upload. Only allowed enough space is left.
|
||||||
|
@ -402,7 +402,7 @@ func (handler *UnroutedHandler) PatchFile(w http.ResponseWriter, r *http.Request
|
||||||
// Do not proxy the call to the data store if the upload is already completed
|
// Do not proxy the call to the data store if the upload is already completed
|
||||||
if info.Offset == info.Size {
|
if info.Offset == info.Size {
|
||||||
w.Header().Set("Upload-Offset", strconv.FormatInt(offset, 10))
|
w.Header().Set("Upload-Offset", strconv.FormatInt(offset, 10))
|
||||||
w.WriteHeader(http.StatusNoContent)
|
handler.sendResp(w, r, http.StatusNoContent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +411,7 @@ func (handler *UnroutedHandler) PatchFile(w http.ResponseWriter, r *http.Request
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
handler.sendResp(w, r, http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PatchFile adds a chunk to an upload. Only allowed enough space is left.
|
// PatchFile adds a chunk to an upload. Only allowed enough space is left.
|
||||||
|
@ -430,6 +430,8 @@ func (handler *UnroutedHandler) writeChunk(id string, info FileInfo, w http.Resp
|
||||||
maxSize = length
|
maxSize = length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handler.log("ChunkWriteStart", "id", id, "maxSize", i64toa(maxSize), "offset", i64toa(offset))
|
||||||
|
|
||||||
var bytesWritten int64
|
var bytesWritten int64
|
||||||
// Prevent a nil pointer derefernce when accessing the body which may not be
|
// Prevent a nil pointer derefernce when accessing the body which may not be
|
||||||
// available in the case of a malicious request.
|
// available in the case of a malicious request.
|
||||||
|
@ -444,6 +446,8 @@ func (handler *UnroutedHandler) writeChunk(id string, info FileInfo, w http.Resp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handler.log("ChunkWriteComplete", "id", id, "bytesWritten", i64toa(bytesWritten))
|
||||||
|
|
||||||
// Send new offset to client
|
// Send new offset to client
|
||||||
newOffset := offset + bytesWritten
|
newOffset := offset + bytesWritten
|
||||||
w.Header().Set("Upload-Offset", strconv.FormatInt(newOffset, 10))
|
w.Header().Set("Upload-Offset", strconv.FormatInt(newOffset, 10))
|
||||||
|
@ -502,7 +506,7 @@ func (handler *UnroutedHandler) GetFile(w http.ResponseWriter, r *http.Request)
|
||||||
|
|
||||||
// Do not do anything if no data is stored yet.
|
// Do not do anything if no data is stored yet.
|
||||||
if info.Offset == 0 {
|
if info.Offset == 0 {
|
||||||
w.WriteHeader(http.StatusNoContent)
|
handler.sendResp(w, r, http.StatusNoContent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,7 +522,7 @@ func (handler *UnroutedHandler) GetFile(w http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Length", strconv.FormatInt(info.Offset, 10))
|
w.Header().Set("Content-Length", strconv.FormatInt(info.Offset, 10))
|
||||||
w.WriteHeader(http.StatusOK)
|
handler.sendResp(w, r, http.StatusOK)
|
||||||
io.Copy(w, src)
|
io.Copy(w, src)
|
||||||
|
|
||||||
// Try to close the reader if the io.Closer interface is implemented
|
// Try to close the reader if the io.Closer interface is implemented
|
||||||
|
@ -566,7 +570,7 @@ func (handler *UnroutedHandler) DelFile(w http.ResponseWriter, r *http.Request)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
handler.sendResp(w, r, http.StatusNoContent)
|
||||||
|
|
||||||
if handler.config.NotifyTerminatedUploads {
|
if handler.config.NotifyTerminatedUploads {
|
||||||
handler.TerminatedUploads <- info
|
handler.TerminatedUploads <- info
|
||||||
|
@ -598,9 +602,18 @@ func (handler *UnroutedHandler) sendError(w http.ResponseWriter, r *http.Request
|
||||||
w.WriteHeader(status)
|
w.WriteHeader(status)
|
||||||
w.Write([]byte(reason))
|
w.Write([]byte(reason))
|
||||||
|
|
||||||
|
handler.log("ResponseOutgoing", "status", strconv.Itoa(status), "method", r.Method, "path", r.URL.Path, "error", err.Error())
|
||||||
|
|
||||||
go handler.Metrics.incErrorsTotal(err)
|
go handler.Metrics.incErrorsTotal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sendResp writes the header to w with the specified status code.
|
||||||
|
func (handler *UnroutedHandler) sendResp(w http.ResponseWriter, r *http.Request, status int) {
|
||||||
|
w.WriteHeader(status)
|
||||||
|
|
||||||
|
handler.log("ResponseOutgoing", "status", strconv.Itoa(status), "method", r.Method, "path", r.URL.Path)
|
||||||
|
}
|
||||||
|
|
||||||
// Make an absolute URLs to the given upload id. If the base path is absolute
|
// Make an absolute URLs to the given upload id. If the base path is absolute
|
||||||
// it will be prepended else the host and protocol from the request is used.
|
// it will be prepended else the host and protocol from the request is used.
|
||||||
func (handler *UnroutedHandler) absFileURL(r *http.Request, id string) string {
|
func (handler *UnroutedHandler) absFileURL(r *http.Request, id string) string {
|
||||||
|
@ -772,3 +785,7 @@ func extractIDFromPath(url string) (string, error) {
|
||||||
}
|
}
|
||||||
return result[1], nil
|
return result[1], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func i64toa(num int64) string {
|
||||||
|
return strconv.FormatInt(num, 10)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue