forked from GoogleCloudPlatform/cloud-sql-go-connector
-
Notifications
You must be signed in to change notification settings - Fork 0
/
trace.go
113 lines (102 loc) · 3.56 KB
/
trace.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package trace
import (
"context"
"go.opencensus.io/trace"
"google.golang.org/api/googleapi"
"google.golang.org/genproto/googleapis/rpc/code"
"google.golang.org/grpc/status"
)
// EndSpanFunc is a function that ends a span, reporting an error if necessary.
type EndSpanFunc func(error)
// Attribute annotates a span with additional data.
type Attribute struct {
key string
value interface{}
}
func (a Attribute) traceAttr() trace.Attribute {
// always use a string attribute for now
// if need for additional types arise, this can be expanded.
return trace.StringAttribute(a.key, a.value.(string))
}
// AddInstanceName creates an attribute with the Cloud SQL instance name.
func AddInstanceName(name string) Attribute {
return Attribute{key: "/cloudsql/instance", value: name}
}
// AddDialerID creates an attribute to identify a particular dialer.
func AddDialerID(dialerID string) Attribute {
return Attribute{key: "/cloudsql/dialer_id", value: dialerID}
}
// StartSpan begins a span with the provided name and returns a context and a
// function to end the created span.
func StartSpan(ctx context.Context, name string, attrs ...Attribute) (context.Context, EndSpanFunc) {
var span *trace.Span
ctx, span = trace.StartSpan(ctx, name)
as := make([]trace.Attribute, 0, len(attrs))
for _, a := range attrs {
as = append(as, a.traceAttr())
}
span.AddAttributes(as...)
return ctx, func(err error) {
if err != nil {
span.SetStatus(toStatus(err))
}
span.End()
}
}
// toStatus interrogates an error and converts it to an appropriate
// OpenCensus status.
// Note: this function is borrowed from
// https://github.com/googleapis/google-cloud-go/blob/master/internal/trace/trace.go
func toStatus(err error) trace.Status {
if err2, ok := err.(*googleapi.Error); ok {
return trace.Status{Code: httpStatusCodeToOCCode(err2.Code), Message: err2.Message}
} else if s, ok := status.FromError(err); ok {
return trace.Status{Code: int32(s.Code()), Message: s.Message()}
} else {
return trace.Status{Code: int32(code.Code_UNKNOWN), Message: err.Error()}
}
}
// Reference: https://github.com/googleapis/googleapis/blob/26b634d2724ac5dd30ae0b0cbfb01f07f2e4050e/google/rpc/code.proto
func httpStatusCodeToOCCode(httpStatusCode int) int32 {
switch httpStatusCode {
case 200:
return int32(code.Code_OK)
case 499:
return int32(code.Code_CANCELLED)
case 500:
return int32(code.Code_UNKNOWN) // Could also be Code_INTERNAL, Code_DATA_LOSS
case 400:
return int32(code.Code_INVALID_ARGUMENT) // Could also be Code_OUT_OF_RANGE
case 504:
return int32(code.Code_DEADLINE_EXCEEDED)
case 404:
return int32(code.Code_NOT_FOUND)
case 409:
return int32(code.Code_ALREADY_EXISTS) // Could also be Code_ABORTED
case 403:
return int32(code.Code_PERMISSION_DENIED)
case 401:
return int32(code.Code_UNAUTHENTICATED)
case 429:
return int32(code.Code_RESOURCE_EXHAUSTED)
case 501:
return int32(code.Code_UNIMPLEMENTED)
case 503:
return int32(code.Code_UNAVAILABLE)
default:
return int32(code.Code_UNKNOWN)
}
}