mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-25 01:00:16 -05:00
[OpenTelemetry] Add traces to init command (#2665)
Signed-off-by: James Humphries <james@james-humphries.co.uk> Signed-off-by: Christian Mesh <christianmesh1@gmail.com> Co-authored-by: Christian Mesh <christianmesh1@gmail.com>
This commit is contained in:
@@ -24,10 +24,16 @@ import (
|
||||
"github.com/hashicorp/go-retryablehttp"
|
||||
svchost "github.com/hashicorp/terraform-svchost"
|
||||
svcauth "github.com/hashicorp/terraform-svchost/auth"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/logging"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
"github.com/opentofu/opentofu/version"
|
||||
)
|
||||
|
||||
@@ -82,6 +88,8 @@ func newRegistryClient(baseURL *url.URL, creds svcauth.HostCredentials) *registr
|
||||
retryableClient.RequestLogHook = requestLogHook
|
||||
retryableClient.ErrorHandler = maxRetryErrorHandler
|
||||
|
||||
retryableClient.HTTPClient.Transport = otelhttp.NewTransport(retryableClient.HTTPClient.Transport)
|
||||
|
||||
retryableClient.Logger = log.New(logging.LogOutput(), "", log.Flags())
|
||||
|
||||
return ®istryClient{
|
||||
@@ -99,6 +107,13 @@ func newRegistryClient(baseURL *url.URL, creds svcauth.HostCredentials) *registr
|
||||
// ErrUnauthorized if the registry responds with 401 or 403 status codes, or
|
||||
// ErrQueryFailed for any other protocol or operational problem.
|
||||
func (c *registryClient) ProviderVersions(ctx context.Context, addr addrs.Provider) (map[string][]string, []string, error) {
|
||||
ctx, span := tracing.Tracer().Start(ctx,
|
||||
"List Versions",
|
||||
trace.WithAttributes(
|
||||
otelAttr.String(traceattrs.ProviderAddress, addr.String()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
endpointPath, err := url.Parse(path.Join(addr.Namespace, addr.Type, "versions"))
|
||||
if err != nil {
|
||||
// Should never happen because we're constructing this from
|
||||
@@ -106,6 +121,7 @@ func (c *registryClient) ProviderVersions(ctx context.Context, addr addrs.Provid
|
||||
return nil, nil, err
|
||||
}
|
||||
endpointURL := c.baseURL.ResolveReference(endpointPath)
|
||||
span.SetAttributes(semconv.URLFull(endpointURL.String()))
|
||||
req, err := retryablehttp.NewRequest("GET", endpointURL.String(), nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -115,7 +131,9 @@ func (c *registryClient) ProviderVersions(ctx context.Context, addr addrs.Provid
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, c.errQueryFailed(addr, err)
|
||||
errResult := c.errQueryFailed(addr, err)
|
||||
tracing.SetSpanError(span, errResult)
|
||||
return nil, nil, errResult
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
@@ -123,13 +141,19 @@ func (c *registryClient) ProviderVersions(ctx context.Context, addr addrs.Provid
|
||||
case http.StatusOK:
|
||||
// Great!
|
||||
case http.StatusNotFound:
|
||||
return nil, nil, ErrRegistryProviderNotKnown{
|
||||
err := ErrRegistryProviderNotKnown{
|
||||
Provider: addr,
|
||||
}
|
||||
tracing.SetSpanError(span, err)
|
||||
return nil, nil, err
|
||||
case http.StatusUnauthorized, http.StatusForbidden:
|
||||
return nil, nil, c.errUnauthorized(addr.Hostname)
|
||||
err := c.errUnauthorized(addr.Hostname)
|
||||
tracing.SetSpanError(span, err)
|
||||
return nil, nil, err
|
||||
default:
|
||||
return nil, nil, c.errQueryFailed(addr, errors.New(resp.Status))
|
||||
err := c.errQueryFailed(addr, errors.New(resp.Status))
|
||||
tracing.SetSpanError(span, err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// We ignore the platforms portion of the response body, because the
|
||||
@@ -146,7 +170,9 @@ func (c *registryClient) ProviderVersions(ctx context.Context, addr addrs.Provid
|
||||
|
||||
dec := json.NewDecoder(resp.Body)
|
||||
if err := dec.Decode(&body); err != nil {
|
||||
return nil, nil, c.errQueryFailed(addr, err)
|
||||
errResult := c.errQueryFailed(addr, err)
|
||||
tracing.SetSpanError(span, errResult)
|
||||
return nil, nil, errResult
|
||||
}
|
||||
|
||||
if len(body.Versions) == 0 {
|
||||
@@ -181,12 +207,23 @@ func (c *registryClient) PackageMeta(ctx context.Context, provider addrs.Provide
|
||||
target.OS,
|
||||
target.Arch,
|
||||
))
|
||||
ctx, span := tracing.Tracer().Start(ctx,
|
||||
"Fetch metadata",
|
||||
trace.WithAttributes(
|
||||
otelAttr.String(traceattrs.ProviderAddress, provider.String()),
|
||||
otelAttr.String(traceattrs.ProviderVersion, version.String()),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
if err != nil {
|
||||
// Should never happen because we're constructing this from
|
||||
// already-validated components.
|
||||
return PackageMeta{}, err
|
||||
}
|
||||
endpointURL := c.baseURL.ResolveReference(endpointPath)
|
||||
span.SetAttributes(
|
||||
semconv.URLFull(endpointURL.String()),
|
||||
)
|
||||
|
||||
req, err := retryablehttp.NewRequest("GET", endpointURL.String(), nil)
|
||||
if err != nil {
|
||||
@@ -197,6 +234,7 @@ func (c *registryClient) PackageMeta(ctx context.Context, provider addrs.Provide
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
tracing.SetSpanError(span, err)
|
||||
return PackageMeta{}, c.errQueryFailed(provider, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
@@ -328,7 +366,7 @@ func (c *registryClient) PackageMeta(ctx context.Context, provider addrs.Provide
|
||||
if shasumsURL.Scheme != "http" && shasumsURL.Scheme != "https" {
|
||||
return PackageMeta{}, fmt.Errorf("registry response includes invalid SHASUMS URL: must use http or https scheme")
|
||||
}
|
||||
document, err := c.getFile(shasumsURL)
|
||||
document, err := c.getFile(ctx, shasumsURL)
|
||||
if err != nil {
|
||||
return PackageMeta{}, c.errQueryFailed(
|
||||
provider,
|
||||
@@ -343,7 +381,7 @@ func (c *registryClient) PackageMeta(ctx context.Context, provider addrs.Provide
|
||||
if signatureURL.Scheme != "http" && signatureURL.Scheme != "https" {
|
||||
return PackageMeta{}, fmt.Errorf("registry response includes invalid SHASUMS signature URL: must use http or https scheme")
|
||||
}
|
||||
signature, err := c.getFile(signatureURL)
|
||||
signature, err := c.getFile(ctx, signatureURL)
|
||||
if err != nil {
|
||||
return PackageMeta{}, c.errQueryFailed(
|
||||
provider,
|
||||
@@ -434,8 +472,14 @@ func (c *registryClient) errUnauthorized(hostname svchost.Hostname) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *registryClient) getFile(url *url.URL) ([]byte, error) {
|
||||
resp, err := c.httpClient.Get(url.String())
|
||||
func (c *registryClient) getFile(ctx context.Context, url *url.URL) ([]byte, error) {
|
||||
req, err := retryablehttp.NewRequest("GET", url.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user