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: replace datadog-specific otel lib with generic otel #818

Merged
merged 3 commits into from
Dec 10, 2024

Conversation

smsunarto
Copy link
Member

@smsunarto smsunarto commented Dec 5, 2024

Closes: WORLD-XXX

Overview

Description of the overall background and high-level changes that this PR introduces

Brief Changelog

Testing and Verifying

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new jaeger service for tracing.
    • Added detailed API reference documentation for the World object in the Cardinal package.
  • Bug Fixes

    • Enhanced error handling in the authentication process for improved robustness.
  • Documentation

    • Removed references to DataDog telemetry from configuration documentation.
    • Updated descriptions for telemetry tracing capabilities.
  • Chores

    • Updated golangci-lint version for improved linting rules.
    • Removed DataDog tracing integration from various components to streamline the application.
    • Commented out the GitHub Actions workflow for EVM CI.
  • Style

    • Updated linting directives for clarity across several files.

Copy link

graphite-app bot commented Dec 5, 2024

Your org has enabled the Graphite merge queue for merging into main

Add the label “graphite/merge” to the PR and Graphite will automatically add it to the merge queue when it’s ready to merge.

You must have a Graphite account and log in to Graphite in order to use the merge queue. Sign up using this link.

Copy link
Contributor

coderabbitai bot commented Dec 5, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The pull request encompasses a series of changes primarily focused on updating the CI configuration, enhancing linter settings, and removing dependencies on DataDog's tracing library across various components. Key modifications include the upgrade of golangci-lint to a newer version, adjustments to linter configurations, and the removal of telemetry-related fields and methods. Additionally, documentation has been improved to reflect these changes, including the introduction of new API references and the removal of outdated references to DataDog. Overall, the changes aim to streamline the codebase and improve error handling and clarity.

Changes

File Path Change Summary
.github/workflows/ci-go.yaml Updated golangci-lint version from v1.57.1 to v1.62.2. No other changes to CI workflow structure.
.golangci.yaml Modified linter settings, increased timeout, renamed gomnd to mnd, added gosec, and updated checks.
cardinal/config.go Removed TelemetryProfilerEnabled field from WorldConfig struct.
cardinal/filter/filter.go Introduced ComponentWrapper struct and updated Component function return type.
cardinal/gamestate/redis.go Removed DataDog tracing references, simplified tracing logic in methods.
cardinal/gamestate/tick.go Removed DataDog imports and simplified tracing in FinalizeTick method.
cardinal/router/iterator/iterator.go Updated nolint directive from gomnd to mnd.
cardinal/router/option.go Updated nolint directive from gomnd to mnd.
cardinal/router/router.go Removed DataDog tracing, simplified span creation in methods.
cardinal/search.go Updated return statement comment in NewSearch function for clarity.
cardinal/server/validator/validator.go Enhanced error handling in SignatureValidator, added checks for MessageExpirationSeconds.
cardinal/system.go Removed DataDog tracing, simplified tracing logic in methods.
cardinal/telemetry/telemetry.go Removed DataDog fields, introduced OpenTelemetry setup methods, modified constructor.
cardinal/txpool/pool.go Updated tracing logic in CopyTransactions method, removed DataDog references.
cardinal/world.go Simplified telemetry initialization, updated logging types.
cardinal/world_fixture.go Updated nolint directives from gomnd to mnd.
cardinal/world_test.go Improved error message formatting in doTickCapturePanic.
cardinal/worldstage/worldstage.go Updated comment in Current method regarding error checking.
docker-compose.yml Removed datadog service, added jaeger, and updated environment variables for other services.
docs/cardinal/game/configuration/cardinal.mdx Removed TELEMETRY_PROFILER_ENABLED section, updated description for TELEMETRY_TRACE_ENABLED.
docs/cardinal/game/world/api-reference.mdx Added comprehensive API reference for World object and its functions.
e2e/testgames/game/main.go Updated nolint directive from gomnd to mnd.
e2e/testgames/gamebenchmark/main.go Updated nolint directive from gomnd to mnd.
e2e/tests/clients/nakama.go Improved error handling in validateSuccessfulAuth method using eris.
evm/cmd/world-evm/cmd/commands.go Updated nolint directive from gomnd to mnd in comments.
evm/router/result_storage.go Refined logic in Result method, removed logging statements.
evm/x/namespace/cli/query/query.go Updated nolint directive from gomnd to mnd in comments.
evm/x/namespace/cli/tx/tx.go Updated nolint directive from gomnd to mnd in comments.
makefiles/ci.mk Updated golangci-lint version from v1.57.1 to v1.62.2.
relay/nakama/events/events.go Improved error handling in Dispatch method, updated nolint directive from gomnd to mnd.
.github/workflows/ci-evm.yaml Workflow configuration commented out, disabling CI for EVM without deleting configuration.

Sequence Diagram(s)

sequenceDiagram
    participant CI as CI Workflow
    participant L as Linter
    participant T as Telemetry
    participant R as Redis
    participant W as World

    CI->>L: Run linting
    L->>L: Check for issues
    L->>CI: Return lint results

    CI->>T: Initialize telemetry
    T->>T: Setup OpenTelemetry
    T->>W: Start tracing
    W->>T: Report trace data

    CI->>R: Connect to Redis
    R->>R: Execute commands
    R->>CI: Return results
Loading

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between 62919a4 and d796720.

📒 Files selected for processing (2)
  • .github/workflows/ci-evm.yaml (1 hunks)
  • cardinal/telemetry/telemetry.go (2 hunks)

🪧 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
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@smsunarto smsunarto marked this pull request as ready for review December 5, 2024 22:36
Copy link

github-actions bot commented Dec 5, 2024

Preview Instructions

To preview these changes locally, checkout this branch and run:

make world-docs

@smsunarto smsunarto force-pushed the scott/12-05-feat_replace_ddotel_with_otel branch from 2015e4d to 1be143c Compare December 5, 2024 22:43
@smsunarto smsunarto changed the title feat: replace ddotel with otel feat: replace datadog-specif otel lib with otel Dec 5, 2024
@smsunarto smsunarto changed the title feat: replace datadog-specif otel lib with otel feat: replace datadog-specif otel lib with generic otel Dec 5, 2024
Copy link

github-actions bot commented Dec 5, 2024

Preview Instructions

To preview these changes locally, checkout this branch and run:

make world-docs

@smsunarto smsunarto changed the title feat: replace datadog-specif otel lib with generic otel feat: replace datadog-specific otel lib with generic otel Dec 5, 2024
@smsunarto smsunarto force-pushed the scott/12-05-feat_replace_ddotel_with_otel branch from 1be143c to f01fec8 Compare December 5, 2024 22:44
Copy link

github-actions bot commented Dec 5, 2024

Preview Instructions

To preview these changes locally, checkout this branch and run:

make world-docs

Copy link

codecov bot commented Dec 5, 2024

Codecov Report

Attention: Patch coverage is 45.71429% with 38 lines in your changes missing coverage. Please review.

Project coverage is 58.22%. Comparing base (c43e0ca) to head (d796720).
Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
cardinal/telemetry/telemetry.go 0.00% 22 Missing ⚠️
cardinal/server/validator/validator.go 14.28% 4 Missing and 2 partials ⚠️
cardinal/router/router.go 0.00% 3 Missing ⚠️
cardinal/gamestate/redis.go 60.00% 2 Missing ⚠️
cardinal/world.go 60.00% 1 Missing and 1 partial ⚠️
cardinal/world_fixture.go 75.00% 1 Missing ⚠️
evm/router/result_storage.go 75.00% 1 Missing ⚠️
relay/nakama/events/events.go 80.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #818   +/-   ##
=======================================
  Coverage   58.22%   58.22%           
=======================================
  Files         144      144           
  Lines        9237     9229    -8     
=======================================
- Hits         5378     5374    -4     
+ Misses       3413     3407    -6     
- Partials      446      448    +2     
Files with missing lines Coverage Δ
cardinal/config.go 71.81% <ø> (ø)
cardinal/filter/filter.go 100.00% <ø> (ø)
cardinal/gamestate/tick.go 68.29% <100.00%> (ø)
cardinal/router/iterator/iterator.go 87.65% <100.00%> (ø)
cardinal/router/option.go 83.33% <100.00%> (ø)
cardinal/search.go 79.83% <100.00%> (ø)
cardinal/system.go 86.27% <100.00%> (-0.14%) ⬇️
cardinal/txpool/pool.go 96.29% <100.00%> (ø)
cardinal/worldstage/worldstage.go 100.00% <100.00%> (ø)
evm/cmd/world-evm/cmd/commands.go 69.69% <100.00%> (ø)
... and 10 more

@smsunarto smsunarto enabled auto-merge (squash) December 5, 2024 22:49
Copy link
Contributor

@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: 11

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between 87afddf and f01fec8.

⛔ Files ignored due to path filters (18)
  • assert/go.mod is excluded by !**/*.mod
  • assert/go.sum is excluded by !**/*.sum, !**/*.sum
  • cardinal/go.mod is excluded by !**/*.mod
  • cardinal/go.sum is excluded by !**/*.sum, !**/*.sum
  • e2e/testgames/go.mod is excluded by !**/*.mod
  • e2e/testgames/go.sum is excluded by !**/*.sum, !**/*.sum
  • e2e/tests/go.mod is excluded by !**/*.mod
  • e2e/tests/go.sum is excluded by !**/*.sum, !**/*.sum
  • evm/go.mod is excluded by !**/*.mod
  • evm/go.sum is excluded by !**/*.sum, !**/*.sum
  • go.work is excluded by !**/*.work, !**/*.work
  • go.work.sum is excluded by !**/*.sum, !**/*.sum
  • relay/nakama/go.mod is excluded by !**/*.mod
  • relay/nakama/go.sum is excluded by !**/*.sum, !**/*.sum
  • rift/go.mod is excluded by !**/*.mod
  • rift/go.sum is excluded by !**/*.sum, !**/*.sum
  • sign/go.mod is excluded by !**/*.mod
  • sign/go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (30)
  • .github/workflows/ci-go.yaml (1 hunks)
  • .golangci.yaml (5 hunks)
  • cardinal/config.go (0 hunks)
  • cardinal/filter/filter.go (1 hunks)
  • cardinal/gamestate/redis.go (3 hunks)
  • cardinal/gamestate/tick.go (1 hunks)
  • cardinal/router/iterator/iterator.go (1 hunks)
  • cardinal/router/option.go (1 hunks)
  • cardinal/router/router.go (3 hunks)
  • cardinal/search.go (1 hunks)
  • cardinal/server/validator/validator.go (2 hunks)
  • cardinal/system.go (2 hunks)
  • cardinal/telemetry/telemetry.go (2 hunks)
  • cardinal/txpool/pool.go (1 hunks)
  • cardinal/world.go (5 hunks)
  • cardinal/world_fixture.go (4 hunks)
  • cardinal/world_test.go (1 hunks)
  • cardinal/worldstage/worldstage.go (1 hunks)
  • docker-compose.yml (3 hunks)
  • docs/cardinal/game/configuration/cardinal.mdx (1 hunks)
  • docs/cardinal/game/world/api-reference.mdx (0 hunks)
  • e2e/testgames/game/main.go (1 hunks)
  • e2e/testgames/gamebenchmark/main.go (1 hunks)
  • e2e/tests/clients/nakama.go (2 hunks)
  • evm/cmd/world-evm/cmd/commands.go (2 hunks)
  • evm/router/result_storage.go (1 hunks)
  • evm/x/namespace/cli/query/query.go (1 hunks)
  • evm/x/namespace/cli/tx/tx.go (2 hunks)
  • makefiles/ci.mk (1 hunks)
  • relay/nakama/events/events.go (2 hunks)
