Skip to content
Open
Changes from 1 commit
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
40 changes: 24 additions & 16 deletions examples/cost-analysis-export/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ func ConfigureAndProcess(ctx context.Context, operation string) error {
return fmt.Errorf("invalid config: %w", err)
}

ctx, cancel := context.WithTimeout(ctx, cfg.Timeout)
defer cancel()

app, err := NewApp(cfg)
if err != nil {
return err
Expand Down Expand Up @@ -182,8 +185,9 @@ func (a *App) Export(ctx context.Context) error {
return fmt.Errorf("creating request: %w", err)
}

// Execute request
resp, err := http.DefaultClient.Do(req)
// Execute request with timeout
httpClient := &http.Client{Timeout: 2 * time.Minute}
resp, err := httpClient.Do(req)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Removed the separate http.Client{Timeout: 2m} and reverted to http.DefaultClient. The request already uses NewRequestWithContext(ctx) which carries cfg.Timeout, so the context deadline handles cancellation without a second undocumented knob.

if err != nil {
return fmt.Errorf("failed to reach cost analysis service: %w", err)
}
Expand Down Expand Up @@ -461,6 +465,10 @@ func (a *App) joinAndExportData(ctx context.Context) error {
if err != nil {
return fmt.Errorf("joining data: %w", err)
}
defer func() {
_ = file.Close()
_ = os.Remove(file.Name())
}()
slog.Info("data joined successfully", "file", file.Name())

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not an issue here. JoinData() already seeks back to position 0 before returning (line 812: tmpFile.Seek(0, 0)), so the file handle is at the start when UploadFile receives it. The Azure SDK's UploadFile also takes an *os.File and handles positioning internally.

contentType := "text/csv"
Expand Down Expand Up @@ -648,21 +656,21 @@ func stripBOMReader(r io.Reader) io.Reader {
// - MCA: https://learn.microsoft.com/en-us/azure/cost-management-billing/dataset-schema/cost-usage-details-mca
// - FOCUS: https://learn.microsoft.com/en-us/azure/cost-management-billing/dataset-schema/cost-usage-details-focus
var columnsToMultiply = map[string]bool{
"PreTaxCost": true,
"CostInBillingCurrency": true,
"costInBillingCurrency": true,
"BilledCost": true,
"EffectiveCost": true,
"ListCost": true,
"ContractedCost": true,
"costInUsd": true,
"PreTaxCost": true,
"CostInBillingCurrency": true,
"costInBillingCurrency": true,
"BilledCost": true,
"EffectiveCost": true,
"ListCost": true,
"ContractedCost": true,
"costInUsd": true,
"paygCostInBillingCurrency": true,
"paygCostInUsd": true,
"UsageQuantity": true,
"Quantity": true,
"quantity": true,
"ConsumedQuantity": true,
"PricingQuantity": true,
"paygCostInUsd": true,
"UsageQuantity": true,
"Quantity": true,
"quantity": true,
"ConsumedQuantity": true,
"PricingQuantity": true,
}

// resourceIDColumns lists possible column names for resource ID.
Expand Down
Loading