Created
April 10, 2020 23:49
-
-
Save samthor/c12e129a05785abdcb60b17da5583f9a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package loggerwrap | |
import ( | |
"context" | |
"fmt" | |
"net/http" | |
"os" | |
"strings" | |
"cloud.google.com/go/logging" | |
mrpb "google.golang.org/genproto/googleapis/api/monitoredres" | |
) | |
var ( | |
projectName = os.Getenv("GOOGLE_CLOUD_PROJECT") | |
isProd = (projectName != "") | |
loggingClient *logging.Client | |
pendingError error | |
requestLogger *logging.Logger | |
eventLogger *logging.Logger | |
) | |
const ( | |
loggerKey = "it's a gae logger because they removed the handy one" | |
) | |
func init() { | |
if isProd { | |
ctx := context.Background() | |
loggingClient, pendingError = logging.NewClient(ctx, "projects/"+projectName) | |
res := logging.CommonResource(&mrpb.MonitoredResource{ | |
Type: "gae_app", | |
}) | |
requestLogger = loggingClient.Logger("request", res) | |
eventLogger = loggingClient.Logger("event", res) | |
} | |
} | |
type interceptingResponseWriter struct { | |
w http.ResponseWriter | |
total int | |
} | |
func (irw *interceptingResponseWriter) Header() http.Header { | |
return irw.w.Header() | |
} | |
func (irw *interceptingResponseWriter) Write(b []byte) (int, error) { | |
count, err := irw.w.Write(b) | |
if count > 0 { | |
irw.total += count | |
} | |
return count, err | |
} | |
func (irw *interceptingResponseWriter) WriteHeader(statusCode int) { | |
irw.w.WriteHeader(statusCode) | |
} | |
func internalLog(c context.Context, severity logging.Severity, format string, rest ...interface{}) { | |
requestLogger.Log(logging.Entry{ | |
Severity: severity, | |
Payload: fmt.Sprintf(format, rest...), | |
}) | |
} | |
// Infof logs a message with the "INFO" level. | |
func Infof(c context.Context, format string, rest ...interface{}) { | |
internalLog(c, logging.Info, format, rest...) | |
} | |
// Wrap wraps the given http.HandlerFunc so that logging calls into this package will operate correctly on the active trace. | |
func Wrap(handler http.HandlerFunc) http.HandlerFunc { | |
return func(w http.ResponseWriter, r *http.Request) { | |
traceID := strings.Split(r.Header.Get("X-Cloud-Trace-Context"), "/") | |
ctx := context.WithValue(r.Context(), loggerKey, traceID) | |
irw := &interceptingResponseWriter{w: w} | |
handler(irw, r.WithContext(ctx)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment