Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refine metrics #613

Merged
merged 1 commit into from
Dec 13, 2024
Merged

feat: refine metrics #613

merged 1 commit into from
Dec 13, 2024

Conversation

gfyrag
Copy link
Contributor

@gfyrag gfyrag commented Dec 11, 2024

No description provided.

@gfyrag gfyrag requested a review from a team as a code owner December 11, 2024 11:07
Copy link

coderabbitai bot commented Dec 11, 2024

Walkthrough

The changes introduced in this pull request enhance the telemetry capabilities of the application by integrating OpenTelemetry for tracing and metrics. The ControllerWithTraces struct in the ledger controller has been modified to include multiple histogram fields for performance tracking. The DefaultController struct in the system controller has transitioned to using provider patterns for tracer and meter management. Additionally, the NewFXModule function has updated its parameter names to reflect these changes. Overall, these modifications improve the control flow and instrumentation for performance measurement.

Changes

File Path Change Summary
internal/controller/ledger/controller_with_traces.go - Expanded ControllerWithTraces struct with multiple metric.Int64Histogram fields.
- Updated NewControllerWithTraces to accept meter metric.Meter.
- Modified various methods to utilize tracing.TraceWithMetric.
internal/controller/system/controller.go - Updated DefaultController struct to use tracerProvider and meterProvider.
- Adjusted methods to instantiate tracers using the new provider.
- Renamed WithMeter and WithTracer to WithMeterProvider and WithTracerProvider.
internal/controller/system/module.go - Renamed parameters in NewFXModule from WithMeter to WithMeterProvider and WithTracer to WithTracerProvider.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ControllerWithTraces
    participant MetricsProvider

    User->>ControllerWithTraces: Call Method (e.g., BeginTX)
    ControllerWithTraces->>MetricsProvider: Start Histogram Tracking
    MetricsProvider-->>ControllerWithTraces: Return Histogram
    ControllerWithTraces->>ControllerWithTraces: Perform Operation
    ControllerWithTraces->>MetricsProvider: Stop Histogram Tracking
    MetricsProvider-->>ControllerWithTraces: Log Metrics
Loading

🐰 "In the ledger, we now trace,
With metrics to keep up the pace.
Hopping through code, we measure and log,
A performance boost, like a swift little frog!
With providers in tow, we leap and we bound,
In the world of telemetry, joy can be found!" 🐇


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Experiment)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (2)
internal/controller/ledger/controller_with_traces.go (2)

50-53: Avoid panicking on histogram initialization errors

Using panic for error handling may cause the entire application to crash. Consider returning an error to handle histogram initialization failures gracefully.

Modify the constructor to return an error:

