Ver Fonte

Add telemetry to all metronome methods and endpoints

Mauricio Araujo há 2 anos atrás
pai
commit
d231d5d9ab

+ 1 - 1
api/server/handlers/billing/credits.go

@@ -42,7 +42,7 @@ func (c *GetCreditsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	credits, err := c.Config().BillingManager.MetronomeClient.GetCustomerCredits(proj.UsageID)
+	credits, err := c.Config().BillingManager.MetronomeClient.GetCustomerCredits(ctx, proj.UsageID)
 	if err != nil {
 		err := telemetry.Error(ctx, span, err, "error getting credits")
 		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))

+ 1 - 1
api/server/handlers/billing/list.go

@@ -86,7 +86,7 @@ func (c *CheckPaymentEnabledHandler) ServeHTTP(w http.ResponseWriter, r *http.Re
 
 	if c.Config().ServerConf.MetronomeAPIKey != "" && c.Config().ServerConf.PorterCloudPlanID != "" &&
 		proj.GetFeatureFlag(models.MetronomeEnabled, c.Config().LaunchDarklyClient) && proj.UsageID == uuid.Nil {
-		customerID, customerPlanID, err := c.Config().BillingManager.MetronomeClient.CreateCustomerWithPlan(user.CompanyName, proj.Name, proj.ID, proj.BillingID, c.Config().ServerConf.PorterCloudPlanID)
+		customerID, customerPlanID, err := c.Config().BillingManager.MetronomeClient.CreateCustomerWithPlan(ctx, user.CompanyName, proj.Name, proj.ID, proj.BillingID, c.Config().ServerConf.PorterCloudPlanID)
 		if err != nil {
 			err = telemetry.Error(ctx, span, err, "error creating Metronome customer")
 			c.HandleAPIError(w, r, apierrors.NewErrInternal(err))

+ 1 - 1
api/server/handlers/project/create.go

@@ -99,7 +99,7 @@ func (p *ProjectCreateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 
 	// Create Metronome customer and add to starter plan
 	if p.Config().ServerConf.MetronomeAPIKey != "" && p.Config().ServerConf.PorterCloudPlanID != "" && proj.GetFeatureFlag(models.MetronomeEnabled, p.Config().LaunchDarklyClient) {
-		customerID, customerPlanID, err := p.Config().BillingManager.MetronomeClient.CreateCustomerWithPlan(user.CompanyName, proj.Name, proj.ID, proj.BillingID, p.Config().ServerConf.PorterCloudPlanID)
+		customerID, customerPlanID, err := p.Config().BillingManager.MetronomeClient.CreateCustomerWithPlan(ctx, user.CompanyName, proj.Name, proj.ID, proj.BillingID, p.Config().ServerConf.PorterCloudPlanID)
 		if err != nil {
 			err = telemetry.Error(ctx, span, err, "error creating Metronome customer")
 			p.HandleAPIError(w, r, apierrors.NewErrInternal(err))

+ 6 - 1
api/server/handlers/project/delete.go

@@ -94,13 +94,18 @@ func (p *ProjectDeleteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 
 	if p.Config().ServerConf.MetronomeAPIKey != "" && p.Config().ServerConf.PorterCloudPlanID != "" &&
 		proj.GetFeatureFlag(models.MetronomeEnabled, p.Config().LaunchDarklyClient) {
-		err = p.Config().BillingManager.MetronomeClient.EndCustomerPlan(proj.UsageID, proj.UsagePlanID)
+		err = p.Config().BillingManager.MetronomeClient.EndCustomerPlan(ctx, proj.UsageID, proj.UsagePlanID)
 		if err != nil {
 			e := "error ending billing plan"
 			err = telemetry.Error(ctx, span, err, e)
 			p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
 			return
 		}
+		telemetry.WithAttributes(span,
+			telemetry.AttributeKV{Key: "project-id", Value: proj.ID},
+			telemetry.AttributeKV{Key: "usage-id", Value: proj.UsageID},
+			telemetry.AttributeKV{Key: "usage-plan-id", Value: proj.UsagePlanID},
+		)
 	}
 
 	deletedProject, err := p.Repo().Project().DeleteProject(proj)

+ 33 - 16
internal/billing/metronome.go

@@ -2,6 +2,7 @@ package billing
 
 import (
 	"bytes"
+	"context"
 	"encoding/json"
 	"fmt"
 	"net/http"
@@ -11,6 +12,7 @@ import (
 
 	"github.com/google/uuid"
 	"github.com/porter-dev/porter/api/types"
+	"github.com/porter-dev/porter/internal/telemetry"
 )
 
 const (
@@ -34,7 +36,10 @@ func NewMetronomeClient(metronomeApiKey string) MetronomeClient {
 }
 
 // createCustomer will create the customer in Metronome
-func (m MetronomeClient) createCustomer(orgName string, projectName string, projectID uint, billingID string) (customerID uuid.UUID, err error) {
+func (m MetronomeClient) createCustomer(ctx context.Context, orgName string, projectName string, projectID uint, billingID string) (customerID uuid.UUID, err error) {
+	ctx, span := telemetry.NewSpan(ctx, "create-metronome-customer")
+	defer span.End()
+
 	path := "customers"
 	projIDStr := strconv.FormatUint(uint64(projectID), 10)
 
@@ -56,15 +61,18 @@ func (m MetronomeClient) createCustomer(orgName string, projectName string, proj
 
 	err = post(path, m.ApiKey, customer, &result)
 	if err != nil {
-		return customerID, err
+		return customerID, telemetry.Error(ctx, span, err, "error creating customer")
 	}
 	return result.Data.ID, nil
 }
 
 // addCustomerPlan will start the customer on the given plan
-func (m MetronomeClient) addCustomerPlan(customerID uuid.UUID, planID uuid.UUID) (customerPlanID uuid.UUID, err error) {
+func (m MetronomeClient) addCustomerPlan(ctx context.Context, customerID uuid.UUID, planID uuid.UUID) (customerPlanID uuid.UUID, err error) {
+	ctx, span := telemetry.NewSpan(ctx, "add-metronome-customer-plan")
+	defer span.End()
+
 	if customerID == uuid.Nil || planID == uuid.Nil {
-		return customerPlanID, fmt.Errorf("customer or plan id empty")
+		return customerPlanID, telemetry.Error(ctx, span, err, "customer or plan id empty")
 	}
 
 	path := fmt.Sprintf("/customers/%s/plans/add", customerID)
@@ -87,33 +95,39 @@ func (m MetronomeClient) addCustomerPlan(customerID uuid.UUID, planID uuid.UUID)
 
 	err = post(path, m.ApiKey, req, &result)
 	if err != nil {
-		return customerPlanID, err
+		return customerPlanID, telemetry.Error(ctx, span, err, "failed to add customer to plan")
 	}
 
 	return result.Data.CustomerPlanID, nil
 }
 
 // CreateCustomerWithPlan will create the customer in Metronome and immediately add it to the plan
-func (m MetronomeClient) CreateCustomerWithPlan(orgName string, projectName string, projectID uint, billingID string, planID string) (customerID uuid.UUID, customerPlanID uuid.UUID, err error) {
+func (m MetronomeClient) CreateCustomerWithPlan(ctx context.Context, orgName string, projectName string, projectID uint, billingID string, planID string) (customerID uuid.UUID, customerPlanID uuid.UUID, err error) {
+	ctx, span := telemetry.NewSpan(ctx, "add-metronome-customer-plan")
+	defer span.End()
+
 	porterCloudPlanID, err := uuid.Parse(planID)
 	if err != nil {
-		return customerID, customerPlanID, fmt.Errorf("error parsing starter plan id: %w", err)
+		return customerID, customerPlanID, telemetry.Error(ctx, span, err, "error parsing starter plan id")
 	}
 
-	customerID, err = m.createCustomer(orgName, projectName, projectID, billingID)
+	customerID, err = m.createCustomer(ctx, orgName, projectName, projectID, billingID)
 	if err != nil {
-		return customerID, customerPlanID, err
+		return customerID, customerPlanID, telemetry.Error(ctx, span, err, "error while creatinc customer with plan")
 	}
 
-	customerPlanID, err = m.addCustomerPlan(customerID, porterCloudPlanID)
+	customerPlanID, err = m.addCustomerPlan(ctx, customerID, porterCloudPlanID)
 
 	return customerID, customerPlanID, err
 }
 
 // EndCustomerPlan will immediately end the plan for the given customer
-func (m MetronomeClient) EndCustomerPlan(customerID uuid.UUID, customerPlanID uuid.UUID) (err error) {
+func (m MetronomeClient) EndCustomerPlan(ctx context.Context, customerID uuid.UUID, customerPlanID uuid.UUID) (err error) {
+	ctx, span := telemetry.NewSpan(ctx, "end-metronome-customer-plan")
+	defer span.End()
+
 	if customerID == uuid.Nil || customerPlanID == uuid.Nil {
-		return fmt.Errorf("customer or customer plan id empty")
+		return telemetry.Error(ctx, span, err, "customer or customer plan id empty")
 	}
 
 	path := fmt.Sprintf("/customers/%s/plans/%s/end", customerID, customerPlanID)
@@ -129,16 +143,19 @@ func (m MetronomeClient) EndCustomerPlan(customerID uuid.UUID, customerPlanID uu
 
 	err = post(path, m.ApiKey, req, nil)
 	if err != nil {
-		return err
+		return telemetry.Error(ctx, span, err, "failed to end customer plan")
 	}
 
 	return nil
 }
 
 // GetCustomerCredits will return the first credit grant for the customer
-func (m MetronomeClient) GetCustomerCredits(customerID uuid.UUID) (credits int64, err error) {
+func (m MetronomeClient) GetCustomerCredits(ctx context.Context, customerID uuid.UUID) (credits int64, err error) {
+	ctx, span := telemetry.NewSpan(ctx, "get-customer-credits")
+	defer span.End()
+
 	if customerID == uuid.Nil {
-		return credits, fmt.Errorf("customer id empty")
+		return credits, telemetry.Error(ctx, span, err, "customer id empty")
 	}
 
 	path := "credits/listGrants"
@@ -155,7 +172,7 @@ func (m MetronomeClient) GetCustomerCredits(customerID uuid.UUID) (credits int64
 
 	err = post(path, m.ApiKey, req, &result)
 	if err != nil {
-		return credits, err
+		return credits, telemetry.Error(ctx, span, err, "failed to get customer credits")
 	}
 
 	return result.Data[0].Balance.IncludingPending, nil