Skip to content

Commit

Permalink
[observe] Adding RegisterAndObserveGCP to use within the SimpleServer…
Browse files Browse the repository at this point in the history
… (or any non-sever/kit poject)) (#217)

* adding RegisterAndObserveGCP func to use within gizmo/server

* adding onError, fixing compile errors

* adding more beef to docs

* putting the GAE check first

* adding observe.SkipObserve?

* hooking into logger too

* preventing a breaking change, NewLogger should still fall back to JSON on error and no skip is set
  • Loading branch information
jprobinson authored Jun 10, 2019
1 parent 2c58cba commit 7e4d613
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
43 changes: 42 additions & 1 deletion observe/observe.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,47 @@ import (
"context"
"os"

"cloud.google.com/go/profiler"
traceapi "cloud.google.com/go/trace/apiv2"
"contrib.go.opencensus.io/exporter/stackdriver"
"contrib.go.opencensus.io/exporter/stackdriver/monitoredresource"
"github.com/pkg/errors"
"go.opencensus.io/stats/view"
"go.opencensus.io/trace"
"golang.org/x/oauth2/google"
"google.golang.org/api/option"
)

// RegisterAndObserveGCP will initiate and register Stackdriver profiling and tracing and
// metrics in environments that pass the tests in the IsGCPEnabled function. All
// exporters will be registered using the information returned by the GetServiceInfo
// function. Tracing and metrics are enabled via OpenCensus exporters. See the OpenCensus
// documentation for instructions for registering additional spans and metrics.
func RegisterAndObserveGCP(onError func(error)) error {
if SkipObserve() {
return nil
}
if !IsGCPEnabled() {
return errors.New("environment is not GCP enabled, no observe tools will be run")
}

projectID, svcName, svcVersion := GetServiceInfo()

exp, err := NewStackdriverExporter(projectID, onError)
if err != nil {
return errors.Wrap(err, "unable to initiate error tracing exporter")
}
trace.RegisterExporter(exp)
view.RegisterExporter(exp)

err = profiler.Start(profiler.Config{
ProjectID: projectID,
Service: svcName,
ServiceVersion: svcVersion,
})
return errors.Wrap(err, "unable to initiate profiling client")
}

// NewStackdriverExporter will return the tracing and metrics through
// the stack driver exporter, if exists in the underlying platform.
// If exporter is registered, it returns the exporter so you can register
Expand Down Expand Up @@ -100,5 +134,12 @@ func getSDOpts(projectID, service, version string, onErr func(err error)) *stack
// IsGCPEnabled returns whether the running application
// is inside GCP or has access to its products.
func IsGCPEnabled() bool {
return monitoredresource.Autodetect() != nil || IsGAE()
return IsGAE() || monitoredresource.Autodetect() != nil
}

// SkipObserve checks if the GIZMO_SKIP_OBSERVE environment variable has been populated.
// This may be used along with local development to cut down on long startup times caused
// by the 'monitoredresource.Autodetect()' call in IsGCPEnabled().
func SkipObserve() bool {
return os.Getenv("GIZMO_SKIP_OBSERVE") != ""
}
2 changes: 1 addition & 1 deletion server/kit/kitserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func NewServer(svc Service) *Server {
lg.Log("error", err, "message", "exporter client encountered an error")
}
ocFlush := func() {}
if observe.IsGCPEnabled() {
if !observe.SkipObserve() && observe.IsGCPEnabled() {
exp, err := observe.NewStackdriverExporter(projectID, onErr)
if err != nil {
lg.Log("error", err,
Expand Down
15 changes: 12 additions & 3 deletions server/kit/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,29 @@ import (
// The logID field is used when the server is deployed in a Stackdriver enabled environment.
// If an empty string is provided, "gae_log" will be used in App Engine and "stdout" elsewhere.
// For more information about to use of logID see the documentation here: https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#FIELDS.log_name
// To speed up start up time in non-GCP enabled environments, this function also checks
// the observe.SkipObserve() function and will use a basic JSON logger writing to
// stdout if set.
func NewLogger(ctx context.Context, logID string) (log.Logger, func() error, error) {
if observe.SkipObserve() {
return newJSONLogger(), func() error { return nil }, nil
}
projectID, serviceID, svcVersion := observe.GetServiceInfo()

lg, cl, err := newStackdriverLogger(ctx, logID, projectID, serviceID, svcVersion)
// if Stackdriver logger was not able to find information about monitored resource it returns nil.
if err != nil {
// running locally or in a non-GAE environment? use JSON
lg := log.NewJSONLogger(log.NewSyncWriter(os.Stdout))
lg := newJSONLogger()
lg.Log("error", err,
"message", "unable to initialize Stackdriver logger. falling back to stdout JSON logging.")
return lg, func() error { return nil }, nil
}
return lg, cl, err
}

func newJSONLogger() log.Logger {
return log.NewJSONLogger(log.NewSyncWriter(os.Stdout))
}

// SetLogger sets log.Logger to the context and returns new context with logger.
func SetLogger(ctx context.Context, logger log.Logger) context.Context {
return context.WithValue(ctx, logKey, logger)
Expand Down

0 comments on commit 7e4d613

Please sign in to comment.