Skip to content

Commit 1b66bea

Browse files
committed
return partial errors
1 parent 98cbf36 commit 1b66bea

File tree

2 files changed

+74
-71
lines changed

2 files changed

+74
-71
lines changed

detectors/gcp/detector.go

+71-71
Original file line numberDiff line numberDiff line change
@@ -46,90 +46,90 @@ func (d *detector) Detect(ctx context.Context) (*resource.Resource, error) {
4646
if !metadata.OnGCE() {
4747
return nil, nil
4848
}
49-
projectID, err := d.detector.ProjectID()
50-
if err != nil {
51-
return nil, err
52-
}
53-
attributes := []attribute.KeyValue{semconv.CloudProviderGCP, semconv.CloudAccountIDKey.String(projectID)}
49+
b := &resourceBuilder{}
50+
b.attrs = append(b.attrs, semconv.CloudProviderGCP)
51+
b.add(semconv.CloudAccountIDKey, d.detector.ProjectID)
5452

5553
switch d.detector.CloudPlatform() {
5654
case gcp.GKE:
57-
attributes = append(attributes, semconv.CloudPlatformGCPKubernetesEngine)
58-
v, locType, err := d.detector.GKEAvailabilityZoneOrRegion()
59-
if err != nil {
60-
return nil, err
61-
}
62-
switch locType {
63-
case gcp.Zone:
64-
attributes = append(attributes, semconv.CloudAvailabilityZoneKey.String(v))
65-
case gcp.Region:
66-
attributes = append(attributes, semconv.CloudRegionKey.String(v))
67-
default:
68-
return nil, fmt.Errorf("location must be zone or region. Got %v", locType)
69-
}
70-
return detectWithFuncs(attributes, map[attribute.Key]detectionFunc{
71-
semconv.K8SClusterNameKey: d.detector.GKEClusterName,
72-
semconv.HostIDKey: d.detector.GKEHostID,
73-
semconv.HostNameKey: d.detector.GKEHostName,
74-
})
55+
b.attrs = append(b.attrs, semconv.CloudPlatformGCPKubernetesEngine)
56+
b.addZoneOrRegion(d.detector.GKEAvailabilityZoneOrRegion)
57+
b.add(semconv.K8SClusterNameKey, d.detector.GKEClusterName)
58+
b.add(semconv.HostIDKey, d.detector.GKEHostID)
59+
b.add(semconv.HostNameKey, d.detector.GKEHostName)
7560
case gcp.CloudRun:
76-
attributes = append(attributes, semconv.CloudPlatformGCPCloudRun)
77-
return detectWithFuncs(attributes, map[attribute.Key]detectionFunc{
78-
semconv.FaaSNameKey: d.detector.FaaSName,
79-
semconv.FaaSVersionKey: d.detector.FaaSVersion,
80-
semconv.FaaSIDKey: d.detector.FaaSID,
81-
semconv.CloudRegionKey: d.detector.FaaSCloudRegion,
82-
})
61+
b.attrs = append(b.attrs, semconv.CloudPlatformGCPCloudRun)
62+
b.add(semconv.FaaSNameKey, d.detector.FaaSName)
63+
b.add(semconv.FaaSVersionKey, d.detector.FaaSVersion)
64+
b.add(semconv.FaaSIDKey, d.detector.FaaSID)
65+
b.add(semconv.CloudRegionKey, d.detector.FaaSCloudRegion)
8366
case gcp.CloudFunctions:
84-
attributes = append(attributes, semconv.CloudPlatformGCPCloudFunctions)
85-
return detectWithFuncs(attributes, map[attribute.Key]detectionFunc{
86-
semconv.FaaSNameKey: d.detector.FaaSName,
87-
semconv.FaaSVersionKey: d.detector.FaaSVersion,
88-
semconv.FaaSIDKey: d.detector.FaaSID,
89-
semconv.CloudRegionKey: d.detector.FaaSCloudRegion,
90-
})
67+
b.attrs = append(b.attrs, semconv.CloudPlatformGCPCloudFunctions)
68+
b.add(semconv.FaaSNameKey, d.detector.FaaSName)
69+
b.add(semconv.FaaSVersionKey, d.detector.FaaSVersion)
70+
b.add(semconv.FaaSIDKey, d.detector.FaaSID)
71+
b.add(semconv.CloudRegionKey, d.detector.FaaSCloudRegion)
9172
case gcp.AppEngine:
92-
attributes = append(attributes, semconv.CloudPlatformGCPAppEngine)
93-
zone, region, err := d.detector.AppEngineAvailabilityZoneAndRegion()
94-
if err != nil {
95-
return nil, err
96-
}
97-
attributes = append(attributes, semconv.CloudAvailabilityZoneKey.String(zone))
98-
attributes = append(attributes, semconv.CloudRegionKey.String(region))
99-
return detectWithFuncs(attributes, map[attribute.Key]detectionFunc{
100-
semconv.FaaSNameKey: d.detector.AppEngineServiceName,
101-
semconv.FaaSVersionKey: d.detector.AppEngineServiceVersion,
102-
semconv.FaaSIDKey: d.detector.AppEngineServiceInstance,
103-
})
73+
b.attrs = append(b.attrs, semconv.CloudPlatformGCPAppEngine)
74+
b.addZoneAndRegion(d.detector.AppEngineAvailabilityZoneAndRegion)
75+
b.add(semconv.FaaSNameKey, d.detector.AppEngineServiceName)
76+
b.add(semconv.FaaSVersionKey, d.detector.AppEngineServiceVersion)
77+
b.add(semconv.FaaSIDKey, d.detector.AppEngineServiceInstance)
10478
case gcp.GCE:
105-
attributes = append(attributes, semconv.CloudPlatformGCPComputeEngine)
106-
zone, region, err := d.detector.GCEAvailabilityZoneAndRegion()
107-
if err != nil {
108-
return nil, err
109-
}
110-
attributes = append(attributes, semconv.CloudAvailabilityZoneKey.String(zone))
111-
attributes = append(attributes, semconv.CloudRegionKey.String(region))
112-
return detectWithFuncs(attributes, map[attribute.Key]detectionFunc{
113-
semconv.HostTypeKey: d.detector.GCEHostType,
114-
semconv.HostIDKey: d.detector.GCEHostID,
115-
semconv.HostNameKey: d.detector.GCEHostName,
116-
})
79+
b.attrs = append(b.attrs, semconv.CloudPlatformGCPComputeEngine)
80+
b.addZoneAndRegion(d.detector.GCEAvailabilityZoneAndRegion)
81+
b.add(semconv.HostTypeKey, d.detector.GCEHostType)
82+
b.add(semconv.HostIDKey, d.detector.GCEHostID)
83+
b.add(semconv.HostNameKey, d.detector.GCEHostName)
11784
default:
11885
// We don't support this platform yet, so just return with what we have
119-
return resource.NewWithAttributes(semconv.SchemaURL, attributes...), nil
12086
}
87+
return b.build()
12188
}
12289

