Skip to content

Commit

Permalink
Merge e2aa9e6 into dc1269d
Browse files Browse the repository at this point in the history
  • Loading branch information
marwan-at-work committed Feb 11, 2019
2 parents dc1269d + e2aa9e6 commit 44af4d0
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 85 deletions.
104 changes: 104 additions & 0 deletions gcputil/gcputil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Package gcputil provides functions
// that interact with various GCP platforms
// such as getting GAE metadata and registering
// stack driver monitoring
package gcputil

import (
"os"

"contrib.go.opencensus.io/exporter/stackdriver"
"contrib.go.opencensus.io/exporter/stackdriver/monitoredresource"
"go.opencensus.io/stats/view"
"go.opencensus.io/trace"
)

// NewOpenCensusExporter 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
// it and ensure to call Flush on termination.
func NewOpenCensusExporter(projectID string, onErr func(error)) (*stackdriver.Exporter, error) {
svcName, svcVersion := "", ""
if IsGAE() {
_, svcName, svcVersion = GetGAEInfo()
} else if n, v := os.Getenv("SERVICE_NAME"), os.Getenv("SERVICE_VERSION"); n != "" {
svcName, svcVersion = n, v
}
opts := SDExporterOptions(projectID, svcName, svcVersion, onErr)
if opts == nil {
return nil, nil
}
return stackdriver.NewExporter(*opts)
}

// GoogleProjectID returns the GCP Project ID
// that can be used to instantiate various
// GCP clients such as Stack Driver.
func GoogleProjectID() string {
return os.Getenv("GOOGLE_CLOUD_PROJECT")
}

// IsGAE tells you whether your program is running
// within the App Engine platform.
func IsGAE() bool {
return os.Getenv("GAE_DEPLOYMENT_ID") != ""
}

// GetGAEInfo returns the GCP Project ID,
// the service, and the version of the application.
func GetGAEInfo() (projectID, service, version string) {
return GoogleProjectID(),
os.Getenv("GAE_SERVICE"),
os.Getenv("GAE_VERSION")
}

// SDExporterOptions returns Stack Driver Options that you can pass directly
// to the OpenCensus exporter or other libraries.
func SDExporterOptions(projectID, service, version string, onErr func(err error)) *stackdriver.Options {
var mr monitoredresource.Interface
if m := monitoredresource.Autodetect(); m != nil {
mr = m
} else if IsGAE() {
mr = gaeInterface{
typ: "gae_app",
labels: map[string]string{
"project_id": projectID,
},
}
}
if mr == nil {
return nil
}

return &stackdriver.Options{
ProjectID: projectID,
MonitoredResource: mr,
OnError: onErr,
DefaultMonitoringLabels: &stackdriver.Labels{},
DefaultTraceAttributes: map[string]interface{}{
"service": service,
"version": version,
},
}
}

// InitSDExporter will initialize the OpenCensus tracing/metrics exporter
func InitSDExporter(opts stackdriver.Options) error {
exporter, err := stackdriver.NewExporter(opts)
if err != nil {
return err
}
trace.RegisterExporter(exporter)
view.RegisterExporter(exporter)
return nil
}

// implements contrib.go.opencensus.io/exporter/stackdriver/monitoredresource.Interface
type gaeInterface struct {
typ string
labels map[string]string
}

func (g gaeInterface) MonitoredResource() (string, map[string]string) {
return g.typ, g.labels
}
111 changes: 111 additions & 0 deletions ocexporters/ocexporters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package ocexporters

import (
"fmt"
"os"

"contrib.go.opencensus.io/exporter/stackdriver"
"contrib.go.opencensus.io/exporter/stackdriver/monitoredresource"
"go.opencensus.io/exporter/prometheus"
"go.opencensus.io/stats/view"
"go.opencensus.io/trace"
)

// NewOCExporters returns trace/client exporters
// based on the given environment. ProjectID
// is the GCP projectID for stackdriver (or the prometheus namespace) and backend
// specifies whether the backend is StackDriver or Prometheus
func NewOCExporters(projectID, backend string, onErr func(err error)) (trace.Exporter, view.Exporter, error) {
switch backend {
case "stackdriver":
return getSDExporter(projectID, onErr)
case "prometheus":
return getPrometheusExporter(projectID, onErr)
}

return nil, nil, fmt.Errorf("unrecognized backend: %v", backend)
}

func getPrometheusExporter(namespace string, onErr func(error)) (trace.Exporter, view.Exporter, error) {
pe, err := prometheus.NewExporter(prometheus.Options{
Namespace: namespace,
OnError: onErr,
})
return nil, pe, err
}

func getSDExporter(projectID string, onErr func(error)) (trace.Exporter, view.Exporter, error) {
svcName, svcVersion := "", ""
if IsGAE() {
_, svcName, svcVersion = GetGAEInfo()
} else if n, v := os.Getenv("SERVICE_NAME"), os.Getenv("SERVICE_VERSION"); n != "" {
svcName, svcVersion = n, v
}
opts := getSDExporterOptions(projectID, svcName, svcVersion, onErr)
if opts == nil {
return nil, nil, nil
}
exp, err := stackdriver.NewExporter(*opts)
return exp, exp, err
}

