Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .vscode/cspell.misc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ overrides:
words:
- MSRC
- msrc
- filename: ./docs/specs/metrics-audit/**
words:
- vsrpc
- Buildpacks
- devdeviceid
- appinit
- oneauth
- dashboarding
- Pseudonymized
- pseudonymized
- unhashed
- countif
- Angelos
- Entra
- CODEOWNERS
- weikanglim
- filename: ./README.md
words:
- VSIX
Expand Down
18 changes: 18 additions & 0 deletions cli/azd/cmd/auth_login.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"github.com/azure/azure-dev/cli/azd/cmd/actions"
"github.com/azure/azure-dev/cli/azd/internal"
"github.com/azure/azure-dev/cli/azd/internal/runcontext"
"github.com/azure/azure-dev/cli/azd/internal/tracing"
"github.com/azure/azure-dev/cli/azd/internal/tracing/fields"
"github.com/azure/azure-dev/cli/azd/pkg/account"
"github.com/azure/azure-dev/cli/azd/pkg/auth"
"github.com/azure/azure-dev/cli/azd/pkg/contracts"
Expand Down Expand Up @@ -307,6 +309,7 @@ func (la *loginAction) Run(ctx context.Context) (*actions.ActionResult, error) {
}

if la.flags.onlyCheckStatus {
tracing.SetUsageAttributes(fields.AuthMethodKey.String("check-status"))
// In check status mode, we always print the final status to stdout.
// We print any non-setup related errors to stderr.
// We always return a zero exit code.
Expand Down Expand Up @@ -452,6 +455,11 @@ func runningOnCodespacesBrowser(ctx context.Context, commandRunner exec.CommandR
}

func (la *loginAction) login(ctx context.Context) error {
// Track tenant ID if provided (before resolving from env vars)
if la.flags.tenantID != "" {
tracing.SetUsageAttributes(fields.TenantIdKey.String(la.flags.tenantID))
}

if la.flags.federatedTokenProvider == azurePipelinesProvider {
if la.flags.clientID == "" {
log.Printf("setting client id from environment variable %s", azurePipelinesClientIDEnvVarName)
Expand All @@ -465,6 +473,7 @@ func (la *loginAction) login(ctx context.Context) error {
}

if la.flags.managedIdentity {
tracing.SetUsageAttributes(fields.AuthMethodKey.String("managed-identity"))
if _, err := la.authManager.LoginWithManagedIdentity(
ctx, la.flags.clientID,
); err != nil {
Expand Down Expand Up @@ -494,6 +503,7 @@ func (la *loginAction) login(ctx context.Context) error {

switch {
case la.flags.clientSecret.ptr != nil:
tracing.SetUsageAttributes(fields.AuthMethodKey.String("service-principal-secret"))
if *la.flags.clientSecret.ptr == "" {
v, err := la.console.Prompt(ctx, input.ConsoleOptions{
Message: "Enter your client secret",
Expand All @@ -510,6 +520,7 @@ func (la *loginAction) login(ctx context.Context) error {
return fmt.Errorf("logging in: %w", err)
}
case la.flags.clientCertificate != "":
tracing.SetUsageAttributes(fields.AuthMethodKey.String("service-principal-certificate"))
certFile, err := os.Open(la.flags.clientCertificate)
if err != nil {
return fmt.Errorf("reading certificate: %w", err)
Expand All @@ -527,12 +538,14 @@ func (la *loginAction) login(ctx context.Context) error {
return fmt.Errorf("logging in: %w", err)
}
case la.flags.federatedTokenProvider == "github":
tracing.SetUsageAttributes(fields.AuthMethodKey.String("federated-github"))
if _, err := la.authManager.LoginWithGitHubFederatedTokenProvider(
ctx, la.flags.tenantID, la.flags.clientID,
); err != nil {
return fmt.Errorf("logging in: %w", err)
}
case la.flags.federatedTokenProvider == azurePipelinesProvider:
tracing.SetUsageAttributes(fields.AuthMethodKey.String("federated-azure-pipelines"))
serviceConnectionID := os.Getenv(azurePipelinesServiceConnectionIDEnvVarName)

if serviceConnectionID == "" {
Expand All @@ -546,6 +559,7 @@ func (la *loginAction) login(ctx context.Context) error {
return fmt.Errorf("logging in: %w", err)
}
case la.flags.federatedTokenProvider == "oidc": // generic oidc provider
tracing.SetUsageAttributes(fields.AuthMethodKey.String("federated-oidc"))
if _, err := la.authManager.LoginWithOidcFederatedTokenProvider(
ctx, la.flags.tenantID, la.flags.clientID,
); err != nil {
Expand All @@ -557,6 +571,7 @@ func (la *loginAction) login(ctx context.Context) error {
}

if la.authManager.UseExternalAuth() {
tracing.SetUsageAttributes(fields.AuthMethodKey.String("external"))
// Request a token and assume the external auth system will prompt the user to log in.
//
// TODO(ellismg): We may want instead to call some explicit `/login` endpoint on the external auth system instead
Expand All @@ -581,6 +596,7 @@ func (la *loginAction) login(ctx context.Context) error {
}

if useDevCode {
tracing.SetUsageAttributes(fields.AuthMethodKey.String("device-code"))
_, err = la.authManager.LoginWithDeviceCode(ctx, la.flags.tenantID, la.flags.scopes, claims,
func(url string) error {
if !la.flags.global.NoPrompt {
Expand All @@ -598,8 +614,10 @@ func (la *loginAction) login(ctx context.Context) error {
}

if oneauth.Supported && !la.flags.browser {
tracing.SetUsageAttributes(fields.AuthMethodKey.String("oneauth"))
err = la.authManager.LoginWithOneAuth(ctx, la.flags.tenantID, la.flags.scopes)
} else {
tracing.SetUsageAttributes(fields.AuthMethodKey.String("browser"))
_, err = la.authManager.LoginInteractive(ctx, la.flags.scopes, claims,
&auth.LoginInteractiveOptions{
TenantID: la.flags.tenantID,
Expand Down
4 changes: 4 additions & 0 deletions cli/azd/cmd/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/azure/azure-dev/cli/azd/cmd/actions"
"github.com/azure/azure-dev/cli/azd/internal"
"github.com/azure/azure-dev/cli/azd/internal/tracing"
"github.com/azure/azure-dev/cli/azd/internal/tracing/fields"
"github.com/azure/azure-dev/cli/azd/pkg/account"
"github.com/azure/azure-dev/cli/azd/pkg/alpha"
"github.com/azure/azure-dev/cli/azd/pkg/azapi"
Expand Down Expand Up @@ -874,6 +876,8 @@ func (e *envListAction) Run(ctx context.Context) (*actions.ActionResult, error)
return nil, fmt.Errorf("listing environments: %w", err)
}

tracing.SetUsageAttributes(fields.EnvCountKey.Int(len(envs)))

if e.formatter.Kind() == output.TableFormat {
columns := []output.Column{
{
Expand Down
39 changes: 39 additions & 0 deletions cli/azd/cmd/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (

"github.com/azure/azure-dev/cli/azd/cmd/actions"
"github.com/azure/azure-dev/cli/azd/internal"
"github.com/azure/azure-dev/cli/azd/internal/tracing"
"github.com/azure/azure-dev/cli/azd/internal/tracing/fields"
"github.com/azure/azure-dev/cli/azd/pkg/environment"
"github.com/azure/azure-dev/cli/azd/pkg/exec"
"github.com/azure/azure-dev/cli/azd/pkg/ext"
Expand Down Expand Up @@ -115,9 +117,46 @@ const (
hookContextService hookContextType = "service"
)

// knownHookNames is the set of built-in azd hook names.
// Extension-defined hooks are not included here; they are hashed in telemetry.
// See https://github.com/Azure/azure-dev/issues/7348 for tracking.
var knownHookNames = map[string]bool{
"prebuild": true,
"postbuild": true,
"predeploy": true,
"postdeploy": true,
"predown": true,
"postdown": true,
"prepackage": true,
"postpackage": true,
"preprovision": true,
"postprovision": true,
"prepublish": true,
"postpublish": true,
"prerestore": true,
"postrestore": true,
"preup": true,
"postup": true,
}

func (hra *hooksRunAction) Run(ctx context.Context) (*actions.ActionResult, error) {
hookName := hra.args[0]

hookType := "project"
if hra.flags.service != "" {
hookType = "service"
}

// Log known hook names raw; hash unknown names to avoid logging arbitrary user input.
hookNameAttr := fields.StringHashed(fields.HooksNameKey, hookName)
if knownHookNames[hookName] {
hookNameAttr = fields.HooksNameKey.String(hookName)
}
tracing.SetUsageAttributes(
hookNameAttr,
fields.HooksTypeKey.String(hookType),
)

// Command title
hra.console.MessageUxItem(ctx, &ux.MessageTitle{
Title: "Running hooks (azd hooks run)",
Expand Down
12 changes: 12 additions & 0 deletions cli/azd/cmd/infra_generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (

"github.com/azure/azure-dev/cli/azd/cmd/actions"
"github.com/azure/azure-dev/cli/azd/internal"
"github.com/azure/azure-dev/cli/azd/internal/tracing"
"github.com/azure/azure-dev/cli/azd/internal/tracing/fields"
"github.com/azure/azure-dev/cli/azd/pkg/alpha"
"github.com/azure/azure-dev/cli/azd/pkg/environment/azdcontext"
"github.com/azure/azure-dev/cli/azd/pkg/input"
Expand Down Expand Up @@ -85,6 +87,16 @@ func newInfraGenerateAction(
}

func (a *infraGenerateAction) Run(ctx context.Context) (*actions.ActionResult, error) {
// Track infra provider from project configuration
// Emit "auto" when provider is empty, so we know auto-detection was used.
if a.projectConfig != nil {
provider := string(a.projectConfig.Infra.Provider)
if provider == "" {
provider = "auto"
}
tracing.SetUsageAttributes(fields.InfraProviderKey.String(provider))
}

if a.calledAs == "synth" {
fmt.Fprintln(
a.console.Handles().Stderr,
Expand Down
9 changes: 9 additions & 0 deletions cli/azd/cmd/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/MakeNowJust/heredoc/v2"
"github.com/azure/azure-dev/cli/azd/cmd/actions"
"github.com/azure/azure-dev/cli/azd/internal"
"github.com/azure/azure-dev/cli/azd/internal/tracing"
"github.com/azure/azure-dev/cli/azd/internal/tracing/fields"
"github.com/azure/azure-dev/cli/azd/pkg/alpha"
"github.com/azure/azure-dev/cli/azd/pkg/environment"
"github.com/azure/azure-dev/cli/azd/pkg/infra/provisioning"
Expand Down Expand Up @@ -170,6 +172,13 @@ func (p *pipelineConfigAction) Run(ctx context.Context) (*actions.ActionResult,

// Command title
pipelineProviderName := p.manager.CiProviderName()

// Track the resolved pipeline provider (after CiProviderName resolves auto-detection).
// cmd.flags already indicates whether --provider was explicitly set by the user.
tracing.SetUsageAttributes(fields.PipelineProviderKey.String(pipelineProviderName))
if p.flags.PipelineAuthTypeName != "" {
tracing.SetUsageAttributes(fields.PipelineAuthKey.String(p.flags.PipelineAuthTypeName))
}
p.console.MessageUxItem(ctx, &ux.MessageTitle{
Title: fmt.Sprintf("Configure your %s pipeline", pipelineProviderName),
})
Expand Down
Loading
Loading