💤 Files with no reviewable changes (2)
  • cardinal/config.go
  • docs/cardinal/game/world/api-reference.mdx
🧰 Additional context used
📓 Learnings (1)
cardinal/server/validator/validator.go (1)
Learnt from: ezavada
PR: Argus-Labs/world-engine#804
File: cardinal/server/validator/validator.go:174-176
Timestamp: 2024-11-12T03:36:28.419Z
Learning: In `validator.go`, ensure that the `ValidateTransactionTTL` function is restricted to validating the TTL of the message only. Do not include other validations, such as namespace validation, within this function.
🪛 yamllint (1.35.1)
.golangci.yaml

[error] 142-142: too many spaces inside brackets

(brackets)


[error] 142-142: too many spaces inside brackets

(brackets)


[warning] 201-201: too few spaces before comment

(comments)


[warning] 237-237: too few spaces before comment

(comments)

🔇 Additional comments (32)
cardinal/router/option.go (1)

17-17: Update linter directive to match new linter name

The linter gomnd has been renamed to mnd in newer versions of golangci-lint. Updating the directive ensures that the lint suppression works correctly.

makefiles/ci.mk (1)

5-5: Update golangci-lint to the latest stable version

Updating golangci-lint to v1.62.2 ensures that the latest checks and improvements are included, which can help detect more issues and improve code quality.

e2e/testgames/game/main.go (1)

18-18: Update linter directive to match new linter name

The linter gomnd has been renamed to mnd. Updating the directive ensures the linter recognizes the suppression comment.

evm/router/result_storage.go (1)

50-53: LGTM: Simplified control flow improves readability

The refactored code maintains the same functionality while being more concise and easier to follow. The type assertion is now handled more elegantly within the same conditional block.

e2e/testgames/gamebenchmark/main.go (1)

47-47: LGTM: Updated linting directive

The linting directive has been correctly updated from gomnd to mnd to align with the new linting configuration.

evm/x/namespace/cli/query/query.go (1)

19-19: LGTM: Updated linting directive

The linting directive has been correctly updated from gomnd to mnd to align with the new linting configuration.

evm/x/namespace/cli/tx/tx.go (1)

22-22: LGTM: Linting directive updates are consistent

The changes from gomnd to mnd align with modern linting practices while maintaining the same functionality. These updates are part of the broader linting improvements across the codebase.

Also applies to: 41-41

cardinal/worldstage/worldstage.go (1)

54-54: LGTM: Type assertion safety is guaranteed

The errcheck suppression is appropriate here as the type assertion is guaranteed to be safe:

  1. The atomic.Value is only ever stored with Stage type via Store() and CompareAndSwap
  2. The initialization in NewManager() sets it to Init which is a Stage
cardinal/gamestate/tick.go (2)

Line range hint 41-67: LGTM: Robust error handling with proper tracing integration

The error handling implementation follows best practices:

  1. Properly sets OpenTelemetry span status
  2. Records errors in the span
  3. Provides context through error wrapping

38-38: Verify OpenTelemetry migration completeness

The switch from Datadog-specific to generic OpenTelemetry tracing looks good. However, we should verify that no essential tracing attributes were lost in the migration.

✅ Verification successful

Based on the comprehensive output, I can now generate the final response:

OpenTelemetry migration is complete and properly implemented

The migration from Datadog to OpenTelemetry tracing in tick.go is correct and complete. The new implementation:

  • Properly creates and ends spans
  • Correctly handles error cases with appropriate status codes and error recording
  • Maintains equivalent functionality with proper error context propagation
  • No Datadog dependencies remain in the codebase
  • Follows consistent OpenTelemetry patterns used throughout the project
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining Datadog dependencies and verify tracing attribute coverage

# Check for any remaining Datadog imports
echo "Checking for remaining Datadog dependencies..."
rg -l "datadog|dd-trace" --type go

# Check OpenTelemetry attribute usage
echo "Checking OpenTelemetry attribute usage..."
rg "span\.(Set|Add)Attribute" --type go -A 2

Length of output: 279


Script:

#!/bin/bash
# Let's try a different approach to verify the tracing migration

# Check the diff of the specific file to see what attributes were present before
git log -p cardinal/gamestate/tick.go | grep -A 10 -B 10 "dd-trace"

# Look for any OpenTelemetry imports and usage patterns
echo "Checking OpenTelemetry imports and usage..."
rg "go.opentelemetry.io/otel" --type go

# Check for span operations in the current implementation
echo "Checking span operations..."
rg "span\." --type go -A 2

# Look specifically in tick.go
echo "Checking tick.go specifically..."
cat cardinal/gamestate/tick.go

Length of output: 24020

cardinal/txpool/pool.go (1)

91-93: LGTM: Clean transition to generic OpenTelemetry

The change from Datadog-specific tracing to generic OpenTelemetry is implemented correctly. The span creation and cleanup are properly handled, and the tracer initialization in the constructor remains appropriate.

docs/cardinal/game/configuration/cardinal.mdx (1)

Line range hint 97-102: LGTM: Documentation updated to be vendor-agnostic

The description for TELEMETRY_TRACE_ENABLED has been appropriately updated to remove Datadog-specific references.

Let's verify that the profiler configuration removal is consistent with code changes:

✅ Verification successful

Profiler configuration removal is consistent with codebase

The removal of the TELEMETRY_PROFILER_ENABLED section from the documentation is consistent with the codebase state. Our verification shows:

  • No references to "telemetry_profiler" exist in the codebase
  • No profiler configuration settings are present
  • The only telemetry-related configuration that remains is TELEMETRY_TRACE_ENABLED
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any remaining references to the profiler configuration
rg -i "TELEMETRY_PROFILER" 

# Check for any remaining profiler-related code
rg -i "profiler" -g "!*.md" -g "!*.mdx"

Length of output: 66


Script:

#!/bin/bash
# Let's try a more comprehensive search for profiler-related code
# Search in configuration files
fd -e env -e ini -e yaml -e yml -e json -e toml -exec rg -i "profiler|telemetry" {}

# Search in source code files for profiler initialization or setup
fd -e js -e ts -e py -e go -e java -e rb -exec rg -i "profiler|telemetry" {}

# Search specifically in the cardinal directory for any telemetry/profiler references
fd . docs/cardinal -exec rg -i "profiler|telemetry" {}

Length of output: 700


Script:

#!/bin/bash
# Fix the command syntax for proper execution
# Search for profiler/telemetry references in the codebase
rg -i "telemetry_profiler" .

# Search for any profiler configuration or setup
rg -i "profiler.*enabled" .

# Look for telemetry configuration in cardinal docs
rg -i "telemetry" docs/cardinal/

# Check git history for recent changes related to profiler
git log --oneline -S "TELEMETRY_PROFILER" --since="1 month ago"

Length of output: 321

cardinal/router/iterator/iterator.go (1)

141-144: LGTM: Updated linter directive

The change from gomnd to mnd is correct and the magic number usage for buffer size is justified in this context.

.github/workflows/ci-go.yaml (1)

50-50: Verify compatibility with the updated golangci-lint version

The update from v1.57.1 to v1.62.2 might introduce new linting rules. Ensure all existing code passes the updated linter checks.

✅ Verification successful

Golangci-lint version update appears safe to proceed

The update from v1.57.1 to v1.62.2 consists mainly of dependency updates and minor fixes. The changelog shows no breaking changes or new linting rules that could impact existing code. The codebase already uses linter directives appropriately across multiple files, indicating good linting practices are in place.

  • Multiple Go files contain existing linter directives (//nolint or //golangci), showing active lint management
  • The version bump includes only dependency updates and a minor fix for cache handling
  • No new linting rules or breaking changes are introduced in this version range
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any breaking changes or new linting rules between versions

# Get the changelog differences between versions
gh api repos/golangci/golangci-lint/releases | jq -r '.[] | select(.tag_name | contains("v1.57.1","v1.62.2")) | .body'

# Check if there are any existing golangci-lint configuration files
fd -t f '.golangci.yml|.golangci.yaml'

Length of output: 1901


Script:

#!/bin/bash
# Let's check for Go files and any existing linter configurations in the codebase
fd -e go

# Check for any existing linter directives or configurations in Go files
rg -l "//nolint|//golangci" -t go

# Look for any existing make targets or scripts that run the linter
rg -l "golangci-lint" --type yaml --type makefile

Length of output: 10477

relay/nakama/events/events.go (2)

59-59: LGTM: Updated linter directive

The change from gomnd to mnd aligns with the latest linting rules.


159-162: LGTM: Improved type safety in shutdown process

The addition of type assertion if keyStr, ok := key.(string); ok enhances robustness by preventing potential panics during shutdown when handling keys.

cardinal/router/router.go (1)

137-137: LGTM: Simplified OpenTelemetry implementation

The removal of DataDog-specific tracing in favor of generic OpenTelemetry implementation maintains the necessary functionality while reducing vendor lock-in.

Also applies to: 207-207

✅ Verification successful

Let me check the actual content of these files to determine if these are just dependency declarations or actual usage.


Let me check for actual DataDog tracing usage in the code to ensure it's completely removed.


Let me try one final check to verify the OpenTelemetry implementation.


LGTM: Confirmed OpenTelemetry implementation

The codebase shows proper implementation of OpenTelemetry tracing with no remaining DataDog dependencies in the active code. The DataDog entries found in go.mod files are only indirect dependencies from other packages and not actively used in the tracing implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify complete removal of DataDog dependencies

# Check for any remaining DataDog imports
rg -l 'github\.com/DataDog|gopkg\.in/DataDog'

# Check for any remaining DataDog configuration
rg -l 'ddtrace|datadog'

Length of output: 197


Script:

#!/bin/bash
# Check the actual content of go.mod files
echo "=== e2e/tests/go.mod ==="
cat e2e/tests/go.mod
echo -e "\n=== evm/go.mod ==="
cat evm/go.mod

# Check for actual DataDog usage in code
echo -e "\n=== Checking for DataDog usage in code ==="
rg "DataDog" --type go -C 2

Length of output: 29074


Script:

#!/bin/bash
# Search for any DataDog tracing related code
rg -i "ddtrace|datadog.*trace" --type go -C 2

# Search for any remaining tracer implementations to verify OpenTelemetry usage
ast-grep --pattern 'tracer.$$$Start($$$)'

Length of output: 91


Script:

#!/bin/bash
# Check for OpenTelemetry imports and usage
rg "go.opentelemetry.io" --type go -C 2

# Check the specific file for tracer implementation
cat cardinal/router/router.go

Length of output: 10205

cardinal/system.go (2)

138-138: LGTM: Clean OpenTelemetry tracer initialization

The tracer initialization is properly configured using the generic OpenTelemetry tracer.


159-167: Verify error handling in spans

The error handling and span management looks good, but let's verify the error propagation pattern across the codebase.

✅ Verification successful

The previous ast-grep pattern might have been too strict. Let's try with ripgrep to find error handling patterns in spans with more flexibility, including both exact matches and similar patterns.


Error handling in spans follows consistent pattern

The error handling pattern in spans is consistently implemented across the codebase. The pattern of calling span.SetStatus(codes.Error, ...) followed by span.RecordError(err) is uniformly used in all error cases across multiple packages including cardinal/system.go, cardinal/world.go, cardinal/router/router.go, cardinal/gamestate/, and relay/nakama/handlers.go. The implementation in the reviewed code follows this established pattern correctly.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar error handling patterns in spans
ast-grep --pattern 'span.SetStatus(codes.Error, $_)
span.RecordError($_)'

Length of output: 75


Script:

#!/bin/bash
# Let's search for error handling patterns in spans with a more flexible pattern
rg -U "SetStatus.*Error.*\n.*RecordError" --type go

# Also search for general span error handling
rg "span.*Error" --type go

Length of output: 8374

docker-compose.yml (2)

Line range hint 202-212: LGTM: Well-configured Jaeger service

The Jaeger service is properly configured with:

  • OTLP collector enabled
  • Correct ports exposed for UI (16686) and OTLP (4317, 4318)
  • Appropriate network configuration

218-220: LGTM: Explicit network configuration

Good practice to explicitly define the network driver.

evm/cmd/world-evm/cmd/commands.go (1)

139-139: LGTM: Updated linting directives

The linting directive has been updated from gomnd to mnd to align with the new golangci-lint version.

Also applies to: 160-160

cardinal/world_fixture.go (1)

49-49: LGTM: Linter directive updates

The changes correctly update the linter directives from gomnd to mnd while maintaining the same functionality.

Also applies to: 113-113, 130-130, 267-267

cardinal/search.go (1)

111-111: LGTM! Verify type assertion safety.

The added linter directive is appropriate as the type assertion is indeed safe. NewLegacySearch always returns a non-nil *Search which implements searchBuilder.

✅ Verification successful

Type assertion is safe - verification successful

The code analysis confirms the safety of the type assertion:

  • NewLegacySearch always returns a non-nil *Search struct with initialized fields
  • Search struct properly implements the searchBuilder interface by providing the required Entity method
  • The implementation matches the interface contract, making the type assertion safe
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify NewLegacySearch always returns *Search implementing searchBuilder

# Check if NewLegacySearch has any nil returns or error paths
ast-grep --pattern 'func NewLegacySearch($_, $_) EntitySearch {
  return $$$
}'