-func NewControllerWithTraces(underlying Controller, tracer trace.Tracer, meter metric.Meter) *ControllerWithTraces {
+func NewControllerWithTraces(underlying Controller, tracer trace.Tracer, meter metric.Meter) (*ControllerWithTraces, error) {
    ret := &ControllerWithTraces{
        underlying: underlying,
        tracer:     tracer,
    }
 
    var err error
    ret.beginTxHistogram, err = meter.Int64Histogram("BeginTX")
    if err != nil {
-       panic(err)
+       return nil, fmt.Errorf("failed to create histogram 'BeginTX': %w", err)
    }
    // ... repeat for other histograms
-   return ret
+   return ret, nil
}

Update the calls to NewControllerWithTraces to handle the possible error.


49-138: Refactor histogram initialization to reduce duplication

The repetitive initialization of histograms can be refactored to improve maintainability and reduce potential errors.

Example refactor:

operationNames := []struct {
    name       string
    histogram *metric.Int64Histogram
}{
    {"BeginTX", &ret.beginTxHistogram},
    {"Commit", &ret.commitHistogram},
    {"Rollback", &ret.rollbackHistogram},
    // ... add other operations
}

for _, op := range operationNames {
    *op.histogram, err = meter.Int64Histogram(op.name)
    if err != nil {
        return nil, fmt.Errorf("failed to create histogram '%s': %w", op.name, err)
    }
}

This approach reduces code duplication and simplifies the addition of new histograms.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between c8a3f5b and 1da836b.

📒 Files selected for processing (3)
  • internal/controller/ledger/controller_with_traces.go (2 hunks)
  • internal/controller/system/controller.go (7 hunks)
  • internal/controller/system/module.go (1 hunks)
🔇 Additional comments (11)
internal/controller/system/controller.go (10)

6-6: Importing OpenTelemetry attribute package

The addition of "go.opentelemetry.io/otel/attribute" is necessary for using OpenTelemetry attributes and enhances telemetry capabilities.


42-43: Replacing tracer and meter with provider patterns

Updating the DefaultController struct to use tracerProvider and meterProvider aligns with OpenTelemetry best practices and promotes consistent management of tracing and metrics.


48-48: Initializing tracer with provider in GetLedgerController

The use of ctrl.tracerProvider.Tracer("system") correctly initializes a tracer for the "system" instrumentation scope.


54-64: Initializing meter and tracer with instrumentation attributes

The code properly initializes meter and tracer with instrumentation attributes using the ledger name, enhancing observability and aligning with OpenTelemetry standards.


69-69: Passing meter to NewDefaultController

By passing the meter to ledgercontroller.NewDefaultController, the code enables metric collection within the ledger controller.


75-75: Passing tracer to NewControllerWithTooManyClientHandling

The tracer is correctly passed to enhance tracing capabilities in client handling.


89-89: Enhancing controller with traces and metrics

Wrapping the ledgerController with NewControllerWithTraces and providing both tracer and meter integrates tracing and metrics seamlessly.


170-172: Adding WithMeterProvider option

The WithMeterProvider function correctly allows setting the meterProvider in the DefaultController, following the options pattern and enhancing configurability.


176-178: Adding WithTracerProvider option

The WithTracerProvider function correctly sets the tracerProvider in the DefaultController, promoting consistent tracing configuration.


189-190: Setting default no-op providers

Assigning noopmetrics.MeterProvider{} and nooptracer.TracerProvider{} as defaults ensures the controller functions correctly even when no providers are explicitly supplied.

internal/controller/system/module.go (1)

51-52: Renaming parameters to WithMeterProvider and WithTracerProvider

Updating the parameter names enhances clarity by indicating that provider instances are being supplied, promoting consistency across the codebase.

Comment on lines 163 to 171
return tracing.SkipResult(tracing.TraceWithMetric(
ctx,
"BeginTX",
c.tracer,
c.commitHistogram,
tracing.NoResult(func(ctx context.Context) error {
return c.underlying.Commit(ctx)
}),
))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Incorrect operation name in Commit method tracing

In the Commit method, the operation name passed to tracing.TraceWithMetric is "BeginTX". It should be "Commit" to reflect the actual operation.

Apply this diff to correct the operation name:

 return tracing.SkipResult(tracing.TraceWithMetric(
     ctx,
-    "BeginTX",
+    "Commit",
     c.tracer,
     c.commitHistogram,
     tracing.NoResult(func(ctx context.Context) error {
         return c.underlying.Commit(ctx)
     }),
 ))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return tracing.SkipResult(tracing.TraceWithMetric(
ctx,
"BeginTX",
c.tracer,
c.commitHistogram,
tracing.NoResult(func(ctx context.Context) error {
return c.underlying.Commit(ctx)
}),
))
return tracing.SkipResult(tracing.TraceWithMetric(
ctx,
"Commit",
c.tracer,
c.commitHistogram,
tracing.NoResult(func(ctx context.Context) error {
return c.underlying.Commit(ctx)
}),
))

Comment on lines 364 to 381
ctx,
"CreateTransaction",
c.tracer,
c.revertTransactionHistogram,
func(ctx context.Context) (any, error) {
log, revertedTransaction, err = c.underlying.RevertTransaction(ctx, parameters)
return nil, err
},
)
if err != nil {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Incorrect operation name in RevertTransaction method tracing

In the RevertTransaction method, the operation name is set to "CreateTransaction". It should be "RevertTransaction" to match the method's purpose.

Apply this diff to correct the operation name:

 _, err = tracing.TraceWithMetric(
     ctx,
-    "CreateTransaction",
+    "RevertTransaction",
     c.tracer,
     c.revertTransactionHistogram,
     func(ctx context.Context) (any, error) {
         log, revertedTransaction, err = c.underlying.RevertTransaction(ctx, parameters)
         return nil, err
     },
 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ctx,
"CreateTransaction",
c.tracer,
c.revertTransactionHistogram,
func(ctx context.Context) (any, error) {
log, revertedTransaction, err = c.underlying.RevertTransaction(ctx, parameters)
return nil, err
},
)
if err != nil {
ctx,
"RevertTransaction",
c.tracer,
c.revertTransactionHistogram,
func(ctx context.Context) (any, error) {
log, revertedTransaction, err = c.underlying.RevertTransaction(ctx, parameters)
return nil, err
},
)
if err != nil {

commitHistogram metric.Int64Histogram
rollbackHistogram metric.Int64Histogram
listTransactionsHistogram metric.Int64Histogram
countTransactions metric.Int64Histogram
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Inconsistent naming of countTransactions histogram field

The field countTransactions should be renamed to countTransactionsHistogram to maintain consistency with other histogram fields.

Apply this diff to rename the field:

-countTransactions                  metric.Int64Histogram
+countTransactionsHistogram         metric.Int64Histogram

Also, update all references to this field in the code.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
countTransactions metric.Int64Histogram
countTransactionsHistogram metric.Int64Histogram

Comment on lines 175 to 183
return tracing.SkipResult(tracing.TraceWithMetric(
ctx,
"BeginTX",
c.tracer,
c.rollbackHistogram,
tracing.NoResult(func(ctx context.Context) error {
return c.underlying.Rollback(ctx)
}),
))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Incorrect operation name in Rollback method tracing

In the Rollback method, the operation name is mistakenly set to "BeginTX". It should be "Rollback" to accurately represent the operation.

Apply this diff to correct the operation name:

 return tracing.SkipResult(tracing.TraceWithMetric(
     ctx,
-    "BeginTX",
+    "Rollback",
     c.tracer,
     c.rollbackHistogram,
     tracing.NoResult(func(ctx context.Context) error {
         return c.underlying.Rollback(ctx)
     }),
 ))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return tracing.SkipResult(tracing.TraceWithMetric(
ctx,
"BeginTX",
c.tracer,
c.rollbackHistogram,
tracing.NoResult(func(ctx context.Context) error {
return c.underlying.Rollback(ctx)
}),
))
return tracing.SkipResult(tracing.TraceWithMetric(
ctx,
"Rollback",
c.tracer,
c.rollbackHistogram,
tracing.NoResult(func(ctx context.Context) error {
return c.underlying.Rollback(ctx)
}),
))

Copy link
Contributor

@paul-nicolas paul-nicolas left a comment

Choose a reason for hiding this comment

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

LGTM

@gfyrag gfyrag force-pushed the feat/refine-metrics branch from 1da836b to 39006e6 Compare December 11, 2024 11:30
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (1)
internal/controller/ledger/controller_with_traces.go (1)

343-362: Standardize error handling pattern

The error handling pattern varies across methods. Some use intermediate variables while others return directly.

Consider standardizing to the simpler direct return pattern:

-var (
-       createdTransaction *ledger.CreatedTransaction
-       log                *ledger.Log
-       err                error
-)
-_, err = tracing.TraceWithMetric(
+return tracing.TraceWithMetric(
        ctx,
        "CreateTransaction",
        c.tracer,
        c.createTransactionHistogram,
-       func(ctx context.Context) (any, error) {
-               log, createdTransaction, err = c.underlying.CreateTransaction(ctx, parameters)
-               return nil, err
+       func(ctx context.Context) (*ledger.Log, *ledger.CreatedTransaction, error) {
+               return c.underlying.CreateTransaction(ctx, parameters)
        },
 )
-if err != nil {
-       return nil, nil, err
-}
-return log, createdTransaction, nil
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1da836b and 39006e6.

📒 Files selected for processing (3)
  • internal/controller/ledger/controller_with_traces.go (2 hunks)
  • internal/controller/system/controller.go (7 hunks)
  • internal/controller/system/module.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/controller/system/module.go
🔇 Additional comments (5)
internal/controller/system/controller.go (3)

42-43: LGTM: Good transition to provider pattern

The change from direct tracer/meter to provider pattern aligns with OpenTelemetry best practices and enables better control over telemetry lifecycle.


54-64: LGTM: Well-structured telemetry setup

The implementation correctly creates scoped tracers and meters with proper instrumentation attributes, enabling per-ledger telemetry.


Line range hint 170-190: LGTM: Consistent provider pattern implementation

The option functions and defaults are correctly updated to match the provider pattern changes while maintaining backward compatibility.

internal/controller/ledger/controller_with_traces.go (2)

19-40: LGTM: Comprehensive telemetry coverage

The histogram fields provide good coverage for all operations, with consistent naming conventions.


343-362: LGTM: Operation names correctly aligned with methods

The operation names in CreateTransaction and RevertTransaction methods now correctly match their respective operations, addressing previous review comments.

Also applies to: 366-385

Comment on lines +187 to +195
return tracing.TraceWithMetric(
ctx,
"GetMigrationsInfo",
c.tracer,
c.listTransactionsHistogram,
func(ctx context.Context) ([]migrations.Info, error) {
return c.underlying.GetMigrationsInfo(ctx)
},
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix incorrect histogram usage

The method is using listTransactionsHistogram for migration info operations, which is incorrect.

Add a dedicated histogram for migrations:

 return tracing.TraceWithMetric(
         ctx,
         "GetMigrationsInfo",
         c.tracer,
-        c.listTransactionsHistogram,
+        c.getMigrationsInfoHistogram,
         func(ctx context.Context) ([]migrations.Info, error) {
                 return c.underlying.GetMigrationsInfo(ctx)
         },
 )

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +43 to +137
func NewControllerWithTraces(underlying Controller, tracer trace.Tracer, meter metric.Meter) *ControllerWithTraces {
ret := &ControllerWithTraces{
underlying: underlying,
tracer: tracer,
}

var err error
ret.beginTxHistogram, err = meter.Int64Histogram("BeginTX")
if err != nil {
panic(err)
}
ret.listTransactionsHistogram, err = meter.Int64Histogram("ListTransactions")
if err != nil {
panic(err)
}
ret.commitHistogram, err = meter.Int64Histogram("Commit")
if err != nil {
panic(err)
}
ret.rollbackHistogram, err = meter.Int64Histogram("Rollback")
if err != nil {
panic(err)
}
ret.countTransactionsHistogram, err = meter.Int64Histogram("CountTransactions")
if err != nil {
panic(err)
}
ret.getTransactionHistogram, err = meter.Int64Histogram("GetTransaction")
if err != nil {
panic(err)
}
ret.countAccountsHistogram, err = meter.Int64Histogram("CountAccounts")
if err != nil {
panic(err)
}
ret.listAccountsHistogram, err = meter.Int64Histogram("ListAccounts")
if err != nil {
panic(err)
}
ret.getAccountHistogram, err = meter.Int64Histogram("GetAccount")
if err != nil {
panic(err)
}
ret.getAggregatedBalancesHistogram, err = meter.Int64Histogram("GetAggregatedBalances")
if err != nil {
panic(err)
}
ret.listLogsHistogram, err = meter.Int64Histogram("ListLogs")
if err != nil {
panic(err)
}
ret.importHistogram, err = meter.Int64Histogram("Import")
if err != nil {
panic(err)
}
ret.exportHistogram, err = meter.Int64Histogram("Export")
if err != nil {
panic(err)
}
ret.isDatabaseUpToDateHistogram, err = meter.Int64Histogram("IsDatabaseUpToDate")
if err != nil {
panic(err)
}
ret.getVolumesWithBalancesHistogram, err = meter.Int64Histogram("GetVolumesWithBalances")
if err != nil {
panic(err)
}
ret.getStatsHistogram, err = meter.Int64Histogram("GetStats")
if err != nil {
panic(err)
}
ret.createTransactionHistogram, err = meter.Int64Histogram("CreateTransaction")
if err != nil {
panic(err)
}
ret.revertTransactionHistogram, err = meter.Int64Histogram("RevertTransaction")
if err != nil {
panic(err)
}
ret.saveTransactionMetadataHistogram, err = meter.Int64Histogram("SaveTransactionMetadata")
if err != nil {
panic(err)
}
ret.saveAccountMetadataHistogram, err = meter.Int64Histogram("SaveAccountMetadata")
if err != nil {
panic(err)
}
ret.deleteTransactionMetadataHistogram, err = meter.Int64Histogram("DeleteTransactionMetadata")
if err != nil {
panic(err)
}
ret.deleteAccountMetadataHistogram, err = meter.Int64Histogram("DeleteAccountMetadata")
if err != nil {
panic(err)
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor constructor to improve error handling and reduce duplication

The constructor has several issues:

  1. Using panic for error handling
  2. Repetitive error handling code
  3. Long and hard to maintain

Consider this refactoring:

func NewControllerWithTraces(underlying Controller, tracer trace.Tracer, meter metric.Meter) *ControllerWithTraces {
+       createHistogram := func(name string) metric.Int64Histogram {
+               h, err := meter.Int64Histogram(name)
+               if err != nil {
+                       return nil, fmt.Errorf("failed to create histogram %s: %w", name, err)
+               }
+               return h
+       }

        ret := &ControllerWithTraces{
                underlying: underlying,
                tracer:     tracer,
        }

-       var err error
-       ret.beginTxHistogram, err = meter.Int64Histogram("BeginTX")
-       if err != nil {
-               panic(err)
-       }
+       histograms := map[string]*metric.Int64Histogram{
+               "BeginTX":                 &ret.beginTxHistogram,
+               "ListTransactions":        &ret.listTransactionsHistogram,
+               // ... other histograms
+       }
+
+       for name, hist := range histograms {
+               *hist, err = createHistogram(name)
+               if err != nil {
+                       return nil, err
+               }
+       }

        return ret
}

Committable suggestion skipped: line range outside the PR's diff.

@gfyrag gfyrag added this pull request to the merge queue Dec 13, 2024
Merged via the queue into main with commit 4a5d23d Dec 13, 2024
8 checks passed
@gfyrag gfyrag deleted the feat/refine-metrics branch December 13, 2024 11:43
@coderabbitai coderabbitai bot mentioned this pull request Dec 13, 2024
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.

3 participants