Skip to content

Conversation

@Drjacky
Copy link

@Drjacky Drjacky commented Oct 29, 2025

Problem

Currently, the SDK lacks request correlation capabilities, making it difficult to:

  • Debug production issues by correlating errors with specific API requests
  • Track requests across distributed systems and microservices
  • Provide specific request identifiers to MongoDB support for faster resolution

Solution

Implement request ID propagation that enables distributed tracing through:

  • Automatic X-Request-ID header inclusion from context
  • Enhanced error messages with request context
  • Zero-breaking changes with opt-in functionality

Changes Made

Template and Specification Changes (Source)

  • openapi/atlas-api.yaml - Added x-is-api-error: true vendor extension to ApiError schema
  • tools/config/go-templates/client.mustache - Added request ID header propagation in prepareRequest method
  • tools/config/go-templates/model_simple.mustache - Added GetContextualError method with context imports

Generated Code (Expected Output)

  • admin/client.go - Updated prepareRequest method with request ID handling
  • admin/model_api_error.go - Added GetContextualError method to ApiError struct

Tests

  • admin/client_test.go - Tests for request ID header propagation
  • admin/model_api_error_test.go - Tests for GetContextualError method functionality

Usage

Basic Usage

// Set request ID in context
ctx := context.WithValue(context.Background(), "X-Request-ID", "support-ticket-456")

// All API calls automatically include the request ID header
project, _, err := client.ProjectsApi.GetProject(ctx, "project-id")

// Enhanced error messages include request ID for correlation
if err != nil {
    if apiErr, ok := err.(*admin.ApiError); ok {
        log.Printf("Error: %s", apiErr.GetContextualError(ctx))
        // Output: "404 RESOURCE_NOT_FOUND Project not found (RequestID: support-ticket-456)"
    }
}

Distributed Tracing Example

// In microservice architecture
func handleRequest(w http.ResponseWriter, r *http.Request) {
    // Propagate request ID through your call stack
    requestID := r.Header.Get("X-Request-ID")
    if requestID == "" {
        requestID = generateRequestID()
    }
    
    ctx := context.WithValue(r.Context(), "X-Request-ID", requestID)
    
    // All MongoDB API calls will include the same request ID
    cluster, _, err := client.ClustersApi.CreateCluster(ctx, clusterReq)
    
    if err != nil {
        // Return request ID to client for support tickets
        w.Header().Set("X-Request-ID", requestID)
        w.WriteHeader(500)
        json.NewEncoder(w).Encode(map[string]string{
            "error": "Operation failed",
            "request_id": requestID, // Client can reference this with support
        })
    }
}

Benefits

  • Production Debugging: Correlate errors with specific requests in logs
  • Distributed Tracing: Track requests across microservices and systems
  • Support Efficiency: Provide specific request IDs to MongoDB support
  • Monitoring: Enhanced observability for enterprise deployments
  • Zero Breaking Changes: Fully optional and backward compatible

Generation Note

This PR modifies source templates and specifications. The included Go file changes reflect the expected output from regeneration. After merging, the following regeneration steps are recommended:

  1. Regenerate openapi/atlas-api-transformed.yaml from atlas-api.yaml
  2. Regenerate Go client files from templates and transformed specification

The changes are designed to work with the existing generation pipeline in tools/scripts/generate.sh.

Testing

Comprehensive tests included:

  • Request ID header propagation in HTTP client
  • Error message enhancement with request context
  • Edge cases (empty request IDs, non-string values)
  • Backward compatibility verification

Type of change:

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Required Checklist:

  • I have signed the MongoDB CLA
  • I have added tests that prove my fix is effective or that my feature works
  • I have added any necessary documentation (if appropriate)
  • I have run make fmt and formatted my code

Copilot AI review requested due to automatic review settings October 29, 2025 13:00
@Drjacky Drjacky requested a review from a team as a code owner October 29, 2025 13:00
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds request ID tracking capabilities to the MongoDB Atlas Go SDK to improve debugging and distributed tracing. The implementation uses context propagation to automatically include X-Request-ID headers in API requests and enhance error messages with request context.

