Skip to content
This repository was archived by the owner on Jul 31, 2023. It is now read-only.

Commit fa977d6

Browse files
author
Ramon Nogueira
authored
Application default credentials for Stackdriver (#501)
1 parent 0135db1 commit fa977d6

File tree

3 files changed

+99
-1
lines changed

3 files changed

+99
-1
lines changed

exporter/stackdriver/example_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ func Example() {
3333

3434
// Export to Stackdriver Monitoring.
3535
view.RegisterExporter(exporter)
36+
// Subscribe views to see stats in Stackdriver Monitoring
37+
view.Subscribe(ochttp.ClientLatencyView, ochttp.ClientResponseBytesView)
3638

3739
// Export to Stackdriver Trace.
3840
trace.RegisterExporter(exporter)

exporter/stackdriver/stackdriver.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,15 @@
2222
package stackdriver // import "go.opencensus.io/exporter/stackdriver"
2323

2424
import (
25+
"context"
26+
"errors"
27+
"fmt"
2528
"time"
2629

30+
traceapi "cloud.google.com/go/trace/apiv2"
2731
"go.opencensus.io/stats/view"
2832
"go.opencensus.io/trace"
33+
"golang.org/x/oauth2/google"
2934
"google.golang.org/api/option"
3035
monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres"
3136
)
@@ -34,10 +39,12 @@ import (
3439
type Options struct {
3540
// ProjectID is the identifier of the Stackdriver
3641
// project the user is uploading the stats data to.
42+
// If not set, this will default to your "Application Default Credentials".
43+
// For details see: https://developers.google.com/accounts/docs/application-default-credentials
3744
ProjectID string
3845

3946
// OnError is the hook to be called when there is
40-
// an error occurred when uploading the stats data.
47+
// an error uploading the stats or tracing data.
4148
// If no custom hook is set, errors are logged.
4249
// Optional.
4350
OnError func(err error)
@@ -76,6 +83,16 @@ type Exporter struct {
7683
// NewExporter creates a new Exporter that implements both stats.Exporter and
7784
// trace.Exporter.
7885
func NewExporter(o Options) (*Exporter, error) {
86+
if o.ProjectID == "" {
87+
creds, err := google.FindDefaultCredentials(context.Background(), traceapi.DefaultAuthScopes()...)
88+
if err != nil {
89+
return nil, fmt.Errorf("stackdriver: %v", err)
90+
}
91+
if creds.ProjectID == "" {
92+
return nil, errors.New("stackdriver: no project found with application default credentials")
93+
}
94+
o.ProjectID = creds.ProjectID
95+
}
7996
se, err := newStatsExporter(o)
8097
if err != nil {
8198
return nil, err
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2018, OpenCensus Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package stackdriver
16+
17+
import (
18+
"context"
19+
"io/ioutil"
20+
"net/http"
21+
"net/http/httptest"
22+
"os"
23+
"testing"
24+
"time"
25+
26+
"go.opencensus.io/plugin/ochttp"
27+
"go.opencensus.io/stats/view"
28+
"go.opencensus.io/trace"
29+
"golang.org/x/net/context/ctxhttp"
30+
)
31+
32+
func TestExport(t *testing.T) {
33+
projectID, ok := os.LookupEnv("STACKDRIVER_TEST_PROJECT_ID")
34+
if !ok {
35+
t.Skip("STACKDRIVER_TEST_PROJECT_ID not set")
36+
}
37+
38+
exporter, err := NewExporter(Options{ProjectID: projectID})
39+
if err != nil {
40+
t.Fatal(err)
41+
}
42+
defer exporter.Flush()
43+
44+
trace.RegisterExporter(exporter)
45+
defer trace.UnregisterExporter(exporter)
46+
view.RegisterExporter(exporter)
47+
defer view.UnregisterExporter(exporter)
48+
49+
trace.SetDefaultSampler(trace.AlwaysSample())
50+
51+
span := trace.NewSpan("custom-span", nil, trace.StartOptions{})
52+
time.Sleep(10 * time.Millisecond)
53+
span.End()
54+
55+
// Test HTTP spans
56+
57+
handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
58+
time.Sleep(150 * time.Millisecond) // do work
59+
rw.Write([]byte("Hello, world!"))
60+
})
61+
server := httptest.NewServer(&ochttp.Handler{Handler: handler})
62+
defer server.Close()
63+
64+
ctx := context.Background()
65+
client := &http.Client{
66+
Transport: &ochttp.Transport{},
67+
}
68+
resp, err := ctxhttp.Get(ctx, client, server.URL+"/test/123?abc=xyz")
69+
if err != nil {
70+
t.Fatal(err)
71+
}
72+
body, err := ioutil.ReadAll(resp.Body)
73+
if err != nil {
74+
t.Fatal(err)
75+
}
76+
if want, got := "Hello, world!", string(body); want != got {
77+
t.Fatalf("resp.Body = %q; want %q", want, got)
78+
}
79+
}

0 commit comments

Comments
 (0)