// getSDExporterOptions returns Stack Driver Options that you can pass directly
// to the OpenCensus exporter or other libraries.
func getSDExporterOptions(projectID, service, version string, onErr func(err error)) *stackdriver.Options {
var mr monitoredresource.Interface
if m := monitoredresource.Autodetect(); m != nil {
mr = m
} else if IsGAE() {
mr = gaeInterface{
typ: "gae_app",
labels: map[string]string{
"project_id": projectID,
},
}
}
if mr == nil {
return nil
}

return &stackdriver.Options{
ProjectID: projectID,
MonitoredResource: mr,
OnError: onErr,
DefaultMonitoringLabels: &stackdriver.Labels{},
DefaultTraceAttributes: map[string]interface{}{
"service": service,
"version": version,
},
}
}

// implements contrib.go.opencensus.io/exporter/stackdriver/monitoredresource.Interface
type gaeInterface struct {
typ string
labels map[string]string
}

func (g gaeInterface) MonitoredResource() (string, map[string]string) {
return g.typ, g.labels
}

// GoogleProjectID returns the GCP Project ID
// that can be used to instantiate various
// GCP clients such as Stack Driver.
func GoogleProjectID() string {
return os.Getenv("GOOGLE_CLOUD_PROJECT")
}

// IsGAE tells you whether your program is running
// within the App Engine platform.
func IsGAE() bool {
return os.Getenv("GAE_DEPLOYMENT_ID") != ""
}

// GetGAEInfo returns the GCP Project ID,
// the service, and the version of the application.
func GetGAEInfo() (projectID, service, version string) {
return GoogleProjectID(),
os.Getenv("GAE_SERVICE"),
os.Getenv("GAE_VERSION")
}
15 changes: 10 additions & 5 deletions server/kit/kitserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"cloud.google.com/go/errorreporting"
sdpropagation "contrib.go.opencensus.io/exporter/stackdriver/propagation"
"github.com/NYTimes/gizmo/gcputil"
"github.com/go-kit/kit/log"
httptransport "github.com/go-kit/kit/transport/http"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
Expand Down Expand Up @@ -89,16 +90,20 @@ func NewServer(svc Service) *Server {
propr propagation.HTTPFormat
)

projectID := googleProjectID()
projectID := gcputil.GoogleProjectID()
var svcName, svcVersion string
if isGAE() {
_, svcName, svcVersion = getGAEInfo()
if gcputil.IsGAE() {
_, svcName, svcVersion = gcputil.GetGAEInfo()
} else if n, v := os.Getenv("SERVICE_NAME"), os.Getenv("SERVICE_VERSION"); n != "" {
svcName, svcVersion = n, v
}

if opt := sdExporterOptions(projectID, svcName, svcVersion, lg); opt != nil {
err = initSDExporter(*opt)
onErr := func(err error) {
lg.Log("error", err, "message", "tracing client encountered an error")
}

if opt := gcputil.SDExporterOptions(projectID, svcName, svcVersion, onErr); opt != nil {
err = gcputil.InitSDExporter(*opt)
if err != nil {
lg.Log("error", err,
"message", "unable to initiate error tracing exporter")
Expand Down
3 changes: 2 additions & 1 deletion server/kit/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"os"

"github.com/NYTimes/gizmo/gcputil"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/transport/http"
"google.golang.org/grpc/metadata"
Expand All @@ -23,7 +24,7 @@ import (
// 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
func NewLogger(ctx context.Context, logID string) (log.Logger, func() error, error) {
projectID, serviceID, svcVersion := getGAEInfo()
projectID, serviceID, svcVersion := gcputil.GetGAEInfo()
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 {
Expand Down
15 changes: 2 additions & 13 deletions server/kit/sd_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,18 @@ import (
"encoding"
"encoding/json"
"fmt"
"os"
"reflect"
"strings"

"cloud.google.com/go/logging"
"contrib.go.opencensus.io/exporter/stackdriver/monitoredresource"
"github.com/NYTimes/gizmo/gcputil"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"github.com/pkg/errors"
"google.golang.org/genproto/googleapis/api/monitoredres"
)

// project, service, version
func getGAEInfo() (string, string, string) {
return googleProjectID(),
os.Getenv("GAE_SERVICE"),
os.Getenv("GAE_VERSION")
}

func isGAE() bool {
return os.Getenv("GAE_DEPLOYMENT_ID") != ""
}

type sdLogger struct {
project string
monRes *monitoredres.MonitoredResource
Expand All @@ -43,7 +32,7 @@ func newStackdriverLogger(ctx context.Context, logID, projectID, service, versio
"version_id": version,
},
}
if isGAE() {
if gcputil.IsGAE() {
resource.Type = "gae_app"
if logID == "" {
logID = "app_logs"
Expand Down
66 changes: 0 additions & 66 deletions server/kit/stackdriver.go

This file was deleted.

0 comments on commit 44af4d0

Please sign in to comment.