mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 09:48:32 -05:00
tracing: Centralize our OpenTelemetry package imports
OpenTelemetry has various Go packages split across several Go modules that often need to be carefully upgraded together. And in particular, we are using the "semconv" package in conjunction with the OpenTelemetry SDK's "resource" package in a way that requires that they both agree on which version of the OpenTelemetry Semantic Conventions are being followed. To help avoid "dependency hell" situations when upgrading, this centralizes all of our direct calls into the OpenTelemetry SDK and tracing API into packages under internal/tracing, by exposing a few thin wrapper functions that other packages can use to access the same functionality indirectly. We only use a relatively small subset of the OpenTelemetry library surface area, so we don't need too many of these reexports and they should not represent a significant additional maintenance burden. For the semconv and resource interaction in particular this also factors that out into a separate helper function with a unit test, so we should notice quickly whenever they become misaligned. This complements the end-to-end test previously added in opentofu/opentofu#3447 to give us faster feedback about this particular problem, while the end-to-end test has the broader scope of making sure there aren't any errors at all when initializing OpenTelemetry tracing. Finally, this also replaces the constants we previously had in package traceaddrs with functions that return attribute.KeyValue values directly. This matches the API style used by the OpenTelemetry semconv packages, and makes the calls to these helpers from elsewhere in the system a little more concise. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This commit is contained in:
@@ -15,8 +15,6 @@ import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
orasRemote "oras.land/oras-go/v2/registry/remote"
|
||||
orasAuth "oras.land/oras-go/v2/registry/remote/auth"
|
||||
orasCreds "oras.land/oras-go/v2/registry/remote/credentials"
|
||||
@@ -27,6 +25,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/getproviders"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// ociCredsPolicyBuilder is the type of a callback function that the [providerSource]
|
||||
@@ -77,9 +76,9 @@ func getOCIRepositoryStore(ctx context.Context, registryDomain, repositoryName s
|
||||
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Authenticate to OCI Registry",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String("opentofu.oci.registry.domain", registryDomain),
|
||||
otelAttr.String("opentofu.oci.repository.name", repositoryName),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("opentofu.oci.registry.domain", registryDomain),
|
||||
traceattrs.String("opentofu.oci.repository.name", repositoryName),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -189,9 +188,9 @@ func (o ociCredentialsLookupEnv) QueryDockerCredentialHelper(ctx context.Context
|
||||
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Query Docker-style credential helper",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String("opentofu.oci.docker_credential_helper.name", helperName),
|
||||
otelAttr.String("opentofu.oci.registry.url", serverURL),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("opentofu.oci.docker_credential_helper.name", helperName),
|
||||
traceattrs.String("opentofu.oci.registry.url", serverURL),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -203,14 +202,14 @@ func (o ociCredentialsLookupEnv) QueryDockerCredentialHelper(ctx context.Context
|
||||
// than "Docker-style Credential Helper", but it's the
|
||||
// same protocol nonetheless.
|
||||
|
||||
var executeSpan otelTrace.Span // ORAS tracing API can't directly propagate span from Start to Done
|
||||
var executeSpan tracing.Span // ORAS tracing API can't directly propagate span from Start to Done
|
||||
ctx = orasCredsTrace.WithExecutableTrace(ctx, &orasCredsTrace.ExecutableTrace{
|
||||
ExecuteStart: func(executableName, action string) {
|
||||
_, executeSpan = tracing.Tracer().Start(
|
||||
ctx, "Execute helper program",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String("opentofu.oci.docker_credential_helper.executable", helperName),
|
||||
otelAttr.String("opentofu.oci.registry.url", serverURL),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("opentofu.oci.docker_credential_helper.executable", helperName),
|
||||
traceattrs.String("opentofu.oci.registry.url", serverURL),
|
||||
),
|
||||
)
|
||||
log.Printf("[DEBUG] Executing docker-style credentials helper %q for %s", helperName, serverURL)
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
This document describes how to use and implement tracing in OpenTofu Core using OpenTelemetry.
|
||||
|
||||
> [!NOTE]
|
||||
> For background on the design decisions and motivation behind OpenTofu's tracing implementation, see the [OpenTelemetry Tracing RFC](https://github.com/opentofu/opentofu/blob/main/rfc/20250129-Tracing-For-Extra-Context.md).
|
||||
There's background information on OpenTofu's tracing implementation in [the OpenTelemetry Tracing RFC](https://github.com/opentofu/opentofu/blob/main/rfc/20250129-Tracing-For-Extra-Context.md)
|
||||
|
||||
> [!NOTE]
|
||||
> If you are upgrading any dependent libraries which pull in a new OTEL version, you *MUST* update the semconv version in tracing/init.go to the latest version.
|
||||
> Failing to do this will result in an error "Could not initialize telemetry: failed to create resource: error detecting resource: conflicting Schema URL".
|
||||
> This sets the *maximum* supported schema version in our OTEL context. Semconv is backwards compatible with older versions, but the newest must be specified.
|
||||
> [!WARNING]
|
||||
> If you change which version of the `go.opentelemetry.io/otel/sdk` we have selected in our `go.mod`, you **must** make sure that `internal/tracing/traceattrs/semconv.go` imports the same subpackage of `go.opentelemetry.io/otel/semconv/*` that is used by the selected version of `go.opentelemetry.io/otel/sdk`.
|
||||
>
|
||||
> This is important because our tracing setup uses a blend of directly-constructed `semconv` attributes and attributes chosen indirectly through the `resource` package, and they must all be using the same version of the semantic conventions schema or there will be a "conflicting Schema URL" error at runtime.
|
||||
>
|
||||
> (Problems of this sort should be detected both by a unit test in `internal/tracing/traceattrs` and an end-to-end test that executes OpenTofu with tracing enabled.)
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -61,7 +62,7 @@ Then configure OpenTofu as shown above and access the Jaeger UI at http://localh
|
||||
## Adding Tracing to OpenTofu Code
|
||||
|
||||
> [!NOTE]
|
||||
> **For Contributors**: When adding tracing to OpenTofu, remember that the primary audience is **end users** who need to understand performance, not developers. Add spans sparingly to avoid polluting traces with too much detail.
|
||||
> **For Contributors**: When adding tracing to OpenTofu, remember that the primary audience is **end users** who need to understand performance, not OpenTofu developers. Add spans sparingly to avoid polluting traces with too much detail.
|
||||
|
||||
### Basic Span Creation
|
||||
|
||||
@@ -69,19 +70,25 @@ Then configure OpenTofu as shown above and access the Jaeger UI at http://localh
|
||||
import (
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute" // Note the alias
|
||||
)
|
||||
|
||||
func SomeFunction(ctx context.Context) error {
|
||||
// Create a new span
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Human readable operation name")
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Human readable operation name",
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("opentofu.some_attribute", "value")
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
// Add attributes to provide context
|
||||
span.SetAttributes(otelAttr.String("opentofu.some.attribute", "value"))
|
||||
// Optionally add additional attributes after the span is created, if
|
||||
// they only need to appear in certain cases.
|
||||
span.SetAttributes(traceattrs.String("opentofu.some_other_attribute", "value"))
|
||||
|
||||
// Using predefined attributes from traceattrs package
|
||||
span.SetAttributes(otelAttr.String(traceattrs.ProviderAddress, "hashicorp/aws"))
|
||||
// Use the more specific attribute-construction helpers from package
|
||||
// traceattrs where they are relevant, to ensure we follow consistent
|
||||
// semantic conventions for cross-cutting concerns.
|
||||
span.SetAttributes(traceattrs.OpenTofuProviderAddress("hashicorp/aws"))
|
||||
|
||||
// Your function logic here...
|
||||
|
||||
@@ -95,9 +102,14 @@ func SomeFunction(ctx context.Context) error {
|
||||
}
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> We should use the `otelAttr` alias for OpenTelemetry's attribute package to clearly distinguish it from OpenTofu's trace attribute constants in the `traceattrs` package.
|
||||
> This convention makes the code more readable and prevents import conflicts.
|
||||
OpenTelemetry has many different packages spread across a variety of different Go modules, and those different modules often need to be upgraded together to ensure consistent behavior and avoid errors at runtime.
|
||||
|
||||
Therefore we prefer to directly import `go.opentelemetry.io/otel/*` packages only from our packages under `internal/tracing`, and then reexport certain functions from our own packages so that we can manage all of the OpenTelemetry dependencies in a centralized place to minimize "dependency hell" problems when upgrading. Packages under `go.opentelemetry.io/contrib/instrumentation/*` are an exception because they tend to be more tightly-coupled to whatever they are instrumenting than to the other OpenTelemetry packages, and so it's better to import those from the same file that's importing whatever other package the instrumentation is being applied to.
|
||||
|
||||
> [!WARNING]
|
||||
> Don't import `go.opentelemetry.io/otel/semconv/*` packages from anywhere except `internal/tracing/traceattrs/semconv.go`!
|
||||
>
|
||||
> If you want to use standard OpenTelemetry semantic conventions from other packages, use them indirectly through reexports in `package traceattrs` instead, so we can make sure there's only one file in OpenTofu deciding which version of semconv we are currently depending on.
|
||||
|
||||
### Tracing Conventions
|
||||
|
||||
@@ -110,17 +122,10 @@ func SomeFunction(ctx context.Context) error {
|
||||
|
||||
#### Attributes
|
||||
|
||||
- Prefer standard [OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/semconv/) where applicable
|
||||
- Follow the [OpenTelemetry attribute naming convention](https://opentelemetry.io/docs/specs/semconv/general/naming/)
|
||||
- Cross-cutting attributes are defined in `internal/tracing/traceattrs`
|
||||
|
||||
```go
|
||||
// Good attribute names
|
||||
"opentofu.provider.address" // For provider addresses
|
||||
"opentofu.module.source" // For module sources
|
||||
"opentofu.operation.target_count" // For operation-specific counts
|
||||
```
|
||||
|
||||
- Prefer standard [OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/semconv/) where applicable, using helper functions from [`internal/tracing/traceattrs`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tracing/traceattrs).
|
||||
- Use `OpenTofu`-prefixed functions in [`internal/tracing/traceattrs`](https://pkg.go.dev/github.com/opentofu/opentofu/internal/tracing/traceattrs) for OpenTofu-specific cross-cutting concerns.
|
||||
- It's okay to use one-off inline strings for attribute names specific to a single span, but make sure to still follow the [OpenTelemetry attribute naming conventions](https://opentelemetry.io/docs/specs/semconv/general/naming/) and use the `opentofu.` prefix for anything that is not a standardized semantic convention.
|
||||
- If a particular subsystem of OpenTofu has some repeated conventions for attribute names, consider creating unexported string constants or attribute construction helper functions in the same package to centralize those naming conventions.
|
||||
|
||||
#### Error Handling
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@ import (
|
||||
"github.com/opentofu/svchost"
|
||||
"github.com/posener/complete"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
@@ -36,6 +34,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/tofu"
|
||||
"github.com/opentofu/opentofu/internal/tofumigrate"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
tfversion "github.com/opentofu/opentofu/version"
|
||||
)
|
||||
|
||||
@@ -164,8 +163,8 @@ func (c *InitCommand) Run(args []string) int {
|
||||
ShowLocalPaths: false, // since they are in a weird location for init
|
||||
}
|
||||
|
||||
ctx, span := tracing.Tracer().Start(ctx, "From module", trace.WithAttributes(
|
||||
otelAttr.String("opentofu.module_source", src),
|
||||
ctx, span := tracing.Tracer().Start(ctx, "From module", tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuModuleSource(src),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
@@ -407,8 +406,8 @@ func (c *InitCommand) getModules(ctx context.Context, path, testsDir string, ear
|
||||
return false, false, nil
|
||||
}
|
||||
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Get Modules", trace.WithAttributes(
|
||||
otelAttr.Bool("opentofu.modules.upgrade", upgrade),
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Get Modules", tracing.SpanAttributes(
|
||||
traceattrs.Bool("opentofu.modules.upgrade", upgrade),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
|
||||
@@ -10,14 +10,13 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/depsfile"
|
||||
"github.com/opentofu/opentofu/internal/getproviders"
|
||||
"github.com/opentofu/opentofu/internal/providercache"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
type providersLockChangeType string
|
||||
@@ -61,12 +60,12 @@ func (c *ProvidersLockCommand) Run(args []string) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
span.SetAttributes(otelAttr.StringSlice("opentofu.provider.lock.targetplatforms", optPlatforms))
|
||||
span.SetAttributes(traceattrs.StringSlice("opentofu.provider.lock.targetplatforms", optPlatforms))
|
||||
if fsMirrorDir != "" {
|
||||
span.SetAttributes(otelAttr.String("opentofu.provider.lock.fsmirror", fsMirrorDir))
|
||||
span.SetAttributes(traceattrs.String("opentofu.provider.lock.fsmirror", fsMirrorDir))
|
||||
}
|
||||
if netMirrorURL != "" {
|
||||
span.SetAttributes(otelAttr.String("opentofu.provider.lock.netmirror", netMirrorURL))
|
||||
span.SetAttributes(traceattrs.String("opentofu.provider.lock.netmirror", netMirrorURL))
|
||||
}
|
||||
|
||||
var diags tfdiags.Diagnostics
|
||||
@@ -88,7 +87,7 @@ func (c *ProvidersLockCommand) Run(args []string) int {
|
||||
if len(optPlatforms) == 0 {
|
||||
platforms = []getproviders.Platform{getproviders.CurrentPlatform}
|
||||
span.SetAttributes(
|
||||
otelAttr.StringSlice("opentofu.provider.lock.targetplatforms", []string{getproviders.CurrentPlatform.String()}),
|
||||
traceattrs.StringSlice("opentofu.provider.lock.targetplatforms", []string{getproviders.CurrentPlatform.String()}),
|
||||
)
|
||||
} else {
|
||||
platforms = make([]getproviders.Platform, 0, len(optPlatforms))
|
||||
|
||||
@@ -12,9 +12,6 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/cloud"
|
||||
"github.com/opentofu/opentofu/internal/cloud/cloudplan"
|
||||
@@ -29,6 +26,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tofu"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// Many of the methods we get data from can emit special error types if they're
|
||||
@@ -76,11 +74,11 @@ func (c *ShowCommand) Run(rawArgs []string) int {
|
||||
|
||||
//nolint:ineffassign - As this is a high-level call, we want to ensure that we are correctly using the right ctx later on when
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Show",
|
||||
trace.WithAttributes(
|
||||
otelAttr.String("opentofu.show.view", args.ViewType.String()),
|
||||
otelAttr.String("opentofu.show.target", args.TargetType.String()),
|
||||
otelAttr.String("opentofu.show.target_arg", args.TargetArg),
|
||||
otelAttr.Bool("opentofu.show.show_sensitive", args.ShowSensitive),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("opentofu.show.view", args.ViewType.String()),
|
||||
traceattrs.String("opentofu.show.target", args.TargetType.String()),
|
||||
traceattrs.String("opentofu.show.target_arg", args.TargetArg),
|
||||
traceattrs.Bool("opentofu.show.show_sensitive", args.ShowSensitive),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
@@ -16,14 +16,13 @@ import (
|
||||
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||||
"github.com/hashicorp/hcl/v2/hclwrite"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.30.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/getproviders"
|
||||
"github.com/opentofu/opentofu/internal/replacefile"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
"github.com/opentofu/opentofu/version"
|
||||
)
|
||||
|
||||
@@ -95,7 +94,9 @@ func loadLocks(loadParse func(*hclparse.Parser) (*hcl.File, hcl.Diagnostics)) (*
|
||||
// temporary files may be temporarily created in the same directory as the
|
||||
// given filename during the operation.
|
||||
func SaveLocksToFile(ctx context.Context, locks *Locks, filename string) tfdiags.Diagnostics {
|
||||
_, span := tracing.Tracer().Start(ctx, "Save lockfile", trace.WithAttributes(semconv.FileName(filename)))
|
||||
_, span := tracing.Tracer().Start(ctx, "Save lockfile", tracing.SpanAttributes(
|
||||
traceattrs.FilePath(filename),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
src, diags := SaveLocksToBytes(locks)
|
||||
@@ -105,7 +106,7 @@ func SaveLocksToFile(ctx context.Context, locks *Locks, filename string) tfdiags
|
||||
}
|
||||
|
||||
span.AddEvent("Serialized lockfile")
|
||||
span.SetAttributes(semconv.FileSize(len(src)))
|
||||
span.SetAttributes(traceattrs.FileSize(len(src)))
|
||||
|
||||
err := replacefile.AtomicWriteFile(filename, src, 0644)
|
||||
if err != nil {
|
||||
|
||||
@@ -10,12 +10,11 @@ import (
|
||||
"fmt"
|
||||
"maps"
|
||||
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.30.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
getter "github.com/hashicorp/go-getter"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// PackageFetcher is a low-level utility for fetching remote module packages
|
||||
@@ -90,7 +89,7 @@ func NewPackageFetcher(ctx context.Context, env PackageFetcherEnvironment) *Pack
|
||||
// getmodules.SplitPackageSubdir and getmodules.ExpandSubdirGlobs functions.
|
||||
func (f *PackageFetcher) FetchPackage(ctx context.Context, instDir string, packageAddr string) error {
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Fetch Package",
|
||||
trace.WithAttributes(semconv.URLFull(packageAddr)),
|
||||
tracing.SpanAttributes(traceattrs.URLFull(packageAddr)),
|
||||
)
|
||||
defer span.End()
|
||||
err := f.getter.getWithGoGetter(ctx, instDir, packageAddr)
|
||||
|
||||
@@ -17,11 +17,11 @@ import (
|
||||
getter "github.com/hashicorp/go-getter"
|
||||
ociDigest "github.com/opencontainers/go-digest"
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
orasContent "oras.land/oras-go/v2/content"
|
||||
orasRegistry "oras.land/oras-go/v2/registry"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// ociImageManifestArtifactType is the artifact type we expect for the image
|
||||
@@ -71,9 +71,9 @@ func (g *ociDistributionGetter) Get(destDir string, url *url.URL) error {
|
||||
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Fetch 'oci' module package",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String("opentofu.module.source", url.String()),
|
||||
otelAttr.String("opentofu.module.local_dir", destDir),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("opentofu.module.source", url.String()),
|
||||
traceattrs.String("opentofu.module.local_dir", destDir),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -220,9 +220,9 @@ func (g *ociDistributionGetter) resolveRepositoryRef(url *url.URL) (*orasRegistr
|
||||
func (g *ociDistributionGetter) resolveManifestDescriptor(ctx context.Context, ref *orasRegistry.Reference, query url.Values, store OCIRepositoryStore) (desc ociv1.Descriptor, err error) {
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Resolve reference",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String("opentofu.oci.registry.domain", ref.Registry),
|
||||
otelAttr.String("opentofu.oci.repository.name", ref.Repository),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("opentofu.oci.registry.domain", ref.Registry),
|
||||
traceattrs.String("opentofu.oci.repository.name", ref.Repository),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -279,7 +279,7 @@ func (g *ociDistributionGetter) resolveManifestDescriptor(ctx context.Context, r
|
||||
// If we're starting with a tag name then we need to query the
|
||||
// repository to find out which digest is currently selected.
|
||||
span.SetAttributes(
|
||||
otelAttr.String("opentofu.oci.reference.tag", wantTag),
|
||||
traceattrs.String("opentofu.oci.reference.tag", wantTag),
|
||||
)
|
||||
desc, err = store.Resolve(ctx, wantTag)
|
||||
if err != nil {
|
||||
@@ -294,7 +294,7 @@ func (g *ociDistributionGetter) resolveManifestDescriptor(ctx context.Context, r
|
||||
// and so we can't exercise this specific case from unit tests
|
||||
// using in-memory or on-disk fakes. :(
|
||||
span.SetAttributes(
|
||||
otelAttr.String("opentofu.oci.reference.digest", wantDigest.String()),
|
||||
traceattrs.String("opentofu.oci.reference.digest", wantDigest.String()),
|
||||
)
|
||||
desc, err = store.Resolve(ctx, wantDigest.String())
|
||||
if err != nil {
|
||||
@@ -303,9 +303,9 @@ func (g *ociDistributionGetter) resolveManifestDescriptor(ctx context.Context, r
|
||||
}
|
||||
|
||||
span.SetAttributes(
|
||||
otelAttr.String("oci.manifest.digest", desc.Digest.String()),
|
||||
otelAttr.String("opentofu.oci.manifest.media_type", desc.MediaType),
|
||||
otelAttr.Int64("opentofu.oci.manifest.size", desc.Size),
|
||||
traceattrs.String("oci.manifest.digest", desc.Digest.String()),
|
||||
traceattrs.String("opentofu.oci.manifest.media_type", desc.MediaType),
|
||||
traceattrs.Int64("opentofu.oci.manifest.size", desc.Size),
|
||||
)
|
||||
|
||||
// The initial request is only required to return a "plain" descriptor,
|
||||
@@ -326,9 +326,9 @@ func (g *ociDistributionGetter) resolveManifestDescriptor(ctx context.Context, r
|
||||
func fetchOCIImageManifest(ctx context.Context, desc ociv1.Descriptor, store OCIRepositoryStore) (*ociv1.Manifest, error) {
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Fetch manifest",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String("oci.manifest.digest", desc.Digest.String()),
|
||||
otelAttr.Int64("opentofu.oci.manifest.size", desc.Size),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("oci.manifest.digest", desc.Digest.String()),
|
||||
traceattrs.Int64("opentofu.oci.manifest.size", desc.Size),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -356,8 +356,8 @@ func fetchOCIImageManifest(ctx context.Context, desc ociv1.Descriptor, store OCI
|
||||
}
|
||||
|
||||
span.SetAttributes(
|
||||
otelAttr.String("opentofu.oci.manifest.media_type", desc.MediaType),
|
||||
otelAttr.String("opentofu.oci.manifest.artifact_type", desc.ArtifactType),
|
||||
traceattrs.String("opentofu.oci.manifest.media_type", desc.MediaType),
|
||||
traceattrs.String("opentofu.oci.manifest.artifact_type", desc.ArtifactType),
|
||||
)
|
||||
|
||||
// Now we'll make sure that what we decoded seems vaguely sensible before we
|
||||
@@ -454,10 +454,10 @@ func selectOCILayerBlob(descs []ociv1.Descriptor) (ociv1.Descriptor, error) {
|
||||
func fetchOCIBlobToTemporaryFile(ctx context.Context, desc ociv1.Descriptor, store orasContent.Fetcher) (tempFile string, err error) {
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Fetch module package",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String("opentofu.oci.blob.digest", desc.Digest.String()),
|
||||
otelAttr.String("opentofu.oci.blob.media_type", desc.MediaType),
|
||||
otelAttr.Int64("opentofu.oci.blob.size", desc.Size),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("opentofu.oci.blob.digest", desc.Digest.String()),
|
||||
traceattrs.String("opentofu.oci.blob.media_type", desc.MediaType),
|
||||
traceattrs.Int64("opentofu.oci.blob.size", desc.Size),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
@@ -16,8 +16,6 @@ import (
|
||||
|
||||
"github.com/apparentlymart/go-versions/versions"
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
orasErrors "oras.land/oras-go/v2/errdef"
|
||||
orasRegistryErrors "oras.land/oras-go/v2/registry/remote/errcode"
|
||||
|
||||
@@ -163,8 +161,8 @@ func NewOCIRegistryMirrorSource(
|
||||
func (o *OCIRegistryMirrorSource) AvailableVersions(ctx context.Context, provider addrs.Provider) (VersionList, Warnings, error) {
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Get available versions from oci_mirror",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceattrs.ProviderAddress, provider.String()),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuProviderAddress(provider.String()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -278,10 +276,10 @@ func errRepresentsOCIProviderNotFound(err error) bool {
|
||||
func (o *OCIRegistryMirrorSource) PackageMeta(ctx context.Context, provider addrs.Provider, version Version, target Platform) (PackageMeta, error) {
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Get metadata from oci_mirror",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceattrs.ProviderAddress, provider.String()),
|
||||
otelAttr.String(traceattrs.ProviderVersion, version.String()),
|
||||
otelAttr.String(traceattrs.TargetPlatform, target.String()),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuProviderAddress(provider.String()),
|
||||
traceattrs.OpenTofuProviderVersion(version.String()),
|
||||
traceattrs.OpenTofuTargetPlatform(target.String()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -476,8 +474,8 @@ type OCIRepositoryStore interface {
|
||||
func fetchOCIDescriptorForVersion(ctx context.Context, version versions.Version, store OCIRepositoryStore) (ociv1.Descriptor, error) {
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Resolve reference",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceattrs.ProviderVersion, version.String()),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuProviderVersion(version.String()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -495,9 +493,9 @@ func fetchOCIDescriptorForVersion(ctx context.Context, version versions.Version,
|
||||
return ociv1.Descriptor{}, prepErr(fmt.Errorf("resolving tag %q: %w", tagName, err))
|
||||
}
|
||||
span.SetAttributes(
|
||||
otelAttr.String("oci.manifest.digest", desc.Digest.String()),
|
||||
otelAttr.String("opentofu.oci.reference.tag", tagName),
|
||||
otelAttr.String("opentofu.oci.manifest.media_type", desc.MediaType),
|
||||
traceattrs.String("oci.manifest.digest", desc.Digest.String()),
|
||||
traceattrs.String("opentofu.oci.reference.tag", tagName),
|
||||
traceattrs.String("opentofu.oci.manifest.media_type", desc.MediaType),
|
||||
)
|
||||
// Not all store implementations can return the manifest's artifact type as part
|
||||
// of the tag-resolution response, so we'll check this early if we can, but
|
||||
@@ -507,7 +505,7 @@ func fetchOCIDescriptorForVersion(ctx context.Context, version versions.Version,
|
||||
// one way or another.)
|
||||
if desc.ArtifactType != "" && desc.ArtifactType != ociIndexManifestArtifactType {
|
||||
span.SetAttributes(
|
||||
otelAttr.String("opentofu.oci.manifest.artifact_type", desc.ArtifactType),
|
||||
traceattrs.String("opentofu.oci.manifest.artifact_type", desc.ArtifactType),
|
||||
)
|
||||
switch desc.ArtifactType {
|
||||
case "application/vnd.opentofu.provider-target":
|
||||
@@ -546,9 +544,9 @@ func fetchOCIDescriptorForVersion(ctx context.Context, version versions.Version,
|
||||
func fetchOCIIndexManifest(ctx context.Context, desc ociv1.Descriptor, store OCIRepositoryStore) (*ociv1.Index, error) {
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Fetch index manifest",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String("oci.manifest.digest", desc.Digest.String()),
|
||||
otelAttr.Int64("opentofu.oci.manifest.size", desc.Size),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("oci.manifest.digest", desc.Digest.String()),
|
||||
traceattrs.Int64("opentofu.oci.manifest.size", desc.Size),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -575,8 +573,8 @@ func fetchOCIIndexManifest(ctx context.Context, desc ociv1.Descriptor, store OCI
|
||||
return nil, prepErr(fmt.Errorf("invalid manifest content: %w", err))
|
||||
}
|
||||
span.SetAttributes(
|
||||
otelAttr.String("opentofu.oci.manifest.media_type", manifest.MediaType),
|
||||
otelAttr.String("opentofu.oci.manifest.artifact_type", manifest.ArtifactType),
|
||||
traceattrs.String("opentofu.oci.manifest.media_type", manifest.MediaType),
|
||||
traceattrs.String("opentofu.oci.manifest.artifact_type", manifest.ArtifactType),
|
||||
)
|
||||
|
||||
// Now we'll make sure that what we decoded seems vaguely sensible before we
|
||||
@@ -598,9 +596,9 @@ func fetchOCIIndexManifest(ctx context.Context, desc ociv1.Descriptor, store OCI
|
||||
func fetchOCIImageManifest(ctx context.Context, desc ociv1.Descriptor, store OCIRepositoryStore) (*ociv1.Manifest, error) {
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Fetch platform-specific manifest",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String("oci.manifest.digest", desc.Digest.String()),
|
||||
otelAttr.Int64("opentofu.oci.manifest.size", desc.Size),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("oci.manifest.digest", desc.Digest.String()),
|
||||
traceattrs.Int64("opentofu.oci.manifest.size", desc.Size),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -627,8 +625,8 @@ func fetchOCIImageManifest(ctx context.Context, desc ociv1.Descriptor, store OCI
|
||||
return nil, prepErr(fmt.Errorf("invalid manifest content: %w", err))
|
||||
}
|
||||
span.SetAttributes(
|
||||
otelAttr.String("opentofu.oci.manifest.media_type", manifest.MediaType),
|
||||
otelAttr.String("opentofu.oci.manifest.artifact_type", manifest.ArtifactType),
|
||||
traceattrs.String("opentofu.oci.manifest.media_type", manifest.MediaType),
|
||||
traceattrs.String("opentofu.oci.manifest.artifact_type", manifest.ArtifactType),
|
||||
)
|
||||
|
||||
// Now we'll make sure that what we decoded seems vaguely sensible before we
|
||||
|
||||
@@ -14,12 +14,11 @@ import (
|
||||
|
||||
"github.com/hashicorp/go-getter"
|
||||
"github.com/hashicorp/go-retryablehttp"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/logging"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.30.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// PackageHTTPURL is a provider package location accessible via HTTP.
|
||||
@@ -53,8 +52,8 @@ func (p PackageHTTPURL) String() string { return p.URL }
|
||||
func (p PackageHTTPURL) InstallProviderPackage(ctx context.Context, meta PackageMeta, targetDir string, allowedHashes []Hash) (*PackageAuthenticationResult, error) {
|
||||
url := meta.Location.String()
|
||||
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Install (http)", trace.WithAttributes(
|
||||
semconv.URLFull(url),
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Install (http)", tracing.SpanAttributes(
|
||||
traceattrs.URLFull(url),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/go-getter"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.30.0"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// We borrow the "unpack a zip file into a target directory" logic from
|
||||
@@ -67,7 +67,7 @@ func (p PackageLocalArchive) InstallProviderPackage(ctx context.Context, meta Pa
|
||||
}
|
||||
|
||||
filename := meta.Location.String()
|
||||
span.SetAttributes(semconv.FilePath(filename))
|
||||
span.SetAttributes(traceattrs.FilePath(filename))
|
||||
|
||||
// NOTE: Packages are immutable, but we may want to skip overwriting the existing
|
||||
// files in due to specific scenarios defined below.
|
||||
|
||||
@@ -16,11 +16,10 @@ import (
|
||||
"github.com/hashicorp/go-getter"
|
||||
ociDigest "github.com/opencontainers/go-digest"
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
orasContent "oras.land/oras-go/v2/content"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
orasContent "oras.land/oras-go/v2/content"
|
||||
)
|
||||
|
||||
// ociPackageMediaType is the specific media type we're expecting for the blob
|
||||
@@ -88,16 +87,16 @@ func (p PackageOCIBlobArchive) InstallProviderPackage(ctx context.Context, meta
|
||||
pkgDesc := p.blobDescriptor
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Fetch provider package",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String("opentofu.oci.registry.domain", p.registryDomain),
|
||||
otelAttr.String("opentofu.oci.repository.name", p.repositoryName),
|
||||
otelAttr.String("opentofu.oci.blob.digest", pkgDesc.Digest.String()),
|
||||
otelAttr.String("opentofu.oci.blob.media_type", pkgDesc.MediaType),
|
||||
otelAttr.Int64("opentofu.oci.blob.size", pkgDesc.Size),
|
||||
otelAttr.String("opentofu.provider.local_dir", targetDir),
|
||||
otelAttr.String(traceattrs.ProviderAddress, meta.Provider.String()),
|
||||
otelAttr.String(traceattrs.ProviderVersion, meta.Version.String()),
|
||||
otelAttr.String(traceattrs.TargetPlatform, meta.TargetPlatform.String()),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("opentofu.oci.registry.domain", p.registryDomain),
|
||||
traceattrs.String("opentofu.oci.repository.name", p.repositoryName),
|
||||
traceattrs.String("opentofu.oci.blob.digest", pkgDesc.Digest.String()),
|
||||
traceattrs.String("opentofu.oci.blob.media_type", pkgDesc.MediaType),
|
||||
traceattrs.Int64("opentofu.oci.blob.size", pkgDesc.Size),
|
||||
traceattrs.String("opentofu.provider.local_dir", targetDir),
|
||||
traceattrs.OpenTofuProviderAddress(meta.Provider.String()),
|
||||
traceattrs.OpenTofuProviderVersion(meta.Version.String()),
|
||||
traceattrs.OpenTofuTargetPlatform(meta.TargetPlatform.String()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
@@ -20,9 +20,6 @@ import (
|
||||
"github.com/hashicorp/go-retryablehttp"
|
||||
"github.com/opentofu/svchost"
|
||||
"github.com/opentofu/svchost/svcauth"
|
||||
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/tracing"
|
||||
@@ -67,8 +64,8 @@ func newRegistryClient(ctx context.Context, baseURL *url.URL, creds svcauth.Host
|
||||
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()),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuProviderAddress(addr.String()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -79,7 +76,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()))
|
||||
span.SetAttributes(traceattrs.URLFull(endpointURL.String()))
|
||||
req, err := retryablehttp.NewRequest("GET", endpointURL.String(), nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -167,9 +164,9 @@ func (c *registryClient) PackageMeta(ctx context.Context, provider addrs.Provide
|
||||
))
|
||||
ctx, span := tracing.Tracer().Start(ctx,
|
||||
"Fetch metadata",
|
||||
trace.WithAttributes(
|
||||
otelAttr.String(traceattrs.ProviderAddress, provider.String()),
|
||||
otelAttr.String(traceattrs.ProviderVersion, version.String()),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuProviderAddress(provider.String()),
|
||||
traceattrs.OpenTofuProviderVersion(version.String()),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
@@ -180,7 +177,7 @@ func (c *registryClient) PackageMeta(ctx context.Context, provider addrs.Provide
|
||||
}
|
||||
endpointURL := c.baseURL.ResolveReference(endpointPath)
|
||||
span.SetAttributes(
|
||||
semconv.URLFull(endpointURL.String()),
|
||||
traceattrs.URLFull(endpointURL.String()),
|
||||
)
|
||||
|
||||
req, err := retryablehttp.NewRequest("GET", endpointURL.String(), nil)
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
|
||||
cleanhttp "github.com/hashicorp/go-cleanhttp"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/version"
|
||||
)
|
||||
|
||||
@@ -34,7 +34,7 @@ func New(ctx context.Context) *http.Client {
|
||||
inner: cli.Transport,
|
||||
}
|
||||
|
||||
if span := otelTrace.SpanFromContext(ctx); span != nil && span.IsRecording() {
|
||||
if span := tracing.SpanFromContext(ctx); span != nil && span.IsRecording() {
|
||||
// We consider the presence of an active span -- that is, one whose
|
||||
// presence is going to be reported to a trace collector outside of
|
||||
// the OpenTofu process -- as sufficient signal that generating
|
||||
|
||||
@@ -20,8 +20,6 @@ import (
|
||||
version "github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
@@ -242,10 +240,11 @@ func (i *ModuleInstaller) moduleInstallWalker(_ context.Context, manifest modsdi
|
||||
|
||||
ctx, span := tracing.Tracer().Start(ctx,
|
||||
fmt.Sprintf("Install Module %q", req.Name),
|
||||
trace.WithAttributes(
|
||||
otelAttr.String(traceattrs.ModuleCallName, req.Name),
|
||||
otelAttr.String(traceattrs.ModuleSource, req.SourceAddr.String()),
|
||||
))
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuModuleCallName(req.Name),
|
||||
traceattrs.OpenTofuModuleSource(req.SourceAddr.String()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
log.Printf("[DEBUG] Module installer: begin %s", key)
|
||||
@@ -343,7 +342,7 @@ func (i *ModuleInstaller) moduleInstallWalker(_ context.Context, manifest modsdi
|
||||
|
||||
case addrs.ModuleSourceLocal:
|
||||
log.Printf("[TRACE] ModuleInstaller: %s has local path %q", key, addr.String())
|
||||
span.SetAttributes(otelAttr.String("opentofu.module.source_type", "local"))
|
||||
span.SetAttributes(traceattrs.String("opentofu.module.source_type", "local"))
|
||||
mod, mDiags := i.installLocalModule(ctx, req, key, manifest, hooks)
|
||||
mDiags = maybeImproveLocalInstallError(req, mDiags)
|
||||
diags = append(diags, mDiags...)
|
||||
@@ -351,7 +350,7 @@ func (i *ModuleInstaller) moduleInstallWalker(_ context.Context, manifest modsdi
|
||||
|
||||
case addrs.ModuleSourceRegistry:
|
||||
log.Printf("[TRACE] ModuleInstaller: %s is a registry module at %s", key, addr.String())
|
||||
span.SetAttributes(otelAttr.String("opentofu.module.source_type", "registry"))
|
||||
span.SetAttributes(traceattrs.String("opentofu.module.source_type", "registry"))
|
||||
mod, v, mDiags := i.installRegistryModule(ctx, req, key, instPath, addr, manifest, hooks, fetcher)
|
||||
diags = append(diags, mDiags...)
|
||||
return mod, v, diags
|
||||
@@ -426,9 +425,9 @@ func (i *ModuleInstaller) installDescendentModules(ctx context.Context, rootMod
|
||||
func (i *ModuleInstaller) installLocalModule(ctx context.Context, req *configs.ModuleRequest, key string, manifest modsdir.Manifest, hooks ModuleInstallHooks) (*configs.Module, hcl.Diagnostics) {
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
_, span := tracing.Tracer().Start(ctx, "Install Local Module",
|
||||
trace.WithAttributes(otelAttr.String(traceattrs.ModuleCallName, req.Name)),
|
||||
trace.WithAttributes(otelAttr.String(traceattrs.ModuleSource, req.SourceAddr.String())),
|
||||
_, span := tracing.Tracer().Start(ctx, "Install Local Module", tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuModuleCallName(req.Name),
|
||||
traceattrs.OpenTofuModuleSource(req.SourceAddr.String())),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
@@ -508,11 +507,11 @@ var versionRegexp = regexp.MustCompile(version.VersionRegexpRaw)
|
||||
func (i *ModuleInstaller) installRegistryModule(ctx context.Context, req *configs.ModuleRequest, key string, instPath string, addr addrs.ModuleSourceRegistry, manifest modsdir.Manifest, hooks ModuleInstallHooks, fetcher *getmodules.PackageFetcher) (*configs.Module, *version.Version, hcl.Diagnostics) {
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Install Registry Module",
|
||||
trace.WithAttributes(otelAttr.String(traceattrs.ModuleCallName, req.Name)),
|
||||
trace.WithAttributes(otelAttr.String(traceattrs.ModuleSource, req.SourceAddr.String())),
|
||||
trace.WithAttributes(otelAttr.String(traceattrs.ModuleVersion, req.VersionConstraint.Required.String())),
|
||||
)
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Install Registry Module", tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuModuleCallName(req.Name),
|
||||
traceattrs.OpenTofuModuleSource(req.SourceAddr.String()),
|
||||
traceattrs.OpenTofuModuleVersion(req.VersionConstraint.Required.String()),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
if i.reg == nil || fetcher == nil {
|
||||
@@ -774,7 +773,7 @@ func (i *ModuleInstaller) installRegistryModule(ctx context.Context, req *config
|
||||
return nil, nil, diags
|
||||
}
|
||||
|
||||
span.SetAttributes(otelAttr.String(traceattrs.ModuleSource, realAddr.String()))
|
||||
span.SetAttributes(traceattrs.OpenTofuModuleSource(realAddr.String()))
|
||||
|
||||
switch realAddr := realAddr.(type) {
|
||||
// Only a remote source address is allowed here: a registry isn't
|
||||
|
||||
@@ -14,8 +14,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/apparentlymart/go-versions/versions"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
copydir "github.com/opentofu/opentofu/internal/copy"
|
||||
@@ -235,7 +233,7 @@ func (i *Installer) EnsureProviderVersions(ctx context.Context, locks *depsfile.
|
||||
// Step 3: For each provider version we've decided we need to install,
|
||||
// install its package into our target cache (possibly via the global cache).
|
||||
targetPlatform := i.targetDir.targetPlatform // we inherit this to behave correctly in unit tests
|
||||
span.SetAttributes(otelAttr.String(traceattrs.TargetPlatform, targetPlatform.String()))
|
||||
span.SetAttributes(traceattrs.OpenTofuTargetPlatform(targetPlatform.String()))
|
||||
span.SetName("Install Providers - " + targetPlatform.String())
|
||||
authResults, err := i.ensureProviderVersionsInstall(ctx, locks, reqs, mode, need, targetPlatform, errs)
|
||||
if err != nil {
|
||||
@@ -449,10 +447,10 @@ func (i *Installer) ensureProviderVersionsInstall(
|
||||
for provider, version := range need {
|
||||
traceCtx, span := tracing.Tracer().Start(ctx,
|
||||
fmt.Sprintf("Install Provider %q", provider.String()),
|
||||
trace.WithAttributes(
|
||||
otelAttr.String(traceattrs.ProviderAddress, provider.String()),
|
||||
otelAttr.String(traceattrs.ProviderVersion, version.String()),
|
||||
otelAttr.String(traceattrs.TargetPlatform, targetPlatform.String()),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuProviderAddress(provider.String()),
|
||||
traceattrs.OpenTofuProviderVersion(version.String()),
|
||||
traceattrs.OpenTofuTargetPlatform(targetPlatform.String()),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ import (
|
||||
"github.com/hashicorp/go-retryablehttp"
|
||||
"github.com/opentofu/svchost"
|
||||
"github.com/opentofu/svchost/disco"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/registry/regsrc"
|
||||
@@ -84,11 +82,9 @@ func (c *Client) Discover(ctx context.Context, host svchost.Hostname, serviceID
|
||||
|
||||
// ModuleVersions queries the registry for a module, and returns the available versions.
|
||||
func (c *Client) ModuleVersions(ctx context.Context, module *regsrc.Module) (*response.ModuleVersions, error) {
|
||||
ctx, span := tracing.Tracer().Start(ctx, "List Versions",
|
||||
trace.WithAttributes(
|
||||
otelAttr.String("opentofu.module.name", module.RawName),
|
||||
),
|
||||
)
|
||||
ctx, span := tracing.Tracer().Start(ctx, "List Versions", tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuModuleCallName(module.RawName),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
host, err := module.SvcHost()
|
||||
@@ -165,13 +161,11 @@ func (c *Client) addRequestCreds(ctx context.Context, host svchost.Hostname, req
|
||||
// ModuleLocation find the download location for a specific version module.
|
||||
// This returns a string, because the final location may contain special go-getter syntax.
|
||||
func (c *Client) ModuleLocation(ctx context.Context, module *regsrc.Module, version string) (string, error) {
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Find Module Location",
|
||||
trace.WithAttributes(
|
||||
otelAttr.String(traceattrs.ModuleCallName, module.RawName),
|
||||
otelAttr.String(traceattrs.ModuleSource, module.Module()),
|
||||
otelAttr.String(traceattrs.ModuleVersion, version),
|
||||
),
|
||||
)
|
||||
ctx, span := tracing.Tracer().Start(ctx, "Find Module Location", tracing.SpanAttributes(
|
||||
traceattrs.OpenTofuModuleCallName(module.RawName),
|
||||
traceattrs.OpenTofuModuleSource(module.Module()),
|
||||
traceattrs.OpenTofuModuleVersion(version),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
host, err := module.SvcHost()
|
||||
|
||||
@@ -12,8 +12,6 @@ import (
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
@@ -21,6 +19,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// ApplyOpts are the various options that affect the details of how OpenTofu
|
||||
@@ -57,8 +56,8 @@ func (c *Context) Apply(ctx context.Context, plan *plans.Plan, config *configs.C
|
||||
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, "Apply phase",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String("opentofu.plan.mode", plan.UIMode.UIName()),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String("opentofu.plan.mode", plan.UIMode.UIName()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
@@ -16,8 +16,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
@@ -29,6 +27,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// PlanOpts are the various options that affect the details of how OpenTofu
|
||||
@@ -150,10 +149,10 @@ func (c *Context) Plan(ctx context.Context, config *configs.Config, prevRunState
|
||||
ctx, "Plan phase",
|
||||
)
|
||||
span.SetAttributes(
|
||||
otelAttr.String("opentofu.plan.mode", opts.Mode.UIName()),
|
||||
otelAttr.StringSlice("opentofu.plan.target_addrs", tracing.StringSlice(span, slices.Values(opts.Targets))),
|
||||
otelAttr.StringSlice("opentofu.plan.exclude_addrs", tracing.StringSlice(span, slices.Values(opts.Excludes))),
|
||||
otelAttr.StringSlice("opentofu.plan.force_replace_addrs", tracing.StringSlice(span, slices.Values(opts.ForceReplace))),
|
||||
traceattrs.String("opentofu.plan.mode", opts.Mode.UIName()),
|
||||
traceattrs.StringSlice("opentofu.plan.target_addrs", tracing.StringSlice(span, slices.Values(opts.Targets))),
|
||||
traceattrs.StringSlice("opentofu.plan.exclude_addrs", tracing.StringSlice(span, slices.Values(opts.Excludes))),
|
||||
traceattrs.StringSlice("opentofu.plan.force_replace_addrs", tracing.StringSlice(span, slices.Values(opts.ForceReplace))),
|
||||
// Additions here should typically be limited only to options that
|
||||
// significantly change what provider-driven operations we'd perform
|
||||
// during the planning phase, since that's the main influence on how
|
||||
|
||||
@@ -12,14 +12,13 @@ import (
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// traceAttrProviderAddress is a standardized trace span attribute name that we
|
||||
@@ -127,10 +126,10 @@ func (n *NodeApplyableProvider) executeInstance(ctx context.Context, evalCtx Eva
|
||||
func (n *NodeApplyableProvider) ValidateProvider(ctx context.Context, evalCtx EvalContext, providerKey addrs.InstanceKey, provider providers.Interface) tfdiags.Diagnostics {
|
||||
_, span := tracing.Tracer().Start(
|
||||
ctx, "Validate provider configuration",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceAttrProviderAddr, n.Addr.Provider.String()),
|
||||
otelAttr.String(traceAttrProviderConfigAddr, n.Addr.String()),
|
||||
otelAttr.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.Addr, providerKey)),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String(traceAttrProviderAddr, n.Addr.Provider.String()),
|
||||
traceattrs.String(traceAttrProviderConfigAddr, n.Addr.String()),
|
||||
traceattrs.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.Addr, providerKey)),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -193,10 +192,10 @@ func (n *NodeApplyableProvider) ValidateProvider(ctx context.Context, evalCtx Ev
|
||||
func (n *NodeApplyableProvider) ConfigureProvider(ctx context.Context, evalCtx EvalContext, providerKey addrs.InstanceKey, provider providers.Interface, verifyConfigIsKnown bool) tfdiags.Diagnostics {
|
||||
_, span := tracing.Tracer().Start(
|
||||
ctx, "Configure provider",
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceAttrProviderAddr, n.Addr.Provider.String()),
|
||||
otelAttr.String(traceAttrProviderConfigAddr, n.Addr.String()),
|
||||
otelAttr.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.Addr, providerKey)),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String(traceAttrProviderAddr, n.Addr.Provider.String()),
|
||||
traceattrs.String(traceAttrProviderConfigAddr, n.Addr.String()),
|
||||
traceattrs.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.Addr, providerKey)),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
@@ -10,9 +10,6 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/instances"
|
||||
@@ -22,6 +19,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// NodeApplyableResourceInstance represents a resource instance that is
|
||||
@@ -126,8 +124,8 @@ func (n *NodeApplyableResourceInstance) Execute(ctx context.Context, evalCtx Eva
|
||||
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, traceNameApplyResourceInstance,
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceAttrResourceInstanceAddr, addr.String()),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String(traceAttrResourceInstanceAddr, addr.String()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -161,7 +159,7 @@ func (n *NodeApplyableResourceInstance) Execute(ctx context.Context, evalCtx Eva
|
||||
return diags
|
||||
}
|
||||
span.SetAttributes(
|
||||
otelAttr.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
traceattrs.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
)
|
||||
|
||||
// Eval info is different depending on what kind of resource this is
|
||||
|
||||
@@ -11,8 +11,6 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/dag"
|
||||
@@ -22,6 +20,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// ConcreteResourceInstanceDeposedNodeFunc is a callback type used to convert
|
||||
@@ -96,9 +95,9 @@ func (n *NodePlanDeposedResourceInstanceObject) Execute(ctx context.Context, eva
|
||||
|
||||
_, span := tracing.Tracer().Start(
|
||||
ctx, traceNamePlanResourceInstance,
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceAttrResourceInstanceAddr, n.Addr.String()),
|
||||
otelAttr.Bool(traceAttrPlanRefresh, !n.skipRefresh),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String(traceAttrResourceInstanceAddr, n.Addr.String()),
|
||||
traceattrs.Bool(traceAttrPlanRefresh, !n.skipRefresh),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -108,7 +107,7 @@ func (n *NodePlanDeposedResourceInstanceObject) Execute(ctx context.Context, eva
|
||||
return diags
|
||||
}
|
||||
span.SetAttributes(
|
||||
otelAttr.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
traceattrs.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
)
|
||||
|
||||
// Read the state for the deposed resource instance
|
||||
|
||||
@@ -10,9 +10,6 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/communicator/shared"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
@@ -21,6 +18,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// NodeDestroyResourceInstance represents a resource instance that is to be
|
||||
@@ -157,8 +155,8 @@ func (n *NodeDestroyResourceInstance) Execute(ctx context.Context, evalCtx EvalC
|
||||
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, traceNameApplyResourceInstance,
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceAttrResourceInstanceAddr, addr.String()),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String(traceAttrResourceInstanceAddr, addr.String()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -172,7 +170,7 @@ func (n *NodeDestroyResourceInstance) Execute(ctx context.Context, evalCtx EvalC
|
||||
return diags
|
||||
}
|
||||
span.SetAttributes(
|
||||
otelAttr.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
traceattrs.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
)
|
||||
diags = diags.Append(
|
||||
n.managedResourceExecute(ctx, evalCtx),
|
||||
|
||||
@@ -11,8 +11,7 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/dag"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
@@ -62,9 +61,9 @@ func (n *NodePlanDestroyableResourceInstance) Execute(ctx context.Context, evalC
|
||||
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, traceNamePlanResourceInstance,
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceAttrResourceInstanceAddr, addr.String()),
|
||||
otelAttr.Bool(traceAttrPlanRefresh, !n.skipRefresh),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String(traceAttrResourceInstanceAddr, addr.String()),
|
||||
traceattrs.Bool(traceAttrPlanRefresh, !n.skipRefresh),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -75,7 +74,7 @@ func (n *NodePlanDestroyableResourceInstance) Execute(ctx context.Context, evalC
|
||||
return diags
|
||||
}
|
||||
span.SetAttributes(
|
||||
otelAttr.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
traceattrs.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
)
|
||||
|
||||
switch addr.Resource.Resource.Mode {
|
||||
|
||||
@@ -15,8 +15,6 @@ import (
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
@@ -28,6 +26,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// NodePlannableResourceInstance represents a _single_ resource
|
||||
@@ -93,10 +92,10 @@ func (n *NodePlannableResourceInstance) Execute(ctx context.Context, evalCtx Eva
|
||||
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, traceNamePlanResourceInstance,
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceAttrResourceInstanceAddr, addr.String()),
|
||||
otelAttr.Bool(traceAttrPlanRefresh, !n.skipRefresh),
|
||||
otelAttr.Bool(traceAttrPlanPlanChanges, !n.skipPlanChanges),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String(traceAttrResourceInstanceAddr, addr.String()),
|
||||
traceattrs.Bool(traceAttrPlanRefresh, !n.skipRefresh),
|
||||
traceattrs.Bool(traceAttrPlanPlanChanges, !n.skipPlanChanges),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -107,7 +106,7 @@ func (n *NodePlannableResourceInstance) Execute(ctx context.Context, evalCtx Eva
|
||||
return diags
|
||||
}
|
||||
span.SetAttributes(
|
||||
otelAttr.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
traceattrs.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
)
|
||||
|
||||
// Eval info is different depending on what kind of resource this is
|
||||
|
||||
@@ -11,8 +11,6 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
@@ -20,6 +18,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// NodePlannableResourceInstanceOrphan represents a resource that is "applyable":
|
||||
@@ -63,10 +62,10 @@ func (n *NodePlannableResourceInstanceOrphan) Execute(ctx context.Context, evalC
|
||||
|
||||
ctx, span := tracing.Tracer().Start(
|
||||
ctx, traceNamePlanResourceInstance,
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceAttrResourceInstanceAddr, addr.String()),
|
||||
otelAttr.Bool(traceAttrPlanRefresh, !n.skipRefresh),
|
||||
otelAttr.Bool(traceAttrPlanPlanChanges, !n.skipPlanChanges),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String(traceAttrResourceInstanceAddr, addr.String()),
|
||||
traceattrs.Bool(traceAttrPlanRefresh, !n.skipRefresh),
|
||||
traceattrs.Bool(traceAttrPlanPlanChanges, !n.skipPlanChanges),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
@@ -82,7 +81,7 @@ func (n *NodePlannableResourceInstanceOrphan) Execute(ctx context.Context, evalC
|
||||
return diags
|
||||
}
|
||||
span.SetAttributes(
|
||||
otelAttr.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
traceattrs.String(traceAttrProviderInstanceAddr, traceProviderInstanceAddr(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)),
|
||||
)
|
||||
diags = diags.Append(
|
||||
n.managedResourceExecute(ctx, evalCtx),
|
||||
|
||||
@@ -12,8 +12,6 @@ import (
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
otelAttr "go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/communicator/shared"
|
||||
@@ -26,6 +24,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/provisioners"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/internal/tracing"
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
// NodeValidatableResource represents a resource that is used for validation
|
||||
@@ -54,8 +53,8 @@ func (n *NodeValidatableResource) Path() addrs.ModuleInstance {
|
||||
func (n *NodeValidatableResource) Execute(ctx context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
|
||||
_, span := tracing.Tracer().Start(
|
||||
ctx, traceNameValidateResource,
|
||||
otelTrace.WithAttributes(
|
||||
otelAttr.String(traceAttrConfigResourceAddr, n.Addr.String()),
|
||||
tracing.SpanAttributes(
|
||||
traceattrs.String(traceAttrConfigResourceAddr, n.Addr.String()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
@@ -15,15 +15,21 @@ import (
|
||||
"go.opentelemetry.io/contrib/exporters/autoexport"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/sdk"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
// This *MUST* always be updated to the latest version when OTEL dependencies are updated in OpenTofu
|
||||
// Failing to do so will prevent OpenTofu from initializing tracing.
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
|
||||
// ---------------------------------------------------------------------
|
||||
// DO NOT IMPORT ANY "go.opentelemetry.io/otel/semconv/*" PACKAGES HERE!
|
||||
// ---------------------------------------------------------------------
|
||||
// Instead, use semconv indirectly through wrappers and reexports in
|
||||
// ./traceattrs/semconv.go, because we need to coordinate our chosen
|
||||
// semconv version with the OTel SDK's "resource" package.
|
||||
|
||||
"github.com/opentofu/opentofu/version"
|
||||
// The version number at the end of this package math MUST match the
|
||||
// semconv version imported by the "go.opentelemetry.io/otel/sdk/resource",
|
||||
// so we will typically need to update this each time we upgrade
|
||||
// the module "go.opentelemetry.io/otel/sdk".
|
||||
|
||||
"github.com/opentofu/opentofu/internal/tracing/traceattrs"
|
||||
)
|
||||
|
||||
/*
|
||||
@@ -107,26 +113,7 @@ func OpenTelemetryInit(ctx context.Context) (context.Context, error) {
|
||||
serviceName = envServiceName
|
||||
}
|
||||
|
||||
otelResource, err := resource.New(context.Background(),
|
||||
// Use built-in detectors to simplify the collation of the racing information
|
||||
resource.WithOS(),
|
||||
resource.WithHost(),
|
||||
resource.WithProcess(),
|
||||
resource.WithSchemaURL(semconv.SchemaURL),
|
||||
resource.WithAttributes(),
|
||||
|
||||
// Add custom service attributes
|
||||
resource.WithAttributes(
|
||||
semconv.ServiceName(serviceName),
|
||||
semconv.ServiceVersion(version.Version),
|
||||
|
||||
// We add in the telemetry SDK information so that we don't end up with
|
||||
// duplicate schema urls that clash
|
||||
semconv.TelemetrySDKName("opentelemetry"),
|
||||
semconv.TelemetrySDKLanguageGo,
|
||||
semconv.TelemetrySDKVersion(sdk.Version()),
|
||||
),
|
||||
)
|
||||
otelResource, err := traceattrs.NewResource(ctx, serviceName)
|
||||
if err != nil {
|
||||
return ctx, fmt.Errorf("failed to create resource: %w", err)
|
||||
}
|
||||
|
||||
42
internal/tracing/traceattrs/generic.go
Normal file
42
internal/tracing/traceattrs/generic.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) The OpenTofu Authors
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) 2023 HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package traceattrs
|
||||
|
||||
import (
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
// String wraps [attribute.String] just so that we can keep most of our direct
|
||||
// OpenTelemetry package imports centralized in this package where it's
|
||||
// easier to keep our version selections consistent.
|
||||
func String(name string, val string) attribute.KeyValue {
|
||||
return attribute.String(name, val)
|
||||
}
|
||||
|
||||
// StringSlice wraps [attribute.StringSlice] just so that we can keep most of
|
||||
// our direct OpenTelemetry package imports centralized in this package where
|
||||
// it's easier to keep our version selections consistent.
|
||||
//
|
||||
// If the items you want to report are not yet assembled into a string slice,
|
||||
// consider using [tracing.StringSlice] with an [iter.Seq[string]] argument
|
||||
// to skip constructing the slice when tracing isn't enabled.
|
||||
func StringSlice(name string, val []string) attribute.KeyValue {
|
||||
return attribute.StringSlice(name, val)
|
||||
}
|
||||
|
||||
// Bool wraps [attribute.Bool] just so that we can keep most of our direct
|
||||
// OpenTelemetry package imports centralized in this package where it's
|
||||
// easier to keep our version selections consistent.
|
||||
func Bool(name string, val bool) attribute.KeyValue {
|
||||
return attribute.Bool(name, val)
|
||||
}
|
||||
|
||||
// Int64 wraps [attribute.Int64] just so that we can keep most of our direct
|
||||
// OpenTelemetry package imports centralized in this package where it's
|
||||
// easier to keep our version selections consistent.
|
||||
func Int64(name string, val int64) attribute.KeyValue {
|
||||
return attribute.Int64(name, val)
|
||||
}
|
||||
82
internal/tracing/traceattrs/opentofu.go
Normal file
82
internal/tracing/traceattrs/opentofu.go
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) The OpenTofu Authors
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) 2023 HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package traceattrs
|
||||
|
||||
import (
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
// This file contains some functions representing OpenTofu-specific semantic
|
||||
// conventions, which we use alongside the general OpenTelemetry-specified
|
||||
// semantic conventions.
|
||||
//
|
||||
// These functions tend to take strings that are expected to be the canonical
|
||||
// string representation of some more specific type from elsewhere in OpenTofu,
|
||||
// but we make the caller produce the string representation rather than doing it
|
||||
// inline because this package needs to avoid importing any other packages
|
||||
// from this codebase so that the rest of OpenTofu can use this package without
|
||||
// creating import cycles.
|
||||
//
|
||||
// We only create functions in here for attribute names that we want to use
|
||||
// consistently across many different callers. For one-off attribute names that
|
||||
// are only used in a single kind of span, use the generic functions like
|
||||
// [String], [StringSlice], etc, instead.
|
||||
|
||||
// OpenTofuProviderAddress returns an attribute definition for indicating
|
||||
// which provider is relevant to a particular trace span.
|
||||
//
|
||||
// The given address should be the result of calling [addrs.Provider.String].
|
||||
func OpenTofuProviderAddress(addr string) attribute.KeyValue {
|
||||
return attribute.String("opentofu.provider.address", addr)
|
||||
}
|
||||
|
||||
// OpenTofuProviderVersion returns an attribute definition for indicating
|
||||
// which version of a provider is relevant to a particular trace span.
|
||||
//
|
||||
// The given address should be the result of calling
|
||||
// [getproviders.Version.String]. This should typically be used alongside
|
||||
// [OpenTofuProviderAddress] to indicate which provider the version number is
|
||||
// for.
|
||||
func OpenTofuProviderVersion(v string) attribute.KeyValue {
|
||||
return attribute.String("opentofu.provider.version", v)
|
||||
}
|
||||
|
||||
// OpenTofuTargetPlatform returns an attribute definition for indicating
|
||||
// which target platform is relevant to a particular trace span.
|
||||
//
|
||||
// The given address should be the result of calling
|
||||
// [getproviders.Platform.String].
|
||||
func OpenTofuTargetPlatform(platform string) attribute.KeyValue {
|
||||
return attribute.String("opentofu.target_platform", platform)
|
||||
}
|
||||
|
||||
// OpenTofuModuleCallName returns an attribute definition for indicating
|
||||
// the name of a module call that's relevant to a particular trace span.
|
||||
//
|
||||
// The given address should be something that would be valid in the
|
||||
// [addrs.ModuleCall.Name] field.
|
||||
func OpenTofuModuleCallName(name string) attribute.KeyValue {
|
||||
return attribute.String("opentofu.module.name", name)
|
||||
}
|
||||
|
||||
// OpenTofuModuleSource returns an attribute definition for indicating
|
||||
// which module source address is relevant to a particular trace span.
|
||||
//
|
||||
// The given address should be the result of calling
|
||||
// [addrs.ModuleSource.String], or any other syntax-compatible representation.
|
||||
func OpenTofuModuleSource(addr string) attribute.KeyValue {
|
||||
return attribute.String("opentofu.module.source", addr)
|
||||
}
|
||||
|
||||
// OpenTofuModuleVersion returns an attribute definition for indicating
|
||||
// which version of a module is relevant to a particular trace span.
|
||||
//
|
||||
// The given address should be either the result of calling
|
||||
// [getproviders.Version.String], or the String method from the "Version" type
|
||||
// from HashiCorp's "go-version" library.
|
||||
func OpenTofuModuleVersion(v string) attribute.KeyValue {
|
||||
return attribute.String("opentofu.module.version", v)
|
||||
}
|
||||
90
internal/tracing/traceattrs/semconv.go
Normal file
90
internal/tracing/traceattrs/semconv.go
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) The OpenTofu Authors
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) 2023 HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package traceattrs
|
||||
|
||||
// This file contains wrappers and reexports of some symbols from the
|
||||
// OpenTelemetry "semconv" package and the "resource" package from the
|
||||
// OpenTelemetry SDK, which we centralize here because their version numbers
|
||||
// must be coordinated carefully to avoid runtime panics of mismatched versions.
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/sdk"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
|
||||
// The version number at the end of this package path MUST match the
|
||||
// semconv version imported by the "go.opentelemetry.io/otel/sdk/resource",
|
||||
// because we also use some semconv symbols indirectly through that
|
||||
// package, and so we need to update this each time we upgrade the module
|
||||
// "go.opentelemetry.io/otel/sdk".
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
|
||||
|
||||
"github.com/opentofu/opentofu/version"
|
||||
)
|
||||
|
||||
// NewResource constructs a *resource.Resource that should be used when
|
||||
// constructing our global tracer provider.
|
||||
//
|
||||
// This is factored out here because its correct behavior depends on correctly
|
||||
// matching our import of an "go.opentelemetry.io/otel/semconv/*" package
|
||||
// for direct attribute definitions with the version used indirectly by
|
||||
// "go.opentelemetry.io/otel/sdk/resource". If they don't match then this
|
||||
// function will fail with an error.
|
||||
//
|
||||
// The unit test [TestNewResource] runs this function in isolation so we can
|
||||
// make sure it succeeds without having to actually initialize the telemetry
|
||||
// system.
|
||||
func NewResource(ctx context.Context, serviceName string) (*resource.Resource, error) {
|
||||
return resource.New(ctx,
|
||||
// Use built-in detectors to simplify the collation of the tracing information
|
||||
resource.WithOS(),
|
||||
resource.WithHost(),
|
||||
resource.WithProcess(),
|
||||
resource.WithSchemaURL(semconv.SchemaURL),
|
||||
resource.WithAttributes(),
|
||||
|
||||
// Add custom service attributes
|
||||
resource.WithAttributes(
|
||||
semconv.ServiceName(serviceName),
|
||||
semconv.ServiceVersion(version.Version),
|
||||
|
||||
// We add in the telemetry SDK information so that we don't end up with
|
||||
// duplicate schema urls that clash
|
||||
semconv.TelemetrySDKName("opentelemetry"),
|
||||
semconv.TelemetrySDKLanguageGo,
|
||||
semconv.TelemetrySDKVersion(sdk.Version()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// URLFull returns an attribute representing an absolute URL associated with
|
||||
// a trace span, using the attribute name defined by our currently-selected
|
||||
// version of the OpenTelemetry semantic conventions.
|
||||
//
|
||||
// This wraps [semconv.URLFull].
|
||||
func URLFull(val string) attribute.KeyValue {
|
||||
return semconv.URLFull(val)
|
||||
}
|
||||
|
||||
// FilePath returns an attribute representing an absolute file path associated
|
||||
// with a trace span, using the attribute name defined by our currently-selected
|
||||
// version of the OpenTelemetry semantic conventions.
|
||||
//
|
||||
// This wraps [semconv.FilePath].
|
||||
func FilePath(val string) attribute.KeyValue {
|
||||
return semconv.FilePath(val)
|
||||
}
|
||||
|
||||
// FileSize returns an attribute representing the size in bytes of a file
|
||||
// associated with a trace span, using the attribute name defined by our
|
||||
// currently-selected version of the OpenTelemetry semantic conventions.
|
||||
//
|
||||
// This wraps [semconv.FileSize].
|
||||
func FileSize(val int) attribute.KeyValue {
|
||||
return semconv.FileSize(val)
|
||||
}
|
||||
18
internal/tracing/traceattrs/semconv_test.go
Normal file
18
internal/tracing/traceattrs/semconv_test.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) The OpenTofu Authors
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) 2023 HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package traceattrs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewResource(t *testing.T) {
|
||||
_, err := NewResource(t.Context(), "test-service")
|
||||
if err != nil {
|
||||
t.Errorf("failed to create OpenTelemetry SDK resource: %s", err)
|
||||
t.Errorf("If the above error message is about conflicting schema versions, then make sure that the semconv package imported in semconv.go matches the semconv package imported by \"go.opentelemetry.io/otel/sdk/resource\".")
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright (c) The OpenTofu Authors
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) 2023 HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package traceattrs
|
||||
|
||||
const (
|
||||
// Common attributes names used across the codebase
|
||||
|
||||
ProviderAddress = "opentofu.provider.address"
|
||||
ProviderVersion = "opentofu.provider.version"
|
||||
|
||||
TargetPlatform = "opentofu.target_platform"
|
||||
|
||||
ModuleCallName = "opentofu.module.name"
|
||||
ModuleSource = "opentofu.module.source"
|
||||
ModuleVersion = "opentofu.module.version"
|
||||
)
|
||||
@@ -14,9 +14,9 @@ import (
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
@@ -119,3 +119,26 @@ func extractImportPath(fullName string) string {
|
||||
|
||||
return fullName[:lastSlash+dotAfterSlash]
|
||||
}
|
||||
|
||||
// Span is an alias for [trace.Span] just to centralize all of our direct
|
||||
// imports of OpenTelemetry packages into our tracing packages, to help
|
||||
// avoid dependency hell.
|
||||
type Span = trace.Span
|
||||
|
||||
// SpanFromContext returns the trace span asssociated with the given context,
|
||||
// or nil if there is no associated span.
|
||||
//
|
||||
// This is a wrapper around [trace.SpanFromContext] just to centralize all of
|
||||
// our imports of OpenTelemetry packages into our tracing packages, to help
|
||||
// avoid dependency hell.
|
||||
func SpanFromContext(ctx context.Context) trace.Span {
|
||||
return trace.SpanFromContext(ctx)
|
||||
}
|
||||
|
||||
// SpanAttributes wraps [trace.WithAttributes] just so that we can minimize
|
||||
// how many different OpenTofu packages directly import the OpenTelemetry
|
||||
// packages, because we tend to need to control which versions we're using
|
||||
// quite closely to avoid dependency hell.
|
||||
func SpanAttributes(attrs ...attribute.KeyValue) trace.SpanStartEventOption {
|
||||
return trace.WithAttributes(attrs...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user