Skip to content

Commit

Permalink
Added support for custom tags and deleted old implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
zasweq committed Aug 5, 2022
1 parent ce98283 commit a930d0b
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 217 deletions.
15 changes: 7 additions & 8 deletions gcp/observability/exporting.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import (
"context"
"encoding/json"
"fmt"
"os"

gcplogging "cloud.google.com/go/logging"
configpb "google.golang.org/grpc/gcp/observability/internal/config"
grpclogrecordpb "google.golang.org/grpc/gcp/observability/internal/logging"
"google.golang.org/protobuf/encoding/protojson"
)
Expand All @@ -45,20 +45,19 @@ type cloudLoggingExporter struct {
logger *gcplogging.Logger
}

func newCloudLoggingExporter(ctx context.Context, projectID string) (*cloudLoggingExporter, error) {
c, err := gcplogging.NewClient(ctx, fmt.Sprintf("projects/%v", projectID))
func newCloudLoggingExporter(ctx context.Context, config *configpb.ObservabilityConfig) (*cloudLoggingExporter, error) {
c, err := gcplogging.NewClient(ctx, fmt.Sprintf("projects/%v", config.DestinationProjectId))
if err != nil {
return nil, fmt.Errorf("failed to create cloudLoggingExporter: %v", err)
}
defer logger.Infof("Successfully created cloudLoggingExporter")
customTags := getCustomTags(os.Environ())
if len(customTags) != 0 {
logger.Infof("Adding custom tags: %+v", customTags)
if len(config.CustomTags) != 0 {
logger.Infof("Adding custom tags: %+v", config.CustomTags)
}
return &cloudLoggingExporter{
projectID: projectID,
projectID: config.DestinationProjectId,
client: c,
logger: c.Logger("microservices.googleapis.com/observability/grpc", gcplogging.CommonLabels(customTags)),
logger: c.Logger("microservices.googleapis.com/observability/grpc", gcplogging.CommonLabels(config.CustomTags)),
}, nil
}

Expand Down
193 changes: 104 additions & 89 deletions gcp/observability/internal/config/config.pb.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions gcp/observability/internal/config/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,7 @@ message ObservabilityConfig {
// For example, 0.05 means there is a 5% chance for a RPC to be traced, 1.0
// means trace every call, 0 means don’t start new traces.
double global_trace_sampling_rate = 6;

// A list of custom tags that will be attached to every log entry.
map<string, string> custom_tags = 7;
}
2 changes: 1 addition & 1 deletion gcp/observability/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ func (l *binaryLogger) Start(ctx context.Context, config *configpb.Observability
if config.GetDestinationProjectId() == "" {
return fmt.Errorf("failed to enable CloudLogging: empty destination_project_id")
}
exporter, err := newCloudLoggingExporter(ctx, config.DestinationProjectId)
exporter, err := newCloudLoggingExporter(ctx, config)
if err != nil {
return fmt.Errorf("unable to create CloudLogging exporter: %v", err)
}
Expand Down
67 changes: 61 additions & 6 deletions gcp/observability/observability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
"google.golang.org/grpc/credentials/insecure"
configpb "google.golang.org/grpc/gcp/observability/internal/config"
grpclogrecordpb "google.golang.org/grpc/gcp/observability/internal/logging"
"google.golang.org/grpc/internal"
iblog "google.golang.org/grpc/internal/binarylog"
"google.golang.org/grpc/internal/grpctest"
"google.golang.org/grpc/internal/leakcheck"
Expand Down Expand Up @@ -687,7 +688,7 @@ func (s) TestRefuseStartWithInvalidPatterns(t *testing.T) {
// place in the temporary portion of the file system dependent on system. It
// also sets the environment variable GRPC_CONFIG_OBSERVABILITY_JSON to point to
// this created config.
func createTmpConfigInFileSystem(rawJSON string) (*os.File, error) {
func createTmpConfigInFileSystem(rawJSON string) (func(), error) {
configJSONFile, err := ioutil.TempFile(os.TempDir(), "configJSON-")
if err != nil {
return nil, fmt.Errorf("cannot create file %v: %v", configJSONFile.Name(), err)
Expand All @@ -697,7 +698,10 @@ func createTmpConfigInFileSystem(rawJSON string) (*os.File, error) {
return nil, fmt.Errorf("cannot write marshalled JSON: %v", err)
}
os.Setenv(envObservabilityConfigJSON, configJSONFile.Name())
return configJSONFile, nil
return func() {
configJSONFile.Close()
os.Setenv(envObservabilityConfigJSON, "")
}, nil
}

// TestJSONEnvVarSet tests a valid observability configuration specified by the
Expand All @@ -708,8 +712,9 @@ func (s) TestJSONEnvVarSet(t *testing.T) {
"destinationProjectId": "fake",
"logFilters":[{"pattern":"*","headerBytes":1073741824,"messageBytes":1073741824}]
}`
configJSONFile, err := createTmpConfigInFileSystem(configJSON)
defer configJSONFile.Close()
cleanup, err := createTmpConfigInFileSystem(configJSON)
defer cleanup()

if err != nil {
t.Fatalf("failed to create config in file system: %v", err)
}
Expand All @@ -731,8 +736,8 @@ func (s) TestBothConfigEnvVarsSet(t *testing.T) {
"destinationProjectId":"fake",
"logFilters":[{"pattern":":-)"}, {"pattern":"*"}]
}`
configJSONFile, err := createTmpConfigInFileSystem(configJSON)
defer configJSONFile.Close()
cleanup, err := createTmpConfigInFileSystem(configJSON)
defer cleanup()
if err != nil {
t.Fatalf("failed to create config in file system: %v", err)
}
Expand Down Expand Up @@ -764,6 +769,7 @@ func (s) TestBothConfigEnvVarsSet(t *testing.T) {
// a file (or valid configuration).
func (s) TestErrInFileSystemEnvVar(t *testing.T) {
os.Setenv(envObservabilityConfigJSON, "/this-file/does-not-exist")
defer os.Setenv(envObservabilityConfigJSON, "")
if err := Start(context.Background()); err == nil {
t.Fatalf("Invalid file system path not triggering error")
}
Expand Down Expand Up @@ -835,3 +841,52 @@ func (s) TestOpenCensusIntegration(t *testing.T) {
t.Fatalf("Invalid OpenCensus export data: %v", errs)
}
}

// TestCustomTagsTracingMetrics verifies that the custom tags defined in our
// observability configuration and set to two hardcoded values are passed to the
// function to create an exporter.
func (s) TestCustomTagsTracingMetrics(t *testing.T) {
defer func(ne func(config *configpb.ObservabilityConfig) (tracingMetricsExporter, error)) {
newExporter = ne
}(newExporter)
fe := &fakeOpenCensusExporter{SeenViews: make(map[string]string), t: t}
newExporter = func(config *configpb.ObservabilityConfig) (tracingMetricsExporter, error) {
ct := config.GetCustomTags()
if len(ct) < 1 {
t.Fatalf("less than 2 custom tags sent in")
}
if val, ok := ct["customtag1"]; !ok || val != "wow" {
t.Fatalf("incorrect custom tag: got %v, want %v", val, "wow")
}
if val, ok := ct["customtag2"]; !ok || val != "nice" {
t.Fatalf("incorrect custom tag: got %v, want %v", val, "nice")
}
return fe, nil
}

// This configuration present in file system and it's defined custom tags should make it
// to the created exporter.
configJSON := `{
"destinationProjectId": "fake",
"enableCloudTrace": true,
"enableCloudMonitoring": true,
"globalTraceSamplingRate": 1.0,
"customTags":{"customtag1":"wow","customtag2":"nice"}
}`
cleanup, err := createTmpConfigInFileSystem(configJSON)
defer cleanup()

// To clear globally registered tracing and metrics exporters.
defer func() {
internal.ClearExtraDialOptions()
internal.ClearExtraServerOptions()
}()

ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
defer cancel()
err = Start(ctx)
defer End()
if err != nil {
t.Fatalf("Start() failed with err: %v", err)
}
}
24 changes: 21 additions & 3 deletions gcp/observability/opencensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,28 @@ var (
defaultMetricsReportingInterval = time.Second * 30
)

func convertTagsToMonitoringLabels(tags map[string]string) *stackdriver.Labels {
labels := &stackdriver.Labels{}
for k, v := range tags {
labels.Set(k, v, "")
}
return labels
}

func convertTagsToTraceAttributes(tags map[string]string) map[string]interface{} {
ta := make(map[string]interface{}, len(tags))
for k, v := range tags {
ta[k] = v
}
return ta
}

type tracingMetricsExporter interface {
trace.Exporter
view.Exporter
}

// globals to stub out in tests
// global to stub out in tests
var newExporter = newStackdriverExporter

func newStackdriverExporter(config *configpb.ObservabilityConfig) (tracingMetricsExporter, error) {
Expand All @@ -52,8 +68,10 @@ func newStackdriverExporter(config *configpb.ObservabilityConfig) (tracingMetric
logger.Infof("Detected MonitoredResource:: %+v", mr)
var err error
exporter, err := stackdriver.NewExporter(stackdriver.Options{
ProjectID: config.DestinationProjectId,
MonitoredResource: mr,
ProjectID: config.DestinationProjectId,
MonitoredResource: mr,
DefaultMonitoringLabels: convertTagsToMonitoringLabels(config.CustomTags),
DefaultTraceAttributes: convertTagsToTraceAttributes(config.CustomTags),
})
if err != nil {
return nil, fmt.Errorf("failed to create Stackdriver exporter: %v", err)
Expand Down
46 changes: 0 additions & 46 deletions gcp/observability/tags.go

This file was deleted.

64 changes: 0 additions & 64 deletions gcp/observability/tags_test.go

This file was deleted.

0 comments on commit a930d0b

Please sign in to comment.