# Verify searchBuilder interface implementation
ast-grep --pattern 'type Search struct {
  $$$
}

$$$

func (s *Search) Entity($_) EntitySearch {
  $$$
}'

Length of output: 190


Script:

#!/bin/bash
# Let's try a different approach to verify the implementation

# Check NewLegacySearch implementation
rg "func NewLegacySearch" -A 5

# Check searchBuilder interface definition and Search struct implementation
rg "type searchBuilder interface" -A 5
rg "type Search struct" -A 5

# Check if Search implements Entity method
rg "func \(s \*Search\) Entity" -A 5

Length of output: 1293

cardinal/gamestate/redis.go (2)

Line range hint 127-146: LGTM! Clean transition to generic OpenTelemetry.

The removal of Datadog-specific tracing in favor of standard OpenTelemetry is well implemented. Error handling and span management remain robust.


Line range hint 151-190: LGTM! Well-structured tracing implementation.

The tracing implementation for pipeline operations is clean and maintainable:

  • Each operation has its own span
  • Error handling is comprehensive
  • Spans are properly ended in both success and error cases
.golangci.yaml (2)

98-98: LGTM: Linter rename from gomnd to mnd

The change reflects the latest golangci-lint naming convention. The rename is consistently applied in both the linter settings and the allow-no-explanation list.

Also applies to: 142-142


199-201: Verify the security implications of disabling G115

The G115 rule in gosec checks for hardcoded credentials. Ensure that all cases where this rule is disabled have been thoroughly reviewed and documented.

✅ Verification successful

Disabling G115 appears safe in this codebase

After analyzing the codebase, I can confirm that:

  1. No hardcoded credentials are found in the Go source code
  2. All credential-related code appears to be properly handled:
    • Environment variables and configuration files are used for credentials
    • Test fixtures use clearly marked test/mock values
    • Keys and tokens are properly managed through secure mechanisms (KMS, auth tokens, etc.)
  3. The G115 rule is likely disabled to avoid false positives on legitimate cases like:
    • Configuration structs and environment variable definitions
    • Test fixtures and mock data
    • Protocol buffer definitions for key-value mappings
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for potential hardcoded credentials in the codebase
rg -g '!.golangci.yaml' -i '(password|secret|key|token|credential).*=.*["\'].*["\']'

Length of output: 116


Script:

#!/bin/bash
# Search for potential hardcoded credentials in the codebase with proper quoting
rg -g '!.golangci.yaml' -i "(password|secret|key|token|credential).*=.*['\"].*['\"]"

# Also search for G115 related comments to understand the context
rg "G115" -C 2

# Look for any nolint directives related to G115
rg "nolint.*G115"

# Find Go files that might contain credential-related code
fd -e go -x grep -l -i "password\|secret\|key\|token\|credential" {}

Length of output: 10032

🧰 Tools
🪛 yamllint (1.35.1)

[warning] 201-201: too few spaces before comment

(comments)

cardinal/world.go (4)

106-107: LGTM: Simplified telemetry initialization

The removal of DataDog-specific profiler configuration aligns with the PR objective of moving to generic OpenTelemetry.


201-201: LGTM: Simplified span creation

The tracing implementation has been simplified to use standard OpenTelemetry context without vendor-specific options.


271-271: LGTM: Type correction in logging

Changed tick value type from int to int64 in logging to ensure consistent type representation.


591-591: LGTM: Simplified span creation in broadcastTickResults

Consistent with other tracing changes, the span creation has been simplified to use standard OpenTelemetry.

Comment on lines +62 to +67
// Ensure default SDK resources and the required service name are set.
r, err := resource.Merge(
resource.Default(),
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Handle errors instead of panicking in setupTrace

Using panic for error handling can cause the application to crash unexpectedly. It's better to return the error and allow the caller to handle it appropriately.

Apply this diff to handle the error gracefully:

 func (tm *Manager) setupTrace(exporter trace.SpanExporter) error {
     // Ensure default SDK resources and the required service name are set.
     r, err := resource.Merge(
         resource.Default(),
         resource.NewWithAttributes(
             semconv.SchemaURL,
             semconv.ServiceName(tm.namespace+"-cardinal"),
         ),
     )
     if err != nil {
-        panic(err)
+        return err
     }

     tm.tracerProvider = trace.NewTracerProvider(trace.WithResource(r), trace.WithBatcher(exporter))
     otel.SetTracerProvider(tm.tracerProvider)
+    return nil
 }

Update the call in the New function to handle the error:

 if enableTrace {
-    tm.setupTrace(exporter)
+    if err := tm.setupTrace(exporter); err != nil {
+        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
// Ensure default SDK resources and the required service name are set.
r, err := resource.Merge(
resource.Default(),
func (tm *Manager) setupTrace(exporter trace.SpanExporter) error {
// Ensure default SDK resources and the required service name are set.
r, err := resource.Merge(
resource.Default(),
resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName(tm.namespace+"-cardinal"),
),
)
if err != nil {
return err
}
tm.tracerProvider = trace.NewTracerProvider(trace.WithResource(r), trace.WithBatcher(exporter))
otel.SetTracerProvider(tm.tracerProvider)
return nil
}
// In the New function:
if enableTrace {
if err := tm.setupTrace(exporter); err != nil {
return nil, err
}
}

@smsunarto smsunarto force-pushed the scott/12-05-feat_replace_ddotel_with_otel branch from f01fec8 to 75b1b38 Compare December 6, 2024 00:48
Copy link

github-actions bot commented Dec 6, 2024

Preview Instructions

To preview these changes locally, checkout this branch and run:

make world-docs

@smsunarto smsunarto force-pushed the scott/12-05-feat_replace_ddotel_with_otel branch from 75b1b38 to d99caa2 Compare December 6, 2024 01:02
Copy link

github-actions bot commented Dec 6, 2024

Preview Instructions

To preview these changes locally, checkout this branch and run:

make world-docs

Copy link
Contributor

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

Actionable comments posted: 10

🧹 Outside diff range comments (1)
cardinal/gamestate/redis.go (1)

Line range hint 151-190: Consider consolidating error handling in operation loop

The error handling pattern is repeated for each operation. Consider extracting it into a helper function to reduce duplication.

 operations := []struct {
   name   string
   method func(ctx context.Context, pipe PrimitiveStorage[string]) error
 }{
   {"component_changes", m.addComponentChangesToPipe},
   {"next_entity_id", m.addNextEntityIDToPipe},
   {"pending_arch_ids", m.addPendingArchIDsToPipe},
   {"entity_id_to_arch_id", m.addEntityIDToArchIDToPipe},
   {"active_entity_ids", m.addActiveEntityIDsToPipe},
 }

+func (m *EntityCommandBuffer) executeOperation(
+  ctx context.Context,
+  span trace.Span,
+  operation struct {
+    name   string
+    method func(ctx context.Context, pipe PrimitiveStorage[string]) error
+  },
+  pipe PrimitiveStorage[string],
+) error {
+  ctx, pipeSpan := m.tracer.Start(ctx, "tick.span.finalize.pipe_make."+operation.name)
+  defer pipeSpan.End()
+  
+  if err := operation.method(ctx, pipe); err != nil {
+    span.SetStatus(codes.Error, eris.ToString(err, true))
+    span.RecordError(err)
+    pipeSpan.SetStatus(codes.Error, eris.ToString(err, true))
+    pipeSpan.RecordError(err)
+    return eris.Wrapf(err, "failed to run step %q", operation.name)
+  }
+  return nil
+}

 for _, operation := range operations {
-  ctx, pipeSpan := m.tracer.Start(ctx, "tick.span.finalize.pipe_make."+operation.name)
-  if err := operation.method(ctx, pipe); err != nil {
-    span.SetStatus(codes.Error, eris.ToString(err, true))
-    span.RecordError(err)
-    pipeSpan.SetStatus(codes.Error, eris.ToString(err, true))
-    pipeSpan.RecordError(err)
-    pipeSpan.End()
-    return nil, eris.Wrapf(err, "failed to run step %q", operation.name)
+  if err := m.executeOperation(ctx, span, operation, pipe); err != nil {
+    return nil, err
   }
-  pipeSpan.End()
 }
🛑 Comments failed to post (10)
cardinal/telemetry/telemetry.go (1)

77-78: ⚠️ Potential issue

Assign tracerShutdownFunc to ensure proper shutdown of the tracer provider

Currently, tracerShutdownFunc is not assigned after creating the tracerProvider. This means the Shutdown method won't properly shut down the tracer provider, potentially leading to resource leaks. Assign tracerShutdownFunc to ensure resources are released correctly.

Apply this diff to assign tracerShutdownFunc:

 tm.tracerProvider = trace.NewTracerProvider(trace.WithResource(r), trace.WithBatcher(exporter))
 otel.SetTracerProvider(tm.tracerProvider)
+tm.tracerShutdownFunc = tm.tracerProvider.Shutdown
📝 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.

	tm.tracerProvider = trace.NewTracerProvider(trace.WithResource(r), trace.WithBatcher(exporter))
	otel.SetTracerProvider(tm.tracerProvider)
	tm.tracerShutdownFunc = tm.tracerProvider.Shutdown
cardinal/router/option.go (1)

17-17: 🛠️ Refactor suggestion

Replace magic number with a named constant

Using magic numbers can make the code less readable and harder to maintain. Consider defining a named constant for 20 to clarify its purpose.

Apply this diff to introduce a named constant:

+const jobQueueCapacity = 20

 func WithMockJobQueue() Option {
     return func(rtr *router) {
         sequencerJobQueue, err := jobqueue.New[*shard.SubmitTransactionsRequest](
             "",
             "submit-tx",
-            20, //nolint:mnd // Will do this later
+            jobQueueCapacity,
             handleSubmitTx(rtr.ShardSequencer, rtr.tracer),
             jobqueue.WithInmemDB[*shard.SubmitTransactionsRequest](),
         )

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

evm/router/result_storage.go (1)

50-53: 🧹 Nitpick (assertive)

Consider logging type assertion failures.

While the simplified control flow is good, we're now silently handling type assertion failures. Consider adding debug logging for this error case to help with troubleshooting.

 if res, ok := res.(Result); ok {
   return res, true
 }
+log.Debug().Msgf("type assertion failed for result with key %q", hash)
 return Result{}, false

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

cardinal/worldstage/worldstage.go (1)

54-54: 🧹 Nitpick (assertive)

LGTM: Safe to ignore type assertion check.

The type assertion is indeed safe as the atomic.Value is only ever stored with Stage type through controlled methods (Store and CompareAndSwap). However, consider adding a brief comment explaining why the type assertion is safe for future maintainers.

-	return m.current.Load().(Stage) //nolint:errcheck // Will never have issues here
+	// Safe type assertion: atomic.Value is only stored with Stage type via Store() and CompareAndSwap()
+	return m.current.Load().(Stage) //nolint:errcheck
📝 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.

	// Safe type assertion: atomic.Value is only stored with Stage type via Store() and CompareAndSwap()
	return m.current.Load().(Stage) //nolint:errcheck
cardinal/txpool/pool.go (1)

91-91: 🧹 Nitpick (assertive)

LGTM: Clean transition to generic OpenTelemetry

The tracing implementation has been correctly simplified while maintaining the core functionality and thread-safety of the transaction pool.

Consider adding span attributes to track the number of transactions being copied:

 func (t *TxPool) CopyTransactions(ctx context.Context) *TxPool {
-	_, span := t.tracer.Start(ctx, "txpool.copy-transactions")
+	_, span := t.tracer.Start(ctx, "txpool.copy-transactions")
+	span.SetAttributes(attribute.Int("txs_in_pool", t.txsInPool))
 	defer span.End()
📝 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.

	_, span := t.tracer.Start(ctx, "txpool.copy-transactions")
	span.SetAttributes(attribute.Int("txs_in_pool", t.txsInPool))
relay/nakama/events/events.go (1)

159-162: 🧹 Nitpick (assertive)

Consider OpenTelemetry integration for event logging

While the type safety improvement is good, since we're migrating to generic OpenTelemetry, consider adding telemetry spans for event dispatch and shutdown operations. This would provide better observability for the event hub lifecycle.

Would you like me to provide an example of how to integrate OpenTelemetry spans in the event dispatch and shutdown flows?

cardinal/router/router.go (1)

207-207: 🛠️ Refactor suggestion

Consider propagating context from JobContext

Using context.Background() breaks the trace context chain. Consider using the context from JobContext parameter to maintain proper trace context propagation.

-		_, span := tracer.Start(context.Background(), "router.job-queue.submit-tx")
+		_, span := tracer.Start(ctx, "router.job-queue.submit-tx")

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

cardinal/world_fixture.go (1)

49-49: 🧹 Nitpick (assertive)

LGTM: Updated linting directives with suggested improvements.

The changes correctly update the linting directives from gomnd to mnd. However, consider extracting the magic numbers into named constants for better maintainability and clarity.

Consider applying this refactor:

 const (
+    gameStartupTimeout = 5 * time.Second
+    pollingInterval = 10 * time.Millisecond
 )

 func (t *TestFixture) StartWorld() {
     t.startOnce.Do(func() {
-        timeout := time.After(5 * time.Second) //nolint:mnd // fine for now.
+        timeout := time.After(gameStartupTimeout)
         ...
-        time.Sleep(10 * time.Millisecond) //nolint:mnd // its for testing its ok.
+        time.Sleep(pollingInterval)
     })
 }

 func findOpenPort() (string, error) {
     ...
-    time.Sleep(10 * time.Millisecond) //nolint:mnd // it's fine.
+    time.Sleep(pollingInterval)
 }

Also applies to: 113-113, 130-130, 267-267

.golangci.yaml (2)

142-142: 🧹 Nitpick (assertive)

Fix trailing spaces in allow-no-explanation list

Remove trailing spaces to comply with YAML formatting standards.

-    allow-no-explanation: [funlen, gocognit, lll, exhaustruct, decorder, mnd] 
+    allow-no-explanation: [funlen, gocognit, lll, exhaustruct, decorder, mnd]
📝 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.

    allow-no-explanation: [funlen, gocognit, lll, exhaustruct, decorder, mnd]
🧰 Tools
🪛 yamllint (1.35.1)

[error] 142-142: trailing spaces

(trailing-spaces)


199-202: 🧹 Nitpick (assertive)

Fix comment spacing in gosec configuration

Add a space after the comment marker for consistency.

  gosec:
    excludes:
-      - G115 #Selectively disable G115 for cases where we've verified the conversions are safe
+      - G115 # Selectively disable G115 for cases where we've verified the conversions are safe

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

🧰 Tools
🪛 yamllint (1.35.1)

[warning] 201-201: too few spaces before comment

(comments)

Copy link
Contributor

@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: 10

🧹 Outside diff range comments (5)
evm/x/namespace/cli/query/query.go (1)

Line range hint 1-85: Consider adding telemetry for query operations monitoring.

As part of the OpenTelemetry migration, consider instrumenting these query operations to track metrics like:

  • Query latency
  • Query frequency
  • Error rates

This would help in monitoring the namespace query performance and reliability.

cardinal/txpool/pool.go (1)

Line range hint 29-31: Follow OpenTelemetry semantic conventions for tracer name

Consider using a more specific instrumentation name following OpenTelemetry semantic conventions:

-		tracer: otel.Tracer("txpool"),
+		tracer: otel.Tracer("pkg.world.dev/world-engine/cardinal/txpool"),
docker-compose.yml (1)

Jaeger configuration needs additional environment variables for proper OpenTelemetry integration

The verification reveals that while Jaeger is configured with OTLP enabled and correct ports, the services lack complete OpenTelemetry configuration:

  • Services only have TELEMETRY_TRACE_ENABLED flag
  • Missing crucial configuration for OTLP endpoint address in the main docker-compose.yml
  • No clear connection between services and the Jaeger collector endpoint

Required additions:

  • Add TELEMETRY_TRACE_ADDRESS=http://jaeger:4317 to services that need tracing
  • Consider adding OTEL_SERVICE_NAME for proper service identification in traces
🔗 Analysis chain

Line range hint 207-215: Verify Jaeger configuration with OpenTelemetry.

The Jaeger service has been properly configured with:

  • OTLP collector enabled
  • Standard ports exposed (16686 for UI, 4317/4318 for OTLP)

Let's verify the environment variables in the game services are properly configured to use Jaeger:


Let me gather more information about the OpenTelemetry configuration to ensure proper integration with Jaeger.


Let me check one more thing to verify the complete telemetry configuration.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if game services are configured to use Jaeger
rg "TELEMETRY_TRACE_ENABLED" -A 2

Length of output: 1037


Script:

#!/bin/bash
# Check for OpenTelemetry endpoint configuration and other related settings
rg "TELEMETRY_TRACE|OTEL_" -A 2

# Check for any Jaeger-related configuration in the codebase
rg "jaeger" --type go -A 3

Length of output: 1454


Script:

#!/bin/bash
# Check for telemetry address configuration
rg "TELEMETRY_TRACE_ADDRESS" -A 2

# Look for OpenTelemetry initialization code
ast-grep --pattern 'func $_($$_) {
  $$$
  trace.$$$
  $$$
}'

Length of output: 272

cardinal/gamestate/redis.go (1)

Line range hint 151-192: Consider consolidating span operations.

While the implementation is correct, the nested spans for each operation could be consolidated to reduce overhead. Consider using span attributes or events instead of creating new spans for each operation.

Example refactor:

-		ctx, pipeSpan := m.tracer.Start(ctx, "tick.span.finalize.pipe_make."+operation.name)
+		span.AddEvent("pipe_make_" + operation.name)
 		if err := operation.method(ctx, pipe); err != nil {
 			span.SetStatus(codes.Error, eris.ToString(err, true))
 			span.RecordError(err)
-			pipeSpan.SetStatus(codes.Error, eris.ToString(err, true))
-			pipeSpan.RecordError(err)
-			pipeSpan.End()
 			return nil, eris.Wrapf(err, "failed to run step %q", operation.name)
 		}
-		pipeSpan.End()
cardinal/world.go (1)

Line range hint 590-611: Consider adding span attributes for tick information.

While the tracing implementation is correct, adding span attributes for tick information would improve observability.

 	_, span := w.tracer.Start(ctx, "world.tick.broadcast_tick_results")
+	span.SetAttributes(attribute.Int64("tick", int64(w.CurrentTick()-1)))
 	defer span.End()
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between f01fec8 and d99caa2.

⛔ Files ignored due to path filters (18)
  • assert/go.mod is excluded by !**/*.mod
  • assert/go.sum is excluded by !**/*.sum, !**/*.sum
  • cardinal/go.mod is excluded by !**/*.mod
  • cardinal/go.sum is excluded by !**/*.sum, !**/*.sum
  • e2e/testgames/go.mod is excluded by !**/*.mod
  • e2e/testgames/go.sum is excluded by !**/*.sum, !**/*.sum
  • e2e/tests/go.mod is excluded by !**/*.mod
  • e2e/tests/go.sum is excluded by !**/*.sum, !**/*.sum
  • evm/go.mod is excluded by !**/*.mod
  • evm/go.sum is excluded by !**/*.sum, !**/*.sum
  • go.work is excluded by !**/*.work, !**/*.work
  • go.work.sum is excluded by !**/*.sum, !**/*.sum
  • relay/nakama/go.mod is excluded by !**/*.mod
  • relay/nakama/go.sum is excluded by !**/*.sum, !**/*.sum
  • rift/go.mod is excluded by !**/*.mod
  • rift/go.sum is excluded by !**/*.sum, !**/*.sum
  • sign/go.mod is excluded by !**/*.mod
  • sign/go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (31)
  • .github/workflows/ci-evm.yaml (1 hunks)
  • .github/workflows/ci-go.yaml (1 hunks)
  • .golangci.yaml (5 hunks)
  • cardinal/config.go (0 hunks)
  • cardinal/filter/filter.go (1 hunks)
  • cardinal/gamestate/redis.go (3 hunks)
  • cardinal/gamestate/tick.go (1 hunks)
  • cardinal/router/iterator/iterator.go (1 hunks)
  • cardinal/router/option.go (1 hunks)
  • cardinal/router/router.go (3 hunks)
  • cardinal/search.go (1 hunks)
  • cardinal/server/validator/validator.go (2 hunks)
  • cardinal/system.go (2 hunks)
  • cardinal/telemetry/telemetry.go (2 hunks)
  • cardinal/txpool/pool.go (1 hunks)
  • cardinal/world.go (4 hunks)
  • cardinal/world_fixture.go (4 hunks)
  • cardinal/world_test.go (1 hunks)
  • cardinal/worldstage/worldstage.go (1 hunks)
  • docker-compose.yml (3 hunks)
  • docs/cardinal/game/configuration/cardinal.mdx (1 hunks)
  • docs/cardinal/game/world/api-reference.mdx (0 hunks)
  • e2e/testgames/game/main.go (1 hunks)
  • e2e/testgames/gamebenchmark/main.go (1 hunks)
  • e2e/tests/clients/nakama.go (2 hunks)
  • evm/cmd/world-evm/cmd/commands.go (2 hunks)
  • evm/router/result_storage.go (1 hunks)
  • evm/x/namespace/cli/query/query.go (1 hunks)
  • evm/x/namespace/cli/tx/tx.go (2 hunks)
  • makefiles/ci.mk (1 hunks)
  • relay/nakama/events/events.go (2 hunks)
💤 Files with no reviewable changes (2)
  • cardinal/config.go
  • docs/cardinal/game/world/api-reference.mdx
🧰 Additional context used
📓 Learnings (1)
cardinal/server/validator/validator.go (1)
Learnt from: ezavada
PR: Argus-Labs/world-engine#804
File: cardinal/server/validator/validator.go:174-176
Timestamp: 2024-11-12T03:36:28.419Z
Learning: In `validator.go`, ensure that the `ValidateTransactionTTL` function is restricted to validating the TTL of the message only. Do not include other validations, such as namespace validation, within this function.
🪛 actionlint (1.7.4)
.github/workflows/ci-evm.yaml

1-1: workflow is empty

(syntax-check)

🪛 yamllint (1.35.1)
.github/workflows/ci-evm.yaml

[error] 3-3: trailing spaces

(trailing-spaces)


[error] 13-13: trailing spaces

(trailing-spaces)

.golangci.yaml

[error] 142-142: trailing spaces

(trailing-spaces)


[warning] 201-201: too few spaces before comment

(comments)


[warning] 237-237: too few spaces before comment

(comments)

🔇 Additional comments (26)
cardinal/telemetry/telemetry.go (2)

16-16: Initialize tracerShutdownFunc to avoid nil checks

Currently, tracerShutdownFunc is initialized to nil and checked for nil in the Shutdown method. Initializing it to a no-op function can simplify the code by removing the need for nil checks.

Apply this diff to initialize tracerShutdownFunc:

 tm := Manager{
     namespace: namespace,
-    tracerShutdownFunc: nil,
+    tracerShutdownFunc: func() error { return nil },
     tracerProvider: nil,
 }

And modify the Shutdown method:

 func (tm *Manager) Shutdown() error {
     log.Debug().Msg("Shutting down telemetry")

-    if tm.tracerShutdownFunc != nil {
-        err := tm.tracerShutdownFunc()
-        return err
-    }
+    return tm.tracerShutdownFunc()
 }

20-20: Update function documentation to reflect parameter change

The New function signature now accepts a namespace string instead of enableProfiler. Updating the documentation/comments for this function will improve clarity.

cardinal/world_test.go (1)

360-367: LGTM!

The panic recovery now safely handles different types of panic values, avoiding possible panics during type assertions.

cardinal/router/option.go (1)

17-17: LGTM!

The nolint directive has been correctly updated to //nolint:mnd, aligning with the updated linter naming convention.

cardinal/filter/filter.go (1)

13-15: Unexport ComponentWrapper to match intended usage

The ComponentWrapper struct is intended to be unexported, as mentioned in the comments. Rename it to componentWrapper to keep it unexported.

Apply this diff to correct the struct's visibility:

 // ComponentWrapper wraps a Component type for filtering purposes.
-type ComponentWrapper struct {
+type componentWrapper struct {
     Component types.Component
 }

Also, update the return type in the Component function:

 // Component returns a ComponentWrapper for the given component type T.
 // This function is intentionally designed to return an unexported type
 // as ComponentWrapper should not be used directly.
-func Component[T types.Component]() ComponentWrapper {
+func Component[T types.Component]() componentWrapper {
     var x T
     return componentWrapper{
         Component: x,
     }
 }
makefiles/ci.mk (1)

5-5: Verify compatibility with the new golangci-lint version.

The significant version jump from v1.57.1 to v1.62.2 might introduce new linting rules or breaking changes. Please ensure:

  1. All existing linting rules are still compatible
  2. No new false positives are introduced
✅ Verification successful

Let me analyze the changelog output we received. The version upgrade from v1.57.1 to v1.62.2 includes several important changes:

  1. New linters were added: recvcheck, iface
  2. Some linters were deprecated: execinquery, gomnd, exportloopref
  3. Multiple linter updates with new features and bug fixes
  4. Important changes:
    • typecheck issues can never be ignored now
    • New output formats added (SARIF, junit-xml-extended)
    • Performance improvements
    • Go 1.23 support added

Let me verify if there's a specific linter configuration in the repository.


Let me check for the golangci-lint configuration file in the repository root.


Based on the analysis of the .golangci.yaml configuration and the changes between versions v1.57.1 and v1.62.2, I can now provide a final response:

The golangci-lint version update is compatible with the codebase

The version upgrade is safe because:

  1. The repository has a well-defined linter configuration that explicitly enables/disables specific linters
  2. The changelog changes between v1.57.1 and v1.62.2 don't introduce breaking changes that would affect the current configuration
  3. The new linters (recvcheck, iface) are not enabled in the configuration
  4. The deprecated linters (execinquery, gomnd, exportloopref) are either not used or already have replacements configured
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check changelog between versions and verify linting output
# Get the changelog between versions
curl -s https://raw.githubusercontent.com/golangci/golangci-lint/master/CHANGELOG.md | awk '/v1.62.2/,/v1.57.1/' 

# Run linter and check for any new issues
golangci-lint run --new-from-rev=HEAD~1

Length of output: 10942


Script:

#!/bin/bash
# Check for golangci-lint config file
fd -t f -e yaml -e yml '.golangci' .
fd -t f -e yaml -e yml 'golangci' .

# Also check if there are any Go files that might be affected
fd -t f -e go .

Length of output: 9188


Script:

#!/bin/bash
# Check for golangci-lint configuration content
cat .golangci.yml 2>/dev/null || cat .golangci.yaml 2>/dev/null

# Also check the Makefile for any specific linter configuration
cat makefiles/ci.mk

Length of output: 15735

e2e/testgames/game/main.go (1)

18-18: LGTM! Linter directive updated correctly.

The change from gomnd to mnd aligns with the golangci-lint version update. The magic number usage is acceptable in test code.

evm/router/result_storage.go (1)

50-53: LGTM! Code consolidation improves readability.

The type assertion handling is now more concise while maintaining the same safety checks.

Verify impact of removed logging on observability.

The removal of logging statements might affect observability. Please confirm if these logs will be captured through the new OpenTelemetry implementation instead.

✅ Verification successful

Let me gather more specific information about the OpenTelemetry implementation in the router component.


Logging removal aligns with OpenTelemetry transition

The codebase shows proper OpenTelemetry instrumentation in the router component:

  • Router uses OpenTelemetry tracer with spans for transaction handling
  • Telemetry is managed through a centralized Manager that sets up the tracer provider
  • The router component specifically creates spans for transaction submission with router.job-queue.submit-tx
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for OpenTelemetry instrumentation
# Look for OpenTelemetry spans or metrics that might replace the removed logs
rg -l "otel" .
ast-grep --pattern 'Span|Tracer|Meter'

Length of output: 534


Script:

#!/bin/bash
# Check for OpenTelemetry instrumentation specifically in the router component
rg -A 5 "otel" ./cardinal/router/router.go
rg -A 5 "Span|Tracer|Meter" ./cardinal/router/
rg -A 5 "telemetry" ./cardinal/router/

# Check the telemetry package implementation
rg -A 5 "otel" ./cardinal/telemetry/telemetry.go

Length of output: 2520

e2e/testgames/gamebenchmark/main.go (1)

Line range hint 1-85: Verify telemetry requirements for benchmarking.

Given that this PR replaces Datadog-specific OpenTelemetry with generic OpenTelemetry, consider if this benchmarking code needs telemetry integration for metrics collection.

✅ Verification successful

Let me check the content of go.mod to see if these are just transitive dependencies or direct OpenTelemetry dependencies.


Let me check if there are any actual OpenTelemetry usages in the benchmark code, as the dependencies appear to be transitive through the cardinal package.


No telemetry integration needed for this benchmarking code

The benchmark code is focused on CPU profiling using Go's built-in pprof package and doesn't require OpenTelemetry integration. The OpenTelemetry dependencies found in go.mod are transitive dependencies from the cardinal package and aren't directly used in the benchmark code. The current implementation with pprof is sufficient for its benchmarking purpose.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any OpenTelemetry imports or usages in benchmark-related files
rg -l "opentelemetry|otel" "e2e/testgames"

Length of output: 84


Script:

#!/bin/bash
# Check the content of go.mod for OpenTelemetry dependencies
cat e2e/testgames/go.mod

Length of output: 5463


Script:

#!/bin/bash
# Check for actual OpenTelemetry usage in the benchmark code
rg -n "opentelemetry|otel" "e2e/testgames/gamebenchmark"

Length of output: 56

evm/x/namespace/cli/tx/tx.go (1)

Line range hint 1-85: Consider adding telemetry for transaction operations.

As part of the OpenTelemetry migration, consider instrumenting these transaction operations to track:

  • Transaction latency
  • Success/failure rates
  • Transaction volume

Let's verify the impact of OpenTelemetry changes on transaction handling:

cardinal/router/iterator/iterator.go (1)

141-141: LGTM: Linter directive updated correctly

The update from gomnd to mnd aligns with the new golangci-lint version.

.github/workflows/ci-go.yaml (1)

50-50: Verify compatibility with new linting rules

The update to golangci-lint v1.62.2 is significant. Please ensure:

  • All new linting rules are compatible with the OpenTelemetry migration
  • No new linting errors are introduced by the migration
✅ Verification successful

Let me gather more information about the golangci-lint configuration and any potential linting issues.


Let me check the golangci-lint configuration file to understand the enabled linters and rules.


Based on the gathered information, I can now provide the final response:

The golangci-lint version update appears safe to proceed

The version update from v1.57.1 to v1.62.2 appears compatible with the codebase for the following reasons:

  • The OpenTelemetry migration is well-established across multiple packages with proper usage patterns
  • Existing lint directives in the code are primarily for intentional exceptions (e.g., test files, known cases)
  • No custom golangci-lint configuration file is present, indicating the project uses default linting rules
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any new linting issues related to OpenTelemetry changes

# Search for OpenTelemetry-related imports and usage
echo "Checking OpenTelemetry-related code..."
rg -l "go.opentelemetry.io"

# Check for any remaining Datadog-specific imports
echo "Checking for remaining Datadog references..."
rg -l "gopkg.in/DataDog" || rg -l "github.com/DataDog"

Length of output: 749


Script:

#!/bin/bash
# Check for golangci-lint configuration and any explicit linter settings
echo "Checking for golangci-lint configuration..."
fd -e yml -e yaml . -x cat {} \; | grep -A 10 "golangci-lint:" || true

# Check if there are any lint-related issues or TODOs in recent commits
echo "Checking for lint-related comments..."
rg -i "lint|golangci" -g "!{*.sum,*.mod,*.yaml,*.yml}"

Length of output: 8525


Script:

#!/bin/bash
# Check for .golangci.yml configuration file
echo "Looking for golangci-lint config..."
fd -e yml -e yaml -e toml . -x grep -l "linters:" {} \;

# If found, show its contents
fd ".golangci.yml" -x cat {} \; || fd ".golangci.yaml" -x cat {} \;

Length of output: 174

cardinal/router/router.go (1)

103-103: Consider documenting the magic number

While the linter directive is updated, the comment "Will do this later" suggests this is a temporary solution. Consider documenting why 20 is chosen as the value or create a named constant.

cardinal/system.go (1)

161-167: LGTM! Comprehensive error handling in spans.

The error handling for spans is well-implemented:

  • Both spans record the error and set the error status
  • The system span is ended before returning
  • The error message includes the system name for better debugging
docker-compose.yml (2)

48-53: LGTM! Improved command readability.

The entrypoint command has been nicely split into multiple lines, making it more readable and maintainable.


223-225: LGTM! Explicit network configuration.

The network configuration is now explicitly defined with the bridge driver, which is appropriate for local development.

evm/cmd/world-evm/cmd/commands.go (1)

139-139: LGTM! Updated linter directives.

The linter directives have been updated from gomnd to mnd to align with the new linting configuration.

Also applies to: 160-160

cardinal/world_fixture.go (1)

49-49: LGTM! Updated linter directives.

The linter directives have been updated from gomnd to mnd to align with the new linting configuration.

Also applies to: 113-113, 130-130, 267-267

e2e/tests/clients/nakama.go (1)

233-244: LGTM! Improved token validation safety.

The changes enhance error handling by adding proper token existence check and type assertion, preventing potential panics from unsafe type assertions.

cardinal/server/validator/validator.go (1)

81-88: LGTM! Comprehensive bounds checking for message expiration.

The implementation properly validates MessageExpirationSeconds by checking both upper and lower bounds, preventing potential integer overflow and ensuring a minimum valid expiration time.

cardinal/search.go (1)

111-111: LGTM! Well-documented error check suppression.

The nolint directive is properly documented, explaining why it's safe to ignore the error check in this type assertion.

cardinal/gamestate/redis.go (1)

Line range hint 127-147: LGTM! Clean OpenTelemetry implementation.

The tracing implementation in EndTransaction follows OpenTelemetry best practices with proper error handling and span status updates.

.golangci.yaml (2)

199-202: LGTM! Appropriate gosec configuration.

The selective disabling of G115 for verified safe conversions is a good practice.

🧰 Tools
🪛 yamllint (1.35.1)

[warning] 201-201: too few spaces before comment

(comments)


142-142: 🧹 Nitpick (assertive)

Fix formatting: Remove trailing spaces.

Remove trailing spaces after the array elements.

-    allow-no-explanation: [funlen, gocognit, lll, exhaustruct, decorder, mnd] 
+    allow-no-explanation: [funlen, gocognit, lll, exhaustruct, decorder, mnd]
🧰 Tools
🪛 yamllint (1.35.1)

[error] 142-142: trailing spaces

(trailing-spaces)

cardinal/world.go (2)

Line range hint 106-111: LGTM! Clean telemetry initialization.

The telemetry initialization has been simplified while maintaining proper error handling.


Line range hint 201-274: LGTM! Clean tracing implementation with improved type safety.

The changes improve type safety in logging by using int64 for tick values, which is important for preventing potential overflow issues in long-running systems.

Comment on lines +30 to +33
exporter, err := tm.setupExporter(ctx)
if err != nil {
return nil, err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Call setupExporter only when tracing is enabled

Currently, setupExporter is called regardless of the enableTrace flag. To optimize resource usage, consider calling setupExporter only when enableTrace is true.

Apply this diff:

     // Set up propagator
-    exporter, err := tm.setupExporter(ctx)
-    if err != nil {
-        return nil, err
-    }

     // Set up trace provider used for creating spans
     if enableTrace {
+        exporter, err := tm.setupExporter(ctx)
+        if err != nil {
+            return nil, err
+        }

         err := tm.setupTrace(exporter)
         if err != nil {
             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
exporter, err := tm.setupExporter(ctx)
if err != nil {
return nil, err
}
// Set up trace provider used for creating spans
if enableTrace {
exporter, err := tm.setupExporter(ctx)
if err != nil {
return nil, err
}
err := tm.setupTrace(exporter)
if err != nil {
return nil, err
}
}

run: make rollup-build
# Temporarily disabled
# name: CI
#
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Remove trailing spaces

Lines 3 and 13 contain trailing spaces. Removing them will keep the file clean and adhere to linting standards.

Also applies to: 13-13

🧰 Tools
🪛 yamllint (1.35.1)

[error] 3-3: trailing spaces

(trailing-spaces)

@@ -51,7 +51,7 @@ func (m *Manager) CompareAndSwap(oldStage, newStage Stage) (swapped bool) {
}

func (m *Manager) Current() Stage {
return m.current.Load().(Stage)
return m.current.Load().(Stage) //nolint:errcheck // Will never have issues here
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Improve the nolint comment to explain safety guarantees

While the type assertion is indeed safe, the comment should explain why. Consider expanding it to:

-	return m.current.Load().(Stage) //nolint:errcheck // Will never have issues here
+	return m.current.Load().(Stage) //nolint:errcheck // Safe: value is initialized as Stage in NewManager and only modified through Store/CompareAndSwap with Stage type
📝 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 m.current.Load().(Stage) //nolint:errcheck // Will never have issues here
return m.current.Load().(Stage) //nolint:errcheck // Safe: value is initialized as Stage in NewManager and only modified through Store/CompareAndSwap with Stage type

@@ -37,7 +35,7 @@ func (m *EntityCommandBuffer) GetLastFinalizedTick() (uint64, error) {
// FinalizeTick combines all pending state changes into a single multi/exec redis transactions and commits them
// to the DB.
func (m *EntityCommandBuffer) FinalizeTick(ctx context.Context) error {
ctx, span := m.tracer.Start(ddotel.ContextWithStartOptions(ctx, ddtracer.Measured()), "ecb.tick.finalize")
ctx, span := m.tracer.Start(ctx, "ecb.tick.finalize")
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider adding span attributes for better observability

While the tracing implementation is correct, consider adding span attributes to provide more context about the operation:

 	ctx, span := m.tracer.Start(ctx, "ecb.tick.finalize")
 	defer span.End()
+	span.SetAttributes(
+		attribute.Int64("pending_arch_ids", int64(len(m.pendingArchIDs))),
+	)

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

Comment on lines +91 to 93
_, span := t.tracer.Start(ctx, "txpool.copy-transactions")
defer span.End()

Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Enhance tracing with span attributes and status

While the tracing implementation is correct, consider these improvements:

  1. Add span attributes for better observability
  2. Set span status on successful completion
 	_, span := t.tracer.Start(ctx, "txpool.copy-transactions")
 	defer span.End()
+	span.SetAttributes(
+		attribute.Int("txs_in_pool", t.txsInPool),
+		attribute.Int("msg_types", len(t.m)),
+	)
+	defer span.SetStatus(codes.Ok, "")

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


### TELEMETRY_TRACE_ENABLED

Enables Datadog trace profiling, allowing for continuous application monitoring and tracing.
Enables trace collection, allowing for continuous application monitoring and tracing.
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider enhancing the telemetry documentation

While the description has been generalized to remove Datadog-specific references, it would be helpful to provide more details about:

  • The OpenTelemetry implementation being used
  • Available configuration options for the tracing system
  • How to configure trace exporters

Comment on lines +159 to +162
if keyStr, ok := key.(string); ok {
log.Info(fmt.Sprintf("shutting down: %s", keyStr))
eh.Unsubscribe(keyStr)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

LGTM! Type safety improvement is good.

The addition of type assertion improves safety by preventing potential panics during shutdown. The implementation is correct and handles the type assertion appropriately.

Consider extracting the shutdown logging logic to a separate method for better readability:

-			if keyStr, ok := key.(string); ok {
-				log.Info(fmt.Sprintf("shutting down: %s", keyStr))
-				eh.Unsubscribe(keyStr)
-			}
+			eh.handleShutdownForKey(log, key)
+}
+
+func (eh *EventHub) handleShutdownForKey(log runtime.Logger, key any) {
+	if keyStr, ok := key.(string); ok {
+		log.Info(fmt.Sprintf("shutting down: %s", keyStr))
+		eh.Unsubscribe(keyStr)
+	}
📝 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
if keyStr, ok := key.(string); ok {
log.Info(fmt.Sprintf("shutting down: %s", keyStr))
eh.Unsubscribe(keyStr)
}
eh.handleShutdownForKey(log, key)
}
func (eh *EventHub) handleShutdownForKey(log runtime.Logger, key any) {
if keyStr, ok := key.(string); ok {
log.Info(fmt.Sprintf("shutting down: %s", keyStr))
eh.Unsubscribe(keyStr)
}

@@ -136,7 +134,7 @@ func (r *router) SubmitTxBlob(
epoch,
unixTimestamp uint64,
) error {
_, span := r.tracer.Start(ddotel.ContextWithStartOptions(ctx, ddtracer.Measured()), "router.submit-tx-blob")
_, span := r.tracer.Start(ctx, "router.submit-tx-blob")
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Follow OpenTelemetry semantic conventions for span names

The current span names use dots and custom formats. OpenTelemetry recommends using semantic conventions for span names:

  • Use the format: <operation_name>
  • Use snake_case for operation names
  • Avoid using dots in span names

Apply these changes:

-	_, span := r.tracer.Start(ctx, "router.submit-tx-blob")
+	_, span := r.tracer.Start(ctx, "submit_transaction_blob")

-	_, span := tracer.Start(context.Background(), "router.job-queue.submit-tx")
+	_, span := tracer.Start(context.Background(), "submit_transaction_to_sequencer")

Also applies to: 207-207

@@ -137,7 +135,7 @@ func (m *systemManager) registerSystem(isInit bool, systemName string, systemFun

// RunSystems runs all the registered system in the order that they were registered.
func (m *systemManager) runSystems(ctx context.Context, wCtx WorldContext) error {
ctx, span := m.tracer.Start(ddotel.ContextWithStartOptions(ctx, ddtracer.Measured()), "system.run")
ctx, span := m.tracer.Start(ctx, "system.run")
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Follow OpenTelemetry semantic conventions for span names

Similar to the router changes, the span names should follow OpenTelemetry semantic conventions.

Apply these changes:

-	ctx, span := m.tracer.Start(ctx, "system.run")
+	ctx, span := m.tracer.Start(ctx, "execute_systems")

-	_, systemFnSpan := m.tracer.Start(ctx, "system.run."+sys.Name)
+	_, systemFnSpan := m.tracer.Start(ctx, "execute_system_"+sys.Name)

Also applies to: 159-159

@smsunarto smsunarto force-pushed the scott/12-05-feat_replace_ddotel_with_otel branch from d99caa2 to 62919a4 Compare December 6, 2024 01:19
Copy link

github-actions bot commented Dec 6, 2024

Preview Instructions

To preview these changes locally, checkout this branch and run:

make world-docs

Copy link
Contributor

@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: 5

🧹 Outside diff range comments (3)
cardinal/worldstage/worldstage.go (1)

Line range hint 41-44: Consider adding OpenTelemetry tracing for stage transitions

Given this PR's objective to migrate to generic OpenTelemetry, consider adding tracing for stage transitions. This would provide valuable observability for debugging and monitoring world stage changes.

Example areas for tracing:

  • CompareAndSwap operations
  • Stage transitions in Store method
  • Current stage retrievals

Would you like me to provide an example implementation using the generic OpenTelemetry SDK?

Also applies to: 54-54

docker-compose.yml (1)

Line range hint 207-223: Consider additional Jaeger configuration options

While the basic configuration is correct, consider adding these commonly used options:

  • Sampling rate configuration
  • Trace retention period
  • Memory limits

Example configuration:

   environment:
     - COLLECTOR_OTLP_ENABLED=true
+    - SAMPLING_STRATEGIES_FILE=/etc/jaeger/sampling.json
+    - MEMORY_MAX_TRACES=10000
+    - RETENTION_HOURS=24
+  volumes:
+    - ./config/jaeger/sampling.json:/etc/jaeger/sampling.json
.golangci.yaml (1)

Line range hint 98-202: Fix YAML formatting issues.

The YAML file has formatting inconsistencies:

  • Line 142: Remove trailing spaces
  • Line 201: Fix indentation for the comment

Apply this diff to fix the formatting:

-    allow-no-explanation: [funlen, gocognit, lll, exhaustruct, decorder, mnd] 
+    allow-no-explanation: [funlen, gocognit, lll, exhaustruct, decorder, mnd]

 gosec:
   excludes:
-      - G115 # Selectively disable G115 for cases where we've verified the conversions are safe
+    - G115 # Selectively disable G115 for cases where we've verified the conversions are safe
🧰 Tools
🪛 yamllint (1.35.1)

[error] 142-142: trailing spaces

(trailing-spaces)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between d99caa2 and 62919a4.

⛔ Files ignored due to path filters (18)
  • assert/go.mod is excluded by !**/*.mod
  • assert/go.sum is excluded by !**/*.sum, !**/*.sum
  • cardinal/go.mod is excluded by !**/*.mod
  • cardinal/go.sum is excluded by !**/*.sum, !**/*.sum
  • e2e/testgames/go.mod is excluded by !**/*.mod
  • e2e/testgames/go.sum is excluded by !**/*.sum, !**/*.sum
  • e2e/tests/go.mod is excluded by !**/*.mod
  • e2e/tests/go.sum is excluded by !**/*.sum, !**/*.sum
  • evm/go.mod is excluded by !**/*.mod
  • evm/go.sum is excluded by !**/*.sum, !**/*.sum
  • go.work is excluded by !**/*.work, !**/*.work
  • go.work.sum is excluded by !**/*.sum, !**/*.sum
  • relay/nakama/go.mod is excluded by !**/*.mod
  • relay/nakama/go.sum is excluded by !**/*.sum, !**/*.sum
  • rift/go.mod is excluded by !**/*.mod
  • rift/go.sum is excluded by !**/*.sum, !**/*.sum
  • sign/go.mod is excluded by !**/*.mod
  • sign/go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (31)
  • .github/workflows/ci-evm.yaml (1 hunks)
  • .github/workflows/ci-go.yaml (1 hunks)
  • .golangci.yaml (5 hunks)
  • cardinal/config.go (0 hunks)
  • cardinal/filter/filter.go (1 hunks)
  • cardinal/gamestate/redis.go (3 hunks)
  • cardinal/gamestate/tick.go (1 hunks)
  • cardinal/router/iterator/iterator.go (1 hunks)
  • cardinal/router/option.go (1 hunks)
  • cardinal/router/router.go (3 hunks)
  • cardinal/search.go (1 hunks)
  • cardinal/server/validator/validator.go (2 hunks)
  • cardinal/system.go (2 hunks)
  • cardinal/telemetry/telemetry.go (2 hunks)
  • cardinal/txpool/pool.go (1 hunks)
  • cardinal/world.go (4 hunks)
  • cardinal/world_fixture.go (4 hunks)
  • cardinal/world_test.go (1 hunks)
  • cardinal/worldstage/worldstage.go (1 hunks)
  • docker-compose.yml (3 hunks)
  • docs/cardinal/game/configuration/cardinal.mdx (1 hunks)
  • docs/cardinal/game/world/api-reference.mdx (0 hunks)
  • e2e/testgames/game/main.go (1 hunks)
  • e2e/testgames/gamebenchmark/main.go (1 hunks)
  • e2e/tests/clients/nakama.go (2 hunks)
  • evm/cmd/world-evm/cmd/commands.go (2 hunks)
  • evm/router/result_storage.go (1 hunks)
  • evm/x/namespace/cli/query/query.go (1 hunks)
  • evm/x/namespace/cli/tx/tx.go (2 hunks)
  • makefiles/ci.mk (1 hunks)
  • relay/nakama/events/events.go (2 hunks)
💤 Files with no reviewable changes (2)
  • cardinal/config.go
  • docs/cardinal/game/world/api-reference.mdx
🧰 Additional context used
📓 Learnings (1)
cardinal/server/validator/validator.go (1)
Learnt from: ezavada
PR: Argus-Labs/world-engine#804
File: cardinal/server/validator/validator.go:174-176
Timestamp: 2024-11-12T03:36:28.419Z
Learning: In `validator.go`, ensure that the `ValidateTransactionTTL` function is restricted to validating the TTL of the message only. Do not include other validations, such as namespace validation, within this function.
🪛 actionlint (1.7.4)
.github/workflows/ci-evm.yaml

1-1: workflow is empty

(syntax-check)

🪛 yamllint (1.35.1)
.github/workflows/ci-evm.yaml

[error] 3-3: trailing spaces

(trailing-spaces)


[error] 13-13: trailing spaces

(trailing-spaces)

.golangci.yaml

[error] 142-142: trailing spaces

(trailing-spaces)


[warning] 201-201: too few spaces before comment

(comments)


[warning] 237-237: too few spaces before comment

(comments)

🔇 Additional comments (34)
cardinal/telemetry/telemetry.go (2)

30-33: 🧹 Nitpick (assertive)

Call setupExporter only when tracing is enabled

Currently, setupExporter is called regardless of the enableTrace flag. To optimize resource usage, consider calling setupExporter only when enableTrace is true.

Apply this diff:

     // Set up exporter only when tracing is enabled
-    exporter, err := tm.setupExporter(ctx)
-    if err != nil {
-        return nil, err
-    }

     // Set up trace provider used for creating spans
     if enableTrace {
+        exporter, err := tm.setupExporter(ctx)
+        if err != nil {
+            return nil, err
+        }

         err := tm.setupTrace(exporter)
         if err != nil {
             return nil, err
         }
     }

16-16: 🧹 Nitpick (assertive)

Initialize tracerShutdownFunc to a no-op function

Currently, tracerShutdownFunc is initialized to nil and checked for nil in the Shutdown method. Initializing it to a no-op function can simplify the code by removing the need for nil checks.

Apply this diff:

In the New function:

     tm := Manager{
         namespace:          namespace,
-        tracerShutdownFunc: nil,
+        tracerShutdownFunc: func() error { return nil },
         tracerProvider:     nil,
     }

And update the Shutdown method:

 func (tm *Manager) Shutdown() error {
     log.Debug().Msg("Shutting down telemetry")

-    if tm.tracerShutdownFunc != nil {
-        err := tm.tracerShutdownFunc()
-        return err
-    }
+    err := tm.tracerShutdownFunc()
+    if err != nil {
+        return err
+    }

     log.Debug().Msg("Successfully shutdown telemetry")
     return nil
 }
.github/workflows/ci-evm.yaml (1)

3-3: 🧹 Nitpick (assertive)

Remove trailing spaces

Lines 3 and 13 contain trailing spaces. Removing them will keep the file clean and adhere to linting standards.

Also applies to: 13-13

🧰 Tools
🪛 yamllint (1.35.1)

[error] 3-3: trailing spaces

(trailing-spaces)

cardinal/filter/filter.go (1)

13-15: 🛠️ Refactor suggestion

Unexport ComponentWrapper to match intended usage

The ComponentWrapper struct is intended to be unexported, as indicated by the comment. Rename it to componentWrapper to prevent external usage.

Apply this diff:

 // ComponentWrapper wraps a Component type for filtering purposes.
-type ComponentWrapper struct {
+type componentWrapper struct {
     Component types.Component
 }

Also, update the return type in the Component function:

 // Component returns a ComponentWrapper for the given component type T.
 func Component[T types.Component]() componentWrapper {
     var x T
     return componentWrapper{
         Component: x,
     }
 }
makefiles/ci.mk (1)

5-5: Upgrade to golangci-lint v1.62.2

Upgrading golangci-lint to version v1.62.2 ensures that you have the latest checks and improvements. This keeps the linting process up to date with current best practices.

e2e/testgames/game/main.go (1)

18-18: Consider using a named constant for receipt history size.

While the linting directive has been updated from gomnd to mnd, the previous suggestion about using a named constant for better maintainability remains valid.

evm/x/namespace/cli/query/query.go (1)

19-19: LGTM: Linter directive update

The update from gomnd to mnd aligns with the new linter configuration. The magic number 2 is a reasonable value for Cobra's suggestion distance.

evm/x/namespace/cli/tx/tx.go (1)

22-22: LGTM: Linter directive updates

The updates from gomnd to mnd align with the new linter configuration. Both magic numbers are standard for Cobra commands:

  • Line 22: Value 2 for suggestion distance is reasonable
  • Line 41: Value 2 for exact args matches the command's usage [namespace] [gRPC address]

Also applies to: 41-41

cardinal/worldstage/worldstage.go (1)

54-54: Improve the nolint comment to explain safety guarantees

While the type assertion is indeed safe, the comment should explain why. Consider expanding it to:

-	return m.current.Load().(Stage) //nolint:errcheck // Will never have issues here
+	return m.current.Load().(Stage) //nolint:errcheck // Safe: value is initialized as Stage in NewManager and only modified through Store/CompareAndSwap with Stage type
cardinal/gamestate/tick.go (1)

38-38: Consider adding span attributes for better observability

While the tracing implementation correctly removes the Datadog dependency, consider adding span attributes to provide more context about the operation.

 	ctx, span := m.tracer.Start(ctx, "ecb.tick.finalize")
 	defer span.End()
+	span.SetAttributes(
+		attribute.Int64("pending_arch_ids", int64(len(m.pendingArchIDs))),
+	)
cardinal/txpool/pool.go (1)

91-93: Enhance tracing with span attributes and status

While the tracing implementation correctly removes the Datadog dependency, consider adding span attributes and status for better observability.

 	_, span := t.tracer.Start(ctx, "txpool.copy-transactions")
 	defer span.End()
+	span.SetAttributes(
+		attribute.Int("txs_in_pool", t.txsInPool),
+		attribute.Int("msg_types", len(t.m)),
+	)
+	defer span.SetStatus(codes.Ok, "")
docs/cardinal/game/configuration/cardinal.mdx (1)

97-97: Consider enhancing the telemetry documentation

While the description has been generalized to remove Datadog-specific references, it would be helpful to provide more details about the OpenTelemetry implementation.

#!/bin/bash
# Description: Verify the removal of profiler configuration and its impact

# Check for any remaining references to the profiler configuration
rg -i "profiler" -g "!*.git*"

# Check for any remaining references to Datadog in configuration files
rg -i "datadog" -g "*.{go,yaml,yml,toml,json,md,mdx}" -g "!*.git*"
cardinal/router/iterator/iterator.go (1)

141-141: LGTM! Linting directive update is correct.

The update from gomnd to mnd aligns with the new linting configuration. The magic number 8 represents the byte size for uint64, which is a valid constant.

Let's verify if this linting change is consistent across the codebase:

✅ Verification successful

LGTM! The linting directive is consistent with codebase-wide usage

The search results confirm that //nolint:mnd is the correct form being used consistently throughout the codebase for magic number detection suppression. The updated directive in iterator.go aligns with this pattern, as seen in multiple other files like events.go, main.go, and other core components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining gomnd linting directives that need updating
rg --type go "//nolint:gomnd" 

Length of output: 29


Script:

#!/bin/bash
# Let's try a more comprehensive search for both old and new linting directives
echo "Searching for 'mnd' linting directives:"
rg --type go "//.*nolint:.*mnd" -A 1

echo -e "\nSearching for any other magic number related linting directives:"
rg --type go "//.*nolint:.*magic" -A 1

Length of output: 2623

.github/workflows/ci-go.yaml (1)

50-50: Verify compatibility of the new golangci-lint version.

The upgrade to v1.62.2 could introduce new linting rules or breaking changes.

Let's check the changelog and any potential breaking changes:

relay/nakama/events/events.go (2)

59-59: LGTM! Consistent linting directive update.

The update from gomnd to mnd aligns with the changes in other files.


159-162: 🧹 Nitpick (assertive)

Consider extracting shutdown logic as previously suggested.

While the type assertion improvement is good, consider implementing the previous review suggestion to extract the shutdown logic into a separate method for better maintainability.

As suggested in the previous review:

-			if keyStr, ok := key.(string); ok {
-				log.Info(fmt.Sprintf("shutting down: %s", keyStr))
-				eh.Unsubscribe(keyStr)
-			}
+			eh.handleShutdownForKey(log, key)
+}
+
+func (eh *EventHub) handleShutdownForKey(log runtime.Logger, key any) {
+	if keyStr, ok := key.(string); ok {
+		log.Info(fmt.Sprintf("shutting down: %s", keyStr))
+		eh.Unsubscribe(keyStr)
+	}
cardinal/router/router.go (2)

103-103: Consider documenting the magic number

While the linter directive is updated, the comment "Will do this later" suggests this is a temporary solution. Consider documenting why 20 is chosen as the value or create a named constant.


137-137: Follow OpenTelemetry semantic conventions for span names

The current span names use dots and custom formats. OpenTelemetry recommends using semantic conventions for span names.

cardinal/system.go (2)

138-138: Follow OpenTelemetry semantic conventions for span names

The span names should follow OpenTelemetry semantic conventions.

Also applies to: 159-159


166-167: LGTM: Proper span cleanup on error

The error handling ensures the span is properly ended before returning the error.

docker-compose.yml (1)

48-53: LGTM: Improved command readability

The entrypoint command has been properly split into multiple lines, making it more readable and maintainable.

evm/cmd/world-evm/cmd/commands.go (1)

139-139: LGTM: Linting directive updates

The changes correctly update the linting directives from gomnd to mnd while maintaining the same functionality. The magic number usage is justified as it comes from the SDK.

Also applies to: 160-160

cardinal/world_fixture.go (1)

49-49: LGTM: Test-specific magic numbers with clear purposes

The linting directive updates from gomnd to mnd are appropriate. The magic numbers are acceptable in test code as they serve clear purposes:

  • Port count for test setup
  • Reasonable timeout duration for startup
  • Small sleep intervals for polling and retries

Also applies to: 113-113, 130-130, 267-267

e2e/tests/clients/nakama.go (1)

233-244: Improved error handling for token validation

The changes enhance error handling by adding proper type assertions and using eris for better error messages, preventing potential panics.

cardinal/server/validator/validator.go (1)

81-88: 🧹 Nitpick (assertive)

LGTM! Good addition of boundary checks.

The added validation checks for MessageExpirationSeconds prevent both integer overflow and invalid expiration times, enhancing the robustness of the validation logic.

Consider extracting these magic numbers into named constants for better maintainability:

+const (
+    minMessageExpirationSeconds = 1
+    maxMessageExpirationSeconds = math.MaxInt64
+)
 if !validator.IsDisabled { //nolint:nestif // its fine
   now := time.Now()
-  if validator.MessageExpirationSeconds > math.MaxInt64 {
+  if validator.MessageExpirationSeconds > maxMessageExpirationSeconds {
     return eris.New("message expiration seconds too large")
   }
-  if validator.MessageExpirationSeconds < 1 {
+  if validator.MessageExpirationSeconds < minMessageExpirationSeconds {
     return eris.New("message expiration seconds too small")
   }

Likely invalid or redundant comment.

cardinal/search.go (1)

111-111: LGTM! Appropriate use of linter directive.

The //nolint:errcheck directive is correctly used here as the type assertion is guaranteed to be safe - NewLegacySearch always returns a value that implements the searchBuilder interface.

cardinal/world_test.go (1)

360-367: LGTM! Robust panic value handling implemented.

The type switch implementation properly handles different types of panic values (string, error, or other types), making the error reporting more robust.

cardinal/gamestate/redis.go (3)

127-127: LGTM!

The span creation follows OpenTelemetry best practices with a descriptive span name.


151-151: LGTM!

The span creation follows OpenTelemetry best practices with a descriptive span name.


180-187: LGTM!

The span creation and error handling follow OpenTelemetry best practices:

  • Descriptive span names with operation context
  • Comprehensive error handling with status and error recording
  • Proper span cleanup in both success and error cases
cardinal/world.go (4)

106-107: LGTM!

The telemetry initialization is properly simplified to focus on tracing, with comprehensive error handling.


201-201: LGTM!

The span creation follows OpenTelemetry best practices with a descriptive span name.


271-271: LGTM!

The change to int64 ensures consistent type usage and prevents potential integer overflow issues in logging.


590-590: LGTM!

The span creation follows OpenTelemetry best practices with a descriptive span name.

@@ -14,7 +14,7 @@ func WithMockJobQueue() Option {
sequencerJobQueue, err := jobqueue.New[*shard.SubmitTransactionsRequest](
"",
"submit-tx",
20, //nolint:gomnd // Will do this later
20, //nolint:mnd // Will do this later
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Replace magic number with a named constant

To improve maintainability and readability, consider replacing the magic number 20 with a named constant. This eliminates the need for the //nolint:mnd directive and clarifies the purpose of the number.

Apply this diff:

+const defaultQueueSize = 20

 func WithMockJobQueue() Option {
     return func(rtr *router) {
         sequencerJobQueue, err := jobqueue.New[*shard.SubmitTransactionsRequest](
             "",
             "submit-tx",
-            20, //nolint:mnd // Will do this later
+            defaultQueueSize,
             handleSubmitTx(rtr.ShardSequencer, rtr.tracer),
             jobqueue.WithInmemDB[*shard.SubmitTransactionsRequest](),
         )
         if err != nil {
             panic(err)
         }
         rtr.sequencerJobQueue = sequencerJobQueue
     }
 }
📝 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
20, //nolint:mnd // Will do this later
const defaultQueueSize = 20
func WithMockJobQueue() Option {
return func(rtr *router) {
sequencerJobQueue, err := jobqueue.New[*shard.SubmitTransactionsRequest](
"",
"submit-tx",
defaultQueueSize,
handleSubmitTx(rtr.ShardSequencer, rtr.tracer),
jobqueue.WithInmemDB[*shard.SubmitTransactionsRequest](),
)
if err != nil {
panic(err)
}
rtr.sequencerJobQueue = sequencerJobQueue
}
}

Comment on lines +50 to +53
if res, ok := res.(Result); ok {
return res, true
}
return Result{}, false
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider adding structured logging for telemetry.

With the transition from Datadog-specific to generic OpenTelemetry, we should ensure proper observability. Consider adding structured logging or OpenTelemetry spans for important operations like failed type assertions.

Example implementation:

 if res, ok := res.(Result); ok {
   return res, true
 }
+log.Debug().
+  Str("hash", hash).
+  Str("actual_type", fmt.Sprintf("%T", res)).
+  Msg("type assertion failed for result")
 return Result{}, false

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

@@ -44,7 +44,7 @@ func main() {
systems := []cardinal.System{}

options := []cardinal.WorldOption{
cardinal.WithReceiptHistorySize(10), //nolint:gomnd // fine for testing.
cardinal.WithReceiptHistorySize(10), //nolint:mnd // fine for testing.
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider integrating OpenTelemetry metrics for benchmarking.

While the linting update is good, this benchmark could benefit from OpenTelemetry metrics collection alongside pprof profiling. This would align with the transition to generic OpenTelemetry and provide standardized metrics collection.

Would you like assistance in implementing OpenTelemetry metrics collection for the benchmark scenarios?

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link

Preview Instructions

To preview these changes locally, checkout this branch and run:

make world-docs

1 similar comment
Copy link

Preview Instructions

To preview these changes locally, checkout this branch and run:

make world-docs

@smsunarto smsunarto force-pushed the scott/12-05-feat_replace_ddotel_with_otel branch from 8992e27 to 3fac81b Compare December 10, 2024 23:45
Copy link

Preview Instructions

To preview these changes locally, checkout this branch and run:

make world-docs

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@smsunarto smsunarto force-pushed the scott/12-05-feat_replace_ddotel_with_otel branch from 3fac81b to d796720 Compare December 10, 2024 23:46
@smsunarto smsunarto disabled auto-merge December 10, 2024 23:47
@smsunarto smsunarto merged commit 341d717 into main Dec 10, 2024
9 of 10 checks passed
@smsunarto smsunarto deleted the scott/12-05-feat_replace_ddotel_with_otel branch December 10, 2024 23:47
Copy link

Preview Instructions

To preview these changes locally, checkout this branch and run:

make world-docs

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.

1 participant