Since Cloud Run is already integrated with Cloud Logging, there is no need to use the Go Client Library.
We run all our gRPC services on Cloud Run and use the following to ensure the logs are properly formatted in Cloud Logging:
package main
import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"os"
)
// initializeLogging sets up the logging configuration for the service.
// Invoke this method in your Init() method.
func initializeLogging() {
// Set logging options for production development
if os.Getenv("ENV") != "DEV" {
// change the level field name to ensure these are parsed correctly in Stackdriver
zerolog.LevelFieldName = "severity"
// UNIX Time is faster and smaller than most timestamps
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
} else {
// Set logging options for local development
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
zerolog.SetGlobalLevel(zerolog.DebugLevel)
}
// Example log
log.Info().Msg("This is how you log at Info level")
}
The logs are then nicely displayed for local development.
If you don't want to use any 3rd party logging libraries, a simple way is to construct your own Entry objects.
package main
import (
"context"
"encoding/json"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"log"
"os"
"strings"
)
// LogSeverity is used to map the logging levels consistent with Google Cloud Logging.
type LogSeverity string
const (
// LogSeverity_DEBUG Debug or trace information.
LogSeverity_DEBUG LogSeverity = "DEBUG"
// LogSeverity_INFO Routine information, such as ongoing status or performance.
LogSeverity_INFO LogSeverity = "INFO"
// LogSeverity_NOTICE Normal but significant events, such as start up, shut down, or
// a configuration change.
LogSeverity_NOTICE LogSeverity = "NOTICE"
// LogSeverity_WARNING Warning events might cause problems.
LogSeverity_WARNING LogSeverity = "WARNING"
// LogSeverity_ERROR Error events are likely to cause problems.
LogSeverity_ERROR LogSeverity = "ERROR"
// LogSeverity_CRITICAL Critical events cause more severe problems or outages.
LogSeverity_CRITICAL LogSeverity = "CRITICAL"
// LogSeverity_ALERT A person must take an action immediately.
LogSeverity_ALERT LogSeverity = "ALERT"
// LogSeverity_EMERGENCY One or more systems are unusable.
LogSeverity_EMERGENCY LogSeverity = "EMERGENCY"
)
// Entry defines a log entry.
// If logs are provided in this format, Google Cloud Logging automatically
// parses the attributes into their LogEntry format as per
// https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry which then automatically
// makes the logs available in Google Cloud Logging and Tracing.
type Entry struct {
Message string `json:"message"`
Severity LogSeverity `json:"severity,omitempty"`
Trace string `json:"logging.googleapis.com/trace,omitempty"`
// To extend details sent to the logs, you may add the attributes here.
//MyAttr1 string `json:"component,omitempty"`
}
// String renders an entry structure to the JSON format expected by Cloud Logging.
func (e Entry) String() string {
// Defaults to INFO level.
if e.Severity == "" {
e.Severity = LogSeverity_INFO
}
// if Development is local then print out all logs
if os.Getenv("ENV") == "LOCAL" {
var prefix string
switch e.Severity {
case LogSeverity_DEBUG:
prefix = colorize("DBG: ", 90)
case LogSeverity_INFO:
prefix = colorize("INFO: ", 32)
case LogSeverity_NOTICE:
prefix = colorize("NOTICE: ", 34)
case LogSeverity_WARNING:
prefix = colorize("WARNING: ", 33)
case LogSeverity_ERROR:
prefix = colorize("ERROR: ", 31)
case LogSeverity_ALERT:
prefix = colorize("ALERT: ", 91)
case LogSeverity_CRITICAL:
prefix = colorize("CRITICAL: ", 41)
case LogSeverity_EMERGENCY:
prefix = colorize("EMERGENCY:", 101)
}
return prefix + " " + e.Message
} else {
out, err := json.Marshal(e)
if err != nil {
log.Printf("json.Marshal: %v", err)
}
return string(out)
}
}
// colorize returns the string s wrapped in ANSI code c
// Codes available at https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
func colorize(s interface{}, c int) string {
return fmt.Sprintf("\x1b[%dm%v\x1b[0m", c, s)
}
Using Google Cloud's Special Fields allows tighter integration with their Cloud Logging product.
logger.StandardLogger
orlogging.Info
instead oflog.Println
, which is working? – Quorum