123-
type detectionFunc func() (string, error)
90+
// resourceBuilder simplifies
91+
type resourceBuilder struct {
92+
errs []error
93+
attrs []attribute.KeyValue
94+
}
12495

125-
// detectWithFuncs is a helper to reduce the amount of error handling code
126-
func detectWithFuncs(attributes []attribute.KeyValue, funcs map[attribute.Key]detectionFunc) (*resource.Resource, error) {
127-
for key, detect := range funcs {
128-
v, err := detect()
129-
if err != nil {
130-
return nil, err
96+
func (r *resourceBuilder) add(key attribute.Key, detect func() (string, error)) {
97+
if v, err := detect(); err == nil {
98+
r.attrs = append(r.attrs, key.String(v))
99+
} else {
100+
r.errs = append(r.errs, err)
101+
}
102+
}
103+
104+
// zoneAndRegion functions are expected to return zone, region, err
105+
func (r *resourceBuilder) addZoneAndRegion(detect func() (string, string, error)) {
106+
if zone, region, err := detect(); err == nil {
107+
r.attrs = append(r.attrs, semconv.CloudAvailabilityZoneKey.String(zone))
108+
r.attrs = append(r.attrs, semconv.CloudRegionKey.String(region))
109+
} else {
110+
r.errs = append(r.errs, err)
111+
}
112+
}
113+
114+
func (r *resourceBuilder) addZoneOrRegion(detect func() (string, gcp.LocationType, error)) {
115+
if v, locType, err := detect(); err == nil {
116+
switch locType {
117+
case gcp.Zone:
118+
r.attrs = append(r.attrs, semconv.CloudAvailabilityZoneKey.String(v))
119+
case gcp.Region:
120+
r.attrs = append(r.attrs, semconv.CloudRegionKey.String(v))
121+
default:
122+
r.errs = append(r.errs, fmt.Errorf("location must be zone or region. Got %v", locType))
131123
}
132-
attributes = append(attributes, key.String(v))
124+
} else {
125+
r.errs = append(r.errs, err)
126+
}
127+
}
128+
129+
func (r *resourceBuilder) build() (*resource.Resource, error) {
130+
var err error
131+
if len(r.errs) > 0 {
132+
err = fmt.Errorf("%w: %s", resource.ErrPartialResource, r.errs)
133133
}
134-
return resource.NewWithAttributes(semconv.SchemaURL, attributes...), nil
134+
return resource.NewWithAttributes(semconv.SchemaURL, r.attrs...), err
135135
}

detectors/gcp/detector_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ func TestDetect(t *testing.T) {
179179
err: fmt.Errorf("Failed to get metadata"),
180180
}},
181181
expectErr: true,
182+
expectedResource: resource.NewWithAttributes(semconv.SchemaURL,
183+
semconv.CloudProviderGCP,
184+
),
182185
},
183186
} {
184187
t.Run(tc.desc, func(t *testing.T) {

0 commit comments

Comments
 (0)