Key Changes:

  • Added automatic X-Request-ID header propagation from Go context values
  • Enhanced ApiError with GetContextualError method that includes request IDs in error messages
  • Introduced WithRequestID helper function for ergonomic context management

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
openapi/atlas-api.yaml Added x-is-api-error vendor extension to ApiError schema for template generation
tools/config/go-templates/model_simple.mustache Template modified to generate GetContextualError method for API error types
tools/config/go-templates/client.mustache Template modified to extract and propagate request IDs from context to HTTP headers
admin/model_api_error.go Generated code with GetContextualError method implementation
admin/client.go Generated code with request ID header handling and WithRequestID helper
admin/model_api_error_test.go Unit tests for contextual error formatting
admin/client_test.go Unit tests for request ID header propagation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Member

@AgustinBettati AgustinBettati left a comment

Choose a reason for hiding this comment

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

Hi @Drjacky, thank you for the details and proposed changes.

I would like to gain more context on what value we gain from adding a client defined request-id header to Atlas API. We can continue conversation directly in each comment.

Comment on lines +223 to +232
func (a *ApiError) GetContextualError(ctx context.Context) string {
baseError := a.Error()

// Check if context has request ID
if requestID, ok := ctx.Value("X-Request-ID").(string); ok && requestID != "" {
return fmt.Sprintf("%s (RequestID: %s)", baseError, requestID)
}

return baseError
}
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason we want to place this utility logic within ApiError model? Potentially this can be simplified to a utility function separate from ApiError which simply obtains the RequestID from the Go context.

Copy link
Author

Choose a reason for hiding this comment

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

That's a great point! You're absolutely right that putting this logic in the ApiError model creates unnecessary coupling. A utility function approach would be much cleaner and more reusable.

I can simplify this by:

1- Removing the GetContextualError method from ApiError
2- Adding a simple GetRequestID(ctx) utility function
3- Letting users format the error message with request ID in their logging layer

This keeps the models clean and gives users more flexibility in how they format error messages.

Would you prefer I implement it as a simple GetRequestID(ctx) utility function?

Comment on lines +12 to +13
// Test with request ID in context
ctx := context.WithValue(context.Background(), "X-Request-ID", "test-request-123")
Copy link
Member

Choose a reason for hiding this comment

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

Related to the statement

Provide specific request identifiers to MongoDB support for faster resolution

Has there been a request from the support team to add this information? Do we know if they are capable of leveraging these values/find them useful?

Copy link
Author

Choose a reason for hiding this comment

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

That's a fair question. I made an assumption that support could leverage these values, but I don't have confirmation from the support team or know the right channel to ask them. Could you help me connect with the right people on the support team to get their opinion?

In the meantime, the primary value I see is actually for client-side debugging and tracing in distributed applications. The main benefits would be:

  • Correlating client-side errors with specific API requests in our own logs
  • Tracing requests across microservices in our architecture
  • Better debugging for complex client applications

Would you be able to help me either:

1- Connect with the support team to understand if they'd find client-provided request IDs valuable, or

2- Should we focus on the client-side benefits for now and consider the support angle separately?

I'm happy to adjust the PR based on whatever feedback we get from support.

@Drjacky
Copy link
Author

Drjacky commented Oct 30, 2025

Hi @Drjacky, thank you for the details and proposed changes.

I would like to gain more context on what value we gain from adding a client defined request-id header to Atlas API. We can continue conversation directly in each comment.

The main value is enabling better distributed tracing between client applications and the Atlas API. This allows developers to:

  • Correlate client-side errors with server-side logs
  • Trace requests across service boundaries for debugging
  • Provide specific request IDs to support for faster issue resolution
  • Follow industry-standard practices for request correlation in distributed systems

This is particularly valuable for enterprise applications and complex deployments where understanding the full request flow is crucial for debugging and monitoring.

@AgustinBettati
Copy link
Member

With latest inputs I am seeing the following 2 aspects being handled in this PR:

  1. Include "X-Request-ID" header in Atlas API requests if value is present in Go context.
  2. Provide utility function GetRequestID for obtaining the request id value from a Go context related comment.

For 1 I would not merge this change until we have confirmation from support team that these headers can provide actual value for debugging. Would advise contacting Atlas support directly through their portal https://support.mongodb.com/.

For 2 GetRequestID utility function seems like a more general case function that is not specific to the Atlas Go SDK.

With these considerations I would opt for closing this PR as of now until we receive further inputs from support. Happy to continue the conversation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants