-
Notifications
You must be signed in to change notification settings - Fork 614
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(prover): integrate sentry to monitor error logs & panic events #1477
base: develop
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## develop #1477 +/- ##
===========================================
+ Coverage 52.78% 53.52% +0.74%
===========================================
Files 157 155 -2
Lines 12652 11902 -750
===========================================
- Hits 6678 6371 -307
+ Misses 5392 4990 -402
+ Partials 582 541 -41
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
2f49863
to
43fba89
Compare
WalkthroughThe changes in this pull request involve modifications to configuration files and structures related to the prover and its components. Key updates include the addition of a new Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
🧹 Outside diff range and nitpick comments (14)
prover/src/version.rs (3)
3-4
: Add documentation for the version format.
Consider adding a doc comment explaining the expected format of RELEASE_VERSION
and the meaning of each component in DEFAULT_VERSION
.
+/// Environment variable containing the release version in the format "vX.Y.Z-<metadata>-<git_rev>-<zk_version>"
static RELEASE_VERSION: Option<&str> = option_env!("RELEASE_VERSION");
+/// Default version string used when RELEASE_VERSION is not set
const DEFAULT_VERSION: &str = "v0.0.0-unknown-000000-000000";
6-8
: Add documentation for public functions.
Both public functions need documentation explaining their purpose and return types.
+/// Returns the current version as a String, either from RELEASE_VERSION or the default version
pub fn get_version() -> String {
RELEASE_VERSION.unwrap_or(DEFAULT_VERSION).to_string()
}
+/// Returns the current version as a Cow<str>, avoiding allocation when possible
+/// by returning a borrowed reference to the static version string
pub fn get_version_cow() -> Cow<'static, str> {
let v = RELEASE_VERSION.unwrap_or(DEFAULT_VERSION);
std::borrow::Cow::Borrowed(v)
}
Also applies to: 10-13
22-26
: Consider removing unnecessary logger initialization.
The logger initialization appears unnecessary for version-related tests. Consider removing it unless there's a specific reason for logging in these tests.
- #[ctor::ctor]
- fn init() {
- crate::utils::log_init(None);
- log::info!("logger initialized");
- }
prover/src/coordinator_client/types.rs (1)
55-55
: Consider documenting the Sentry integration.
Since this is part of a new monitoring feature, it would be helpful to add documentation about the Sentry endpoint's purpose and usage.
Add a doc comment above the field:
pub struct LoginResponseData {
pub time: String,
pub token: String,
+ /// Optional Sentry DSN endpoint for error monitoring.
+ /// When provided, the prover will initialize Sentry with this endpoint.
pub sentry_endpoint: Option<String>,
}
prover/src/coordinator_client/errors.rs (1)
89-100
: Consider adding more test cases for comprehensive coverage.
While the current test is good, consider adding tests for:
- Error message formatting
- Different context chains
- Error comparison/matching
Example additional test:
#[test]
fn test_error_display() {
let err = GetEmptyTaskError;
assert_eq!(err.to_string(), "get empty task");
}
prover/src/task_processor.rs (1)
19-27
: LGTM: Clean implementation of graceful shutdown mechanism
The addition of the should_stop
closure parameter provides a clean way to control the task processing lifecycle externally. The logging is appropriate for operational visibility.
Consider adding more context to the stop message:
- log::info!("task processor should stop.");
+ log::info!("Task processor received stop signal, shutting down gracefully.");
prover/src/coordinator_client.rs (2)
95-95
: Consider adding debug logging for Sentry endpoint configuration.
While the implementation is correct, adding debug logging would help with observability when the Sentry endpoint is configured or filtered out.
- self.sentry_endpoint = r.sentry_endpoint.filter(|s| !s.is_empty());
+ self.sentry_endpoint = r.sentry_endpoint.filter(|s| !s.is_empty());
+ if let Some(endpoint) = &self.sentry_endpoint {
+ log::debug!("Sentry endpoint configured: {}", endpoint);
+ }
146-148
: Consider renaming method for consistency.
While the implementation is correct, consider renaming the method from get_sentry_dsn
to get_sentry_endpoint
to maintain consistency with the field name. This would make the code more maintainable and reduce confusion.
- pub fn get_sentry_dsn(&self) -> Option<String> {
+ pub fn get_sentry_endpoint(&self) -> Option<String> {
self.sentry_endpoint.clone()
}
prover/src/coordinator_client/api.rs (2)
72-80
: LGTM! Consider enhancing error context and logging.
The error handling implementation looks good, but could be improved in a few ways:
Consider these improvements:
- let response = self
- .post_with_token::<GetTaskRequest, Response<GetTaskResponseData>>(method, req, token)
- .await?;
-
- if response.errcode == ErrorCode::ErrCoordinatorEmptyProofData {
- log::info!("coordinator return empty task");
- return Err(anyhow::anyhow!(GetEmptyTaskError));
- }
- Ok(response)
+ let response = self
+ .post_with_token::<GetTaskRequest, Response<GetTaskResponseData>>(method, req, token)
+ .await?;
+
+ if response.errcode == ErrorCode::ErrCoordinatorEmptyProofData {
+ log::info!(
+ "Coordinator returned empty task. Request ID: {:?}",
+ req.id
+ );
+ return Err(GetEmptyTaskError.into());
+ }
+ Ok(response)
The suggested changes:
- Add more context to the log message including the request ID
- Use
.into()
for more idiomatic error conversion
72-80
: Consider standardizing error handling and monitoring patterns.
Since this PR is about Sentry integration, consider these architectural improvements:
-
Standardize error handling across methods:
- Create an enum for all possible API errors
- Use thiserror for deriving Error implementations
- Add context to errors using error wrapping
-
Enhance logging for better monitoring:
- Add structured logging fields (request_id, method, status)
- Consider using tracing instead of log for better context
-
Add Sentry integration points:
- Capture errors with appropriate severity levels
- Include relevant context (request details, error codes)
- Group related errors for better tracking
Example structured logging pattern:
log::info!(
target: "coordinator_client",
"Task status: empty; request_id={}; method={}",
req.id,
method
);
prover/src/prover.rs (1)
22-22
: Add documentation for the public field.
Since coordinator_client
is now part of the public API, please add documentation explaining its purpose, usage guidelines, and any threading/borrowing considerations due to the RefCell
wrapper.
Add rustdoc comments:
+ /// The coordinator client used for task management and Sentry error tracking.
+ ///
+ /// This field is wrapped in a `RefCell` to allow interior mutability while maintaining
+ /// the Rust ownership rules. External users should ensure proper borrowing to avoid
+ /// runtime panic.
pub coordinator_client: RefCell<CoordinatorClient<'a>>,
prover/src/types.rs (1)
269-277
: Enhance test coverage with doc tests.
While the current test covers basic functionality, consider adding doc tests for better documentation and usage examples:
Add the following doc tests to the ProverType
enum:
/// Represents different types of provers
///
/// # Examples
///
/// ```
/// use prover::types::ProverType;
///
/// assert_eq!(ProverType::Chunk.to_string(), "Chunk");
/// assert_eq!(ProverType::Batch.to_string(), "Batch");
/// ```
pub enum ProverType {
// ...
}
prover/src/utils.rs (1)
43-58
: Simplify the return type of get_environment
The get_environment
function currently returns a Cow<'static, str>
, but all possible return values are string literals with a 'static
lifetime. Returning a &'static str
directly simplifies the code without impacting functionality.
Consider updating the function signature and return statement:
-pub fn get_environment() -> Cow<'static, str> {
+pub fn get_environment() -> &'static str {
let env: &'static str = match std::env::var("CHAIN_ID") {
Ok(chain_id) => match chain_id.as_str() {
"534352" => ENV_MAINNET,
"534351" => ENV_SEPOLIA,
_ => ENV_DEVNET,
},
Err(_) => ENV_UNKNOWN,
};
- std::borrow::Cow::Borrowed(env)
-}
+ env
+}
prover/src/main.rs (1)
83-89
: Adjust the log message to prevent redundant logging.
The log message "prover start successfully..." is inside the start_loop
function. Since start_loop
is called within a loop, this message will be logged on each iteration, which may clutter the logs and make it harder to track the actual start-up event.
Consider moving this log statement outside the start_loop
function or modifying it to reflect re-initialization when applicable.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
prover/Cargo.lock
is excluded by!**/*.lock
📒 Files selected for processing (18)
- coordinator/conf/config.json (1 hunks)
- coordinator/internal/config/config.go (1 hunks)
- coordinator/internal/controller/api/auth.go (3 hunks)
- coordinator/internal/middleware/login_jwt.go (1 hunks)
- coordinator/internal/types/auth.go (1 hunks)
- prover/Cargo.toml (2 hunks)
- prover/Makefile (1 hunks)
- prover/src/config.rs (2 hunks)
- prover/src/coordinator_client.rs (4 hunks)
- prover/src/coordinator_client/api.rs (1 hunks)
- prover/src/coordinator_client/errors.rs (2 hunks)
- prover/src/coordinator_client/types.rs (1 hunks)
- prover/src/main.rs (4 hunks)
- prover/src/prover.rs (1 hunks)
- prover/src/task_processor.rs (2 hunks)
- prover/src/types.rs (3 hunks)
- prover/src/utils.rs (2 hunks)
- prover/src/version.rs (1 hunks)
🔇 Additional comments (30)
coordinator/conf/config.json (2)
20-22
: LGTM: Time parameters reorganization
The time-related parameters have been logically reorganized under the prover_manager section while maintaining their original values, ensuring no functional changes.
23-23
: Verify default Sentry configuration
The empty default for prover_sentry_endpoint
is appropriate for optional Sentry integration. However, let's verify that the application handles this empty default gracefully.
✅ Verification successful
Let me gather more information about how the Sentry endpoint is used in the codebase.
Let me check the login response type definition and how the Sentry endpoint is used in the auth flow.
Based on the code analysis, I can now provide the final response:
Empty Sentry endpoint is handled appropriately
The empty default for prover_sentry_endpoint
is properly handled in the codebase:
- The
LoginSchema
struct hassentry_endpoint
marked asomitempty
, meaning it won't appear in JSON if empty - The endpoint is simply passed through from config to login response without any validation requirements
- No initialization or error handling is required since Sentry integration is optional
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify proper handling of empty Sentry endpoint in the codebase
# Check how the empty Sentry endpoint is handled
echo "Checking Sentry endpoint handling..."
rg -A 5 "prover_sentry_endpoint|ProverSentryEndpoint"
# Look for any error handling or validation related to Sentry configuration
echo "Checking Sentry-related error handling..."
rg -A 5 "sentry\.(New|Init|Configure)"
Length of output: 1386
Script:
#!/bin/bash
# Let's check for any Sentry initialization or error handling patterns
rg -l "sentry"
# Check the auth response struct to understand how the endpoint is used
ast-grep --pattern 'type LoginResponse struct {
$$$
}'
# Look for any conditional checks around Sentry usage
rg "if.*[Ss]entry" -A 3
Length of output: 517
Script:
#!/bin/bash
# Check the login response type in auth types
cat coordinator/internal/types/auth.go
# Check how the auth handler uses this configuration
rg -A 10 "func.*Login" coordinator/internal/controller/api/auth.go
Length of output: 4190
prover/src/version.rs (1)
1-35
: Verify version usage in Sentry integration.
Since this PR is about Sentry integration, we should verify that the version information is properly utilized in error reporting.
✅ Verification successful
Version information is properly integrated with Sentry initialization
The verification confirms that version information is correctly utilized in Sentry integration:
version::get_version_cow()
is used inprover/src/main.rs
to set the release version during Sentry initialization- The version is set via
release
field insentry::ClientOptions
- The implementation follows Sentry's best practices by including both version and environment information
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if version information is used in Sentry configuration or error reporting
# Test: Search for version usage in Sentry-related code
echo "Searching for version usage in Sentry configuration..."
rg -l "get_version|RELEASE_VERSION" --type rust
# Test: Search for Sentry initialization code that might use version info
echo "Searching for Sentry initialization..."
rg "sentry::init" --type rust -A 5
Length of output: 723
coordinator/internal/middleware/login_jwt.go (1)
27-27
: LGTM! Good architectural improvement.
Moving the login response handling to the Auth controller improves separation of concerns and centralizes authentication logic.
Let's verify the security implementation of the new login response handler:
✅ Verification successful
Security implementation verified - change is safe
The LoginResponse implementation in the Auth controller is secure and properly structured:
- It includes the required security token
- Adds Sentry endpoint from a controlled config source
- Uses proper success response rendering
- Maintains JWT authentication flow integrity with proper middleware configuration
The architectural change improves the codebase by:
- Centralizing authentication response handling in the Auth controller
- Maintaining consistent security token handling
- Properly integrating Sentry monitoring capabilities
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the security implementation of LoginResponse
# Test 1: Check if the new LoginResponse properly handles sensitive data
echo "Checking LoginResponse implementation..."
ast-grep --pattern 'func (a *AuthController) LoginResponse($_, $_) {
$$$
}'
# Test 2: Verify error handling in the login flow
echo "Checking error handling in login flow..."
rg -A 5 "LoginResponse.*error"
# Test 3: Look for any security-related tests
echo "Checking test coverage..."
fd -e go -e test --exec rg -l "TestLogin.*Response"
Length of output: 409
Script:
#!/bin/bash
# Let's try a different approach to locate and analyze the LoginResponse implementation
# Find all files containing LoginResponse
echo "Files containing LoginResponse:"
rg -l "LoginResponse"
# Look for the actual implementation with context
echo -e "\nLoginResponse implementation with context:"
rg -B 3 -A 10 "type.*LoginResponse|func.*LoginResponse"
# Check the auth controller implementation
echo -e "\nAuth controller implementation:"
rg -B 3 -A 10 "type.*AuthController|func.*\(a \*AuthController\)"
# Check for JWT middleware configuration
echo -e "\nJWT middleware configuration:"
rg -B 3 -A 10 "jwt\.New|jwt\.Auth"
Length of output: 9847
prover/Makefile (2)
41-41
: LGTM! Clean modification of the prover target.
The prover target now correctly uses the consolidated RELEASE_VERSION
environment variable for the build process.
38-39
: LGTM! Verify version string format across the codebase.
The introduction of RELEASE_VERSION
improves version handling by combining all version components into a single string.
Let's verify the version string format usage:
✅ Verification successful
Let me gather more information about how the version string is used in the Rust files to ensure consistency.
Version string format is correctly implemented and consistent
The verification shows that:
- The
RELEASE_VERSION
from Makefile is properly consumed inprover/src/version.rs
usingoption_env!
- A sensible default version format (
v0.0.0-unknown-000000-000000
) is provided - The version string components (
GO_TAG-GIT_REV-ZK_VERSION
) are consistently used across the codebase - Version handling is properly tested with default values
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify version string format usage across the codebase
# Test 1: Check version string format in version-related files
echo "Checking version string format in version-related files..."
rg -l "version|Version" --type rust
# Test 2: Check if the version components are used consistently
echo "Checking version components usage..."
rg -A 2 "(GO_TAG|GIT_REV|ZK_VERSION)"
Length of output: 2225
Script:
#!/bin/bash
# Check how RELEASE_VERSION is used in Rust files
echo "Checking RELEASE_VERSION usage in Rust files..."
rg -A 3 "RELEASE_VERSION|release_version" --type rust
# Check version string format in version.rs
echo "Checking version.rs content..."
cat prover/src/version.rs
# Check if there are any other version-related environment variables
echo "Checking other version-related env vars..."
rg -A 2 "env!.*version" --type rust
Length of output: 1930
prover/Cargo.toml (2)
52-52
: LGTM: regex dependency.
The regex dependency is appropriate for the partner name generation functionality mentioned in the summary.
23-24
: Consider consolidating logging dependencies.
The project now has multiple logging libraries: log
, env_logger
, and alterable_logger
. While this isn't necessarily problematic, it could lead to confusion about which logging implementation should be used where.
Let's check the usage of these logging libraries:
✅ Verification successful
Let me gather more information about the logging usage to make a more informed decision.
No consolidation needed - logging dependencies serve different purposes
The logging setup is well-structured and each dependency serves a specific purpose:
log
crate provides the logging facade/interface (used vialog::info!
, etc.)env_logger
is used for initial configuration via environment variablesalterable_logger
is used for runtime log configuration inutils.rs
The multiple logging libraries are not redundant - they work together as part of a complete logging system where:
log
provides the APIenv_logger
handles environment-based configurationalterable_logger
enables dynamic logging level changes
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check usage of different logging implementations
echo "Checking logging implementations usage:"
rg -A 2 "use (log|env_logger|alterable_logger)"
Length of output: 261
Script:
#!/bin/bash
# Check for log macros usage
echo "Checking log macro usage:"
rg "log::(error|warn|info|debug|trace)!"
# Check for alterable_logger usage
echo -e "\nChecking alterable_logger usage:"
rg "alterable_logger"
# Check if env_logger is initialized
echo -e "\nChecking env_logger initialization:"
rg "env_logger::(init|try_init|Builder|from_env)"
Length of output: 7560
prover/src/coordinator_client/types.rs (2)
55-55
: Verify error handling for invalid Sentry endpoints.
Since the Sentry endpoint is crucial for error monitoring, ensure proper validation and error handling is implemented where this field is consumed.
Let's check for endpoint validation:
#!/bin/bash
# Description: Look for endpoint validation in prover initialization
# Test: Search for Sentry initialization code that might validate the endpoint
rg -A 10 "sentry.*init|init.*sentry"
55-55
: LGTM! Well-structured Sentry endpoint integration.
The addition of sentry_endpoint
as Option<String>
is well-designed because:
- It maintains backward compatibility through the
Option
type - It properly integrates with the existing serialization framework
- It follows Rust naming conventions
Let's verify the coordinator side implementation:
✅ Verification successful
Sentry endpoint integration is properly implemented across the stack
The verification confirms the Sentry endpoint integration is complete and correct:
- Coordinator properly configures the endpoint in
coordinator/conf/config.json
viaprover_sentry_endpoint
setting - Coordinator includes the endpoint in login response through
coordinator/internal/types/auth.go
- Prover correctly handles the endpoint in
coordinator_client.rs
:- Stores it in the client state
- Filters out empty strings
- Properly propagates it through the login response flow
The implementation maintains backward compatibility and follows best practices in both Go and Rust codebases.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the coordinator's login response includes sentry endpoint
# Test 1: Check if coordinator config includes sentry endpoint
rg -A 5 "sentry.*endpoint"
# Test 2: Verify login response construction in auth controller
ast-grep --pattern 'fn login($$$) {
$$$
sentry$$$
$$$
}'
Length of output: 779
Script:
#!/bin/bash
# Let's search for sentry endpoint configuration and usage patterns
# Check for sentry endpoint configuration
rg -A 5 "sentry.*endpoint|SENTRY.*ENDPOINT"
# Check for login response construction patterns
rg -A 10 "LoginResponseData|login_response"
# Look for sentry configuration in coordinator configs
fd -e toml -e yaml -e json --exec grep -l "sentry"
Length of output: 5996
coordinator/internal/config/config.go (1)
27-28
: LGTM! Well-documented configuration field.
The new ProverSentryEndpoint
field is clearly documented and properly integrated into the configuration structure.
prover/src/coordinator_client/errors.rs (2)
78-87
: LGTM! Good test setup practice.
The test initialization is well-structured with proper logging setup.
Line range hint 58-101
: Verify error integration with Sentry.
Let's ensure this new error type is properly captured by Sentry's error reporting.
✅ Verification successful
Let me check the Sentry integration details in these files to verify the error handling setup.
Error types are properly integrated with Sentry error reporting system
The error types are well-integrated with the error reporting system:
- Sentry is properly initialized with custom logging setup in
utils.rs
- Both
GetEmptyTaskError
andProofStatusNotOKError
are handled appropriately intask_processor.rs
with proper error level classification:GetEmptyTaskError
is logged as info level (expected case)ProofStatusNotOKError
is logged as info level (expected case)- All other errors are logged as error level and will be captured by Sentry
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for Sentry error handling setup and integration
rg -l "sentry" --type rust
Length of output: 137
Script:
#!/bin/bash
# Check Sentry initialization and error handling patterns
rg "sentry" -A 5 --type rust
# Also check for error handling patterns specific to these error types
rg "GetEmptyTaskError|ProofStatusNotOKError" -A 5 --type rust
Length of output: 8258
coordinator/internal/types/auth.go (1)
27-29
: LGTM! The struct changes look good.
The addition of SentryEndpoint
with proper JSON tags and optional handling is well-implemented.
coordinator/internal/controller/api/auth.go (4)
6-6
: LGTM: Import changes are appropriate.
The new imports for time
and commonTypes
are necessary for the new LoginResponse
method implementation.
Also applies to: 12-13
22-22
: LGTM: AuthController struct field addition is well-designed.
The new cfg
field provides access to configuration settings, which is necessary for the Sentry integration.
29-29
: LGTM: Constructor properly initializes the new field.
The cfg
field is correctly initialized in the constructor, maintaining the expected initialization pattern.
107-115
: Verify security implications of exposing Sentry endpoint.
The LoginResponse
method includes the Sentry endpoint in the response. Please verify that this is intentionally exposed to clients and doesn't pose any security risks.
✅ Verification successful
Exposing Sentry endpoint in login response is safe - used for monitoring
Based on the codebase analysis, the Sentry endpoint exposure is an intentional and safe design choice:
-
The Sentry endpoint is used for monitoring/observability purposes, as evidenced by:
- It's part of the monitoring infrastructure alongside OpenTelemetry and Prometheus
- The endpoint is optional (
omitempty
JSON tag) and filtered if empty - The prover client only uses it for monitoring via
get_sentry_dsn()
-
The implementation has proper controls:
- The endpoint is only exposed after successful authentication
- The value comes from a controlled configuration (
ProverSentryEndpoint
) - It's specifically designed for prover monitoring integration
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if the Sentry endpoint is exposed elsewhere in the codebase
# or if there are any security-related comments about it
echo "Checking for other instances of Sentry endpoint exposure..."
rg -i "sentry.*endpoint" -A 5 -B 5
echo "Checking for security-related comments about Sentry..."
rg -i "sentry.*security|security.*sentry" -A 5 -B 5
Length of output: 6691
Script:
#!/bin/bash
# Let's check for any documentation or comments about the Sentry endpoint usage
echo "Checking documentation and comments..."
rg -i "sentry" "README|\.md$"
# Check the configuration and initialization of Sentry endpoint
echo "Checking Sentry configuration..."
ast-grep --pattern 'ProverSentryEndpoint'
# Check if there are any access controls or authentication checks before exposing the endpoint
echo "Checking auth controls..."
rg -i "auth.*sentry|sentry.*auth" -A 5 -B 5
# Check if this is used for monitoring/observability
echo "Checking monitoring usage..."
rg -i "monitoring|observability|telemetry" -A 3 -B 3
Length of output: 23170
prover/src/config.rs (1)
2-2
: LGTM: Appropriate use of the regex crate
The addition of the regex crate is appropriate for the pattern matching requirements.
prover/src/task_processor.rs (2)
1-5
: LGTM: Imports are well-organized
The new imports are correctly structured and necessary for the enhanced error handling capabilities.
Line range hint 30-40
: Verify error handling coverage
Let's ensure all error scenarios are properly handled and will be tracked by Sentry.
✅ Verification successful
Error handling appears comprehensive and well-structured
The error handling implementation is appropriate and follows consistent patterns across the codebase:
GetEmptyTaskError
andProofStatusNotOKError
are properly defined custom errors incoordinator_client/errors.rs
and used consistently- Error logging follows a clear severity pattern:
- Empty tasks and proof status issues are logged as
info
since they are expected scenarios - Unexpected errors are properly escalated to
error
level
- Empty tasks and proof status issues are logged as
- The panic scenarios found are in appropriate locations:
- Invalid prover type validation (types.rs)
- Parameter loading failures (verifier.rs)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other error handling patterns in the codebase to ensure consistency
rg -A 2 "log::(error|warn|info).*err" --type rust
# Look for potential panic scenarios that should be handled
ast-grep --pattern 'panic!($$$)'
# Check for other instances of these error types to ensure consistent handling
rg "GetEmptyTaskError|ProofStatusNotOKError" --type rust
Length of output: 2932
prover/src/coordinator_client.rs (4)
17-17
: LGTM: Error type export addition is appropriate.
The addition of GetEmptyTaskError
to public exports enhances error handling capabilities.
22-22
: LGTM: Well-structured field addition.
The sentry_endpoint
field is appropriately defined as Option<String>
and follows Rust's encapsulation principles.
50-50
: LGTM: Proper initialization in constructor.
The sentry_endpoint
is correctly initialized to None
in the constructor.
22-22
: Verify Sentry integration consistency across the codebase.
Let's ensure the Sentry integration is consistent and properly initialized across the codebase.
Also applies to: 95-95, 146-148
✅ Verification successful
Let me gather more information about the Sentry implementation details.
Sentry integration is properly implemented and consistent
The Sentry integration follows a clean pattern:
- Single initialization point in
main.rs
- Consistent endpoint configuration through
coordinator_client
- No duplicate configurations or initialization found
- Proper optional handling with empty string checks
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for consistent Sentry integration patterns
# Test 1: Check for other Sentry endpoint configurations
echo "Checking for Sentry endpoint configurations..."
rg -l "sentry.*endpoint" --type rust
# Test 2: Check for Sentry initialization patterns
echo "Checking for Sentry initialization..."
rg -l "sentry::init" --type rust
# Test 3: Check for potential duplicate configurations
echo "Checking for potential duplicate configurations..."
ast-grep --pattern 'sentry_endpoint: Option<String>'
Length of output: 516
Script:
#!/bin/bash
# Check the actual implementation details
# Check how sentry_endpoint is used in coordinator_client
echo "Checking coordinator_client usage..."
rg -A 5 "sentry_endpoint" prover/src/coordinator_client.rs
# Check Sentry initialization in main.rs
echo "Checking main.rs Sentry initialization..."
rg -A 5 "sentry::init" prover/src/main.rs
# Check the types definition
echo "Checking types definition..."
rg -A 5 "sentry_endpoint" prover/src/coordinator_client/types.rs
Length of output: 1352
prover/src/prover.rs (1)
22-22
: Verify the necessity of public access to coordinator_client.
Making internal fields public can break encapsulation. While the RefCell
wrapper ensures safe access, consider if this change could be avoided by adding specific public methods instead.
Let's check how this field will be used externally:
✅ Verification successful
Based on the search results, I can now generate the final response:
Making coordinator_client public is justified for Sentry integration
The public access to coordinator_client
is necessary as evidenced by its usage in main.rs
for Sentry DSN configuration:
new_dsn = prover.coordinator_client.borrow().get_sentry_dsn();
This external access is part of the PR's Sentry integration objective and follows a valid use case for error monitoring setup.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for external usage of coordinator_client
rg -A 5 "coordinator_client" --type rust
Length of output: 4211
prover/src/types.rs (1)
263-267
: 🛠️ Refactor suggestion
Review test initialization approach.
The current test initialization has several concerns:
- Using
ctor
for test initialization could affect other test modules - Global logging initialization might interfere with other tests
- The log message doesn't provide meaningful context
Let's check if other test modules might be affected:
Consider using a more isolated approach:
fn setup_test_logger() {
static INIT: std::sync::Once = std::sync::Once::new();
INIT.call_once(|| {
crate::utils::log_init(None);
log::info!("ProverType test logger initialized");
});
}
prover/src/utils.rs (2)
2-2
: Approved: Necessary imports added
The addition of borrow::Cow
and fs::OpenOptions
is appropriate and required for the new functionalities introduced.
23-27
: Approved: Logger initialization refactored and Sentry integration added
The refactoring of the logger initialization into build_logger
enhances modularity and reusability. The addition of set_logger_with_sentry
function correctly integrates Sentry for error tracking, aligning with the PR objectives to monitor error logs and panic events.
Also applies to: 29-33
prover/src/main.rs (1)
42-96
:
Ensure proper disposal of previous Sentry instances to prevent resource leaks.
The sentry::init
function is called inside start_loop
, which may lead to multiple initializations of Sentry if current_dsn
changes. Without explicitly shutting down the previous Sentry client, this could cause resource leaks or unexpected behavior.
Consider invoking sentry::shutdown()
before re-initializing Sentry to ensure that resources from the previous instance are properly released. Here's how you might adjust the code:
let _guard = current_dsn.clone().map(|dsn| {
+ sentry::shutdown();
log::info!("successfully get dsn from coordinator");
let guard = sentry::init((
dsn,
#[test] | ||
fn test_get_version_cow() -> Result<()> { | ||
let version = get_version_cow(); | ||
|
||
assert_eq!(get_version(), DEFAULT_VERSION); | ||
assert_eq!(&version, DEFAULT_VERSION); | ||
Ok(()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance test coverage and simplify test implementation.
The test can be improved in several ways:
- Add test case for when RELEASE_VERSION is set
- Remove unnecessary Result type since no operations can fail
- Consider testing version format compliance
- #[test]
- fn test_get_version_cow() -> Result<()> {
- let version = get_version_cow();
-
- assert_eq!(get_version(), DEFAULT_VERSION);
- assert_eq!(&version, DEFAULT_VERSION);
- Ok(())
- }
+ #[test]
+ fn test_get_version() {
+ // Test default case
+ assert_eq!(get_version(), DEFAULT_VERSION);
+ assert_eq!(&get_version_cow(), DEFAULT_VERSION);
+
+ // Verify version format
+ let version = get_version();
+ assert!(version.starts_with('v'), "Version should start with 'v'");
+ assert!(version.split('-').count() >= 3, "Version should contain at least 3 parts");
+ }
Committable suggestion was skipped due to low confidence.
sentry = "0.34.0" | ||
sentry-log = "0.34.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider enabling relevant Sentry features.
The Sentry integration could benefit from enabling specific features based on your monitoring needs. Common useful features include:
debug-images
for better panic trackingbacktrace
for enhanced stack tracescontexts
for additional context in error reports
Consider updating the dependencies with specific features:
-sentry = "0.34.0"
-sentry-log = "0.34.0"
+sentry = { version = "0.34.0", features = ["debug-images", "backtrace", "contexts"] }
+sentry-log = { version = "0.34.0", default-features = true }
📝 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.
sentry = "0.34.0" | |
sentry-log = "0.34.0" | |
sentry = { version = "0.34.0", features = ["debug-images", "backtrace", "contexts"] } | |
sentry-log = { version = "0.34.0", default-features = true } |
// ProverSentryEndpoint the sentry endpoint being sent to each prover in login response | ||
ProverSentryEndpoint string `json:"prover_sentry_endpoint"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding URL validation for the Sentry endpoint.
Since this endpoint is critical for error monitoring, consider adding validation in the NewConfig
function to ensure the URL is properly formatted when provided.
Here's a suggested implementation:
func NewConfig(file string) (*Config, error) {
buf, err := os.ReadFile(filepath.Clean(file))
if err != nil {
return nil, err
}
cfg := &Config{}
err = json.Unmarshal(buf, cfg)
if err != nil {
return nil, err
}
// Override config with environment variables
err = utils.OverrideConfigWithEnv(cfg, "SCROLL_COORDINATOR")
if err != nil {
return nil, err
}
+
+ // Validate Sentry endpoint if provided
+ if cfg.ProverManager != nil && cfg.ProverManager.ProverSentryEndpoint != "" {
+ if _, err := url.Parse(cfg.ProverManager.ProverSentryEndpoint); err != nil {
+ return nil, fmt.Errorf("invalid prover_sentry_endpoint URL: %v", err)
+ }
+ }
return cfg, nil
}
Don't forget to add these imports:
import (
"fmt"
"net/url"
)
#[derive(Debug, Clone)] | ||
pub struct GetEmptyTaskError; | ||
|
||
impl fmt::Display for GetEmptyTaskError { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!(f, "get empty task") | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider enriching error with additional context for Sentry.
While the implementation is correct, consider adding more context to help with error tracking in Sentry. This could include task-related metadata or error conditions.
Here's a suggested enhancement:
#[derive(Debug, Clone)]
-pub struct GetEmptyTaskError;
+pub struct GetEmptyTaskError {
+ pub task_type: Option<String>,
+ pub timestamp: std::time::SystemTime,
+}
impl fmt::Display for GetEmptyTaskError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "get empty task")
+ write!(
+ f,
+ "get empty task (type: {:?}, time: {:?})",
+ self.task_type,
+ self.timestamp
+ )
}
}
📝 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.
#[derive(Debug, Clone)] | |
pub struct GetEmptyTaskError; | |
impl fmt::Display for GetEmptyTaskError { | |
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
write!(f, "get empty task") | |
} | |
} | |
#[derive(Debug, Clone)] | |
pub struct GetEmptyTaskError { | |
pub task_type: Option<String>, | |
pub timestamp: std::time::SystemTime, | |
} | |
impl fmt::Display for GetEmptyTaskError { | |
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
write!( | |
f, | |
"get empty task (type: {:?}, time: {:?})", | |
self.task_type, | |
self.timestamp | |
) | |
} | |
} |
Token string `json:"token"` | ||
Time time.Time `json:"time"` | ||
Token string `json:"token"` | ||
SentryEndpoint string `json:"sentry_endpoint,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding validation and documentation for the SentryEndpoint field.
Since this field contains sensitive configuration information:
- Add field documentation explaining its purpose and expected format
- Consider implementing validation for the endpoint URL format
- Add logging sanitization to prevent the endpoint from being logged
Here's a suggested improvement:
type LoginSchema struct {
Time time.Time `json:"time"`
Token string `json:"token"`
- SentryEndpoint string `json:"sentry_endpoint,omitempty"`
+ // SentryEndpoint holds the URL for error reporting to Sentry.
+ // This field should not be logged or exposed in debug output.
+ // Format: https://<key>@<organization>.ingest.sentry.io/<project>
+ SentryEndpoint string `json:"sentry_endpoint,omitempty" sensitive:"true"`
}
Consider adding a validation method:
// ValidateSentryEndpoint ensures the endpoint URL is properly formatted
func (l *LoginSchema) ValidateSentryEndpoint() error {
if l.SentryEndpoint == "" {
return nil
}
_, err := url.Parse(l.SentryEndpoint)
if err != nil {
return fmt.Errorf("invalid sentry endpoint format: %w", err)
}
return nil
}
pub fn partner_name(&self) -> String { | ||
let prover_name = &self.prover_name; | ||
let scroll_prefix = Regex::new(r"^scroll-.*").unwrap(); | ||
let idc_prefix = Regex::new(r"^idc-.*").unwrap(); | ||
|
||
if scroll_prefix.is_match(prover_name) || idc_prefix.is_match(prover_name) { | ||
let parts = prover_name.split('-').collect::<Vec<&str>>(); | ||
format!("{}-{}", parts[0], parts[1]) | ||
} else { | ||
let split_re = Regex::new(r"[-_]").unwrap(); | ||
let parts = split_re.split(prover_name).collect::<Vec<&str>>(); | ||
parts[0].to_string() | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Several improvements needed for robustness and performance
The implementation has potential issues that should be addressed:
- Unwrap usage on regex compilation could panic
- Array indexing could panic with malformed input
- Regex objects are inefficiently recompiled on every call
- Missing documentation for public API
- Magic strings could be constants
Here's a suggested improvement:
+ /// Extracts the partner name from the prover name.
+ ///
+ /// For prover names starting with "scroll-" or "idc-", returns the first two parts.
+ /// For other names, returns the first part before any hyphen or underscore.
+ ///
+ /// # Returns
+ /// A string containing the extracted partner name.
pub fn partner_name(&self) -> String {
- let prover_name = &self.prover_name;
- let scroll_prefix = Regex::new(r"^scroll-.*").unwrap();
- let idc_prefix = Regex::new(r"^idc-.*").unwrap();
-
- if scroll_prefix.is_match(prover_name) || idc_prefix.is_match(prover_name) {
- let parts = prover_name.split('-').collect::<Vec<&str>>();
- format!("{}-{}", parts[0], parts[1])
- } else {
- let split_re = Regex::new(r"[-_]").unwrap();
- let parts = split_re.split(prover_name).collect::<Vec<&str>>();
- parts[0].to_string()
- }
+ lazy_static! {
+ static ref SCROLL_PREFIX: Regex = Regex::new(r"^scroll-.*").expect("Invalid regex pattern");
+ static ref IDC_PREFIX: Regex = Regex::new(r"^idc-.*").expect("Invalid regex pattern");
+ static ref SPLIT_RE: Regex = Regex::new(r"[-_]").expect("Invalid regex pattern");
+ }
+
+ let prover_name = &self.prover_name;
+
+ if SCROLL_PREFIX.is_match(prover_name) || IDC_PREFIX.is_match(prover_name) {
+ let parts: Vec<&str> = prover_name.split('-').collect();
+ if parts.len() >= 2 {
+ format!("{}-{}", parts[0], parts[1])
+ } else {
+ prover_name.to_string()
+ }
+ } else {
+ SPLIT_RE.split(prover_name).next().unwrap_or(prover_name).to_string()
+ }
}
You'll need to add these dependencies to Cargo.toml:
[dependencies]
lazy_static = "1.4"
💡 Codebase verification
Add test coverage for the new partner_name
method
The partner_name
method is currently used only in Sentry configuration but lacks test coverage. Consider adding unit tests to verify:
- Scroll prefix pattern matching (
scroll-*
) - IDC prefix pattern matching (
idc-*
) - Default pattern matching with
-
and_
separators
Example test locations:
- Add test module in
prover/src/config.rs
- Test cases should cover all pattern matching scenarios
🔗 Analysis chain
Verify test coverage and usage
Since this is a new public API being added for Sentry integration, we should verify its test coverage and usage.
Let me verify the test coverage further by searching for any test modules in the config file itself and checking the overall test structure.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for test cases and usages of partner_name
echo "Searching for test cases..."
rg -l "partner_name.*test" --type rust
echo "Searching for usage of partner_name..."
rg "partner_name\(\)" --type rust
Length of output: 313
Script:
#!/bin/bash
# Search for test module in config.rs
echo "Searching for test module in config.rs..."
rg "mod test" prover/src/config.rs -A 5
# Search for test files in prover directory
echo -e "\nSearching for test files in prover directory..."
fd "test.*\.rs" prover/src/
# Check the implementation details of partner_name usage
echo -e "\nChecking partner_name usage context..."
rg -B 5 -A 5 "partner_name\(\)" prover/src/main.rs
Length of output: 856
if err.is::<GetEmptyTaskError>() { | ||
log::info!("get empty task, skip."); | ||
} else if err.is::<ProofStatusNotOKError>() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance error logging for better Sentry integration
While the error handling logic is sound, consider the following improvements for better error tracking with Sentry:
- Empty tasks are expected scenarios, but the current implementation might make it difficult to track patterns in task availability.
- The error levels should be consistent with their severity.
Consider this enhancement:
if err.is::<GetEmptyTaskError>() {
- log::info!("get empty task, skip.");
+ log::debug!("No tasks available in queue, will retry. Details: {:#}", err);
} else if err.is::<ProofStatusNotOKError>() {
- log::info!("proof status not ok, downgrade level to info.");
+ log::warn!("Proof status check failed. Details: {:#}", err);
} else {
- log::error!("encounter error: {:#}", err);
+ log::error!("Critical error in task processing: {:#}", err);
}
This change will:
- Use appropriate log levels for different scenarios
- Provide more context in log messages
- Make it easier to set up meaningful Sentry alerts based on log levels
Committable suggestion was skipped due to low confidence.
impl Display for ProverType { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
f.write_str(format!("{:?}", self).as_str())?; | ||
Ok(()) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Optimize the Display implementation for ProverType.
The current implementation uses Debug formatting and unnecessary string allocation. Consider a more idiomatic implementation:
impl Display for ProverType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.write_str(format!("{:?}", self).as_str())?;
- Ok(())
+ match self {
+ ProverType::Chunk => write!(f, "Chunk"),
+ ProverType::Batch => write!(f, "Batch"),
+ }
}
}
Committable suggestion was skipped due to low confidence.
pub fn build_logger(log_file: Option<String>) -> env_logger::Logger { | ||
let mut builder = env_logger::Builder::from_env(Env::default().default_filter_or("info")); | ||
if let Some(file_path) = log_file { | ||
let target = Box::new( | ||
OpenOptions::new() | ||
.write(true) | ||
.create(true) | ||
.truncate(false) | ||
.open(file_path) | ||
.expect("Can't create log file"), | ||
); | ||
builder.target(env_logger::Target::Pipe(target)); | ||
} | ||
builder.build() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle potential errors when opening the log file to prevent panics
In the build_logger
function, using .expect("Can't create log file")
will cause the application to panic if the log file cannot be opened. It's recommended to handle this error gracefully to improve the robustness of the application.
Consider modifying the code to handle the error more gracefully:
let target = Box::new(
OpenOptions::new()
.write(true)
.create(true)
.truncate(false)
.open(file_path)
- .expect("Can't create log file"),
+ .unwrap_or_else(|e| {
+ eprintln!("Failed to open log file: {}", e);
+ // Handle the error appropriately, such as defaulting to standard output or returning an error
+ std::process::exit(1);
+ }),
);
Alternatively, you could return a Result<env_logger::Logger, std::io::Error>
from build_logger
and propagate the error upwards for handling at a higher level.
Committable suggestion was skipped due to low confidence.
let gurad = sentry::init(( | ||
dsn, | ||
sentry::ClientOptions { | ||
release: Some(version::get_version_cow()), | ||
environment: Some(utils::get_environment()), | ||
..Default::default() | ||
}, | ||
)); | ||
utils::set_logger_with_sentry(log_file); | ||
gurad |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in variable name gurad
to guard
.
There is a typographical error in the variable name gurad
. It should be corrected to guard
to ensure clarity and prevent potential confusion.
Apply this diff to fix the typo:
- let gurad = sentry::init((
+ let guard = sentry::init((
...
- gurad
+ guard
📝 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.
let gurad = sentry::init(( | |
dsn, | |
sentry::ClientOptions { | |
release: Some(version::get_version_cow()), | |
environment: Some(utils::get_environment()), | |
..Default::default() | |
}, | |
)); | |
utils::set_logger_with_sentry(log_file); | |
gurad | |
let guard = sentry::init(( | |
dsn, | |
sentry::ClientOptions { | |
release: Some(version::get_version_cow()), | |
environment: Some(utils::get_environment()), | |
..Default::default() | |
}, | |
)); | |
utils::set_logger_with_sentry(log_file); | |
guard |
Purpose or design rationale of this PR
feat(prover): integrate sentry to monitor error logs & panic events
PR title
Your PR title must follow conventional commits (as we are doing squash merge for each PR), so it must start with one of the following types:
Deployment tag versioning
Has
tag
incommon/version.go
been updated or have you addedbump-version
label to this PR?Breaking change label
Does this PR have the
breaking-change
label?Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests
Chores