A native OCaml SDK for Sentry error monitoring and performance tracking. Built with modern OCaml features and Lwt for asynchronous operations.
- 🚨 Exception Capture: Automatically capture and report exceptions with full stack traces
- 💬 Message Capture: Send custom messages and log entries to Sentry
- 📊 Performance Monitoring (WIP): Track transactions and spans for performance insights
- 👤 User Context: Associate events with user information
- 🏷️ Tags & Extra Data: Add custom metadata to events
- 🌍 Environment & Release Tracking: Distinguish between different deployments
- 🌐 HTTP Request Context: Capture request details for web applications
- 🔄 Asynchronous Operations: Built on Lwt for non-blocking operations
git clone https://github.com/getsentry/sentry-ocaml.git
cd sentry-ocaml
dune build
dune installFor development or testing, you can also use it directly in your project:
# Clone into your project's dependencies
git clone https://github.com/getsentry/sentry-ocaml.git deps/sentry-ocaml
# Add to your dune-projectecho"(depends (sentry-ocaml (>= 0.1.0)))">> dune-projectopenLwt.Syntaxletmain()=(* Initialize Sentry with your DSN *)let dsn ="https://your-key@your-org.sentry.io/your-project"inlet* client_result =Sentry.init dsn inmatch client_result with|Ok_client -> Printf.printf "Sentry initialized successfully!\n";
Lwt.return_unit
|Errormsg -> Printf.printf "Failed to initialize: %s\n" msg;
Lwt.return_unit
let()=Lwt_main.run (main ())Capture exceptions automatically with full stack traces:
openLwt.Syntaxletrisky_operation()=try(* Your potentially failing code here *)ifRandom.int10>5then
failwith "Random failure occurred!"elsePrintf.printf "Operation succeeded!\n";
Lwt.return_unit
withexn ->(* Capture the exception in Sentry *)let* result =Sentry.capture_exception exninmatch result with|Ok() -> Printf.printf "Exception captured in Sentry\n";
Lwt.return_unit
|Errormsg -> Printf.printf "Failed to capture exception: %s\n" msg;
Lwt.return_unit
letmain()=let dsn =Unix.getenv "SENTRY_DSN"inlet* client_result =Sentry.init dsn inmatch client_result with|Ok_client -> risky_operation ()|Errormsg -> Printf.printf "Sentry init failed: %s\n" msg;
Lwt.return_unit
let()=Lwt_main.run (main ())Send custom messages and log entries:
openLwt.Syntaxletlog_user_actionusernameaction=let message =Printf.sprintf "User %s performed action: %s" username action inlet* result =Sentry.capture_message ~level:"info" message inmatch result with|Ok() -> Printf.printf "Message logged to Sentry\n"|Errormsg -> Printf.printf "Failed to log message: %s\n" msg
letmain()=let dsn =Unix.getenv "SENTRY_DSN"inlet* client_result =Sentry.init dsn inmatch client_result with|Ok_client -> let*()= log_user_action "john_doe""login"inlet*()= log_user_action "john_doe""view_profile"inLwt.return_unit
|Errormsg -> Printf.printf "Sentry init failed: %s\n" msg;
Lwt.return_unit
let()=Lwt_main.run (main ())Track transactions and spans for performance insights:
openLwt.Syntax(* Simulate some operations *)letvalidate_data()=Unix.sleepf 0.1letprocess_data()=Unix.sleepf 0.2letsave_data()=Unix.sleepf 0.3letperform_complex_operation()=(* Start a transaction *)let transaction =Sentry.start_transaction ~name:"complex_operation"~operation:"data_processing"in(* Validate data *)let validation_span =Sentry.start_child transaction ~name:"validation"~operation:"data_validation"in
validate_data ();
let _ =Sentry.finish_span validation_span in(* Process data *)let process_span =Sentry.start_child transaction ~name:"processing"~operation:"data_processing"in
process_data ();
let _ =Sentry.finish_span process_span in(* Save data *)let save_span =Sentry.start_child transaction ~name:"saving"~operation:"data_persistence"in
save_data ();
let _ =Sentry.finish_span save_span in(* Finish and send the transaction *)let* _ =Sentry.finish_transaction transaction inLwt.return_unit
letmain()=let dsn =Unix.getenv "SENTRY_DSN"inlet* client_result =Sentry.init dsn inmatch client_result with|Ok_client -> perform_complex_operation ()|Errormsg -> Printf.printf "Sentry init failed: %s\n" msg;
Lwt.return_unit
let()=Lwt_main.run (main ())Add user information, tags, and extra data to events:
openLwt.Syntaxletsetup_user_context()=(* Set user information *)let*()=Sentry.set_user {
id =Some"user123";
username =Some"john_doe";
email =Some"john@example.com";
ip_address =Some"192.168.1.100";
} in(* Add tags for categorization *)let*()=Sentry.set_tag "component""user_service"inlet*()=Sentry.set_tag "service""api_gateway"in(* Add extra data for debugging *)let*()=Sentry.set_extra "deployment""us-east-1"inlet*()=Sentry.set_extra "version""2.1.0"in(* Set environment and release *)let*()=Sentry.set_environment "production"inlet*()=Sentry.set_release "v2.1.0"inLwt.return_unit
letmain()=let dsn =Unix.getenv "SENTRY_DSN"inlet* client_result =Sentry.init dsn inmatch client_result with|Ok_client -> let*()= setup_user_context ()in(* Now all events will include this context *)let*()=Sentry.capture_message ~level:"info""User context configured"inLwt.return_unit
|Errormsg -> Printf.printf "Sentry init failed: %s\n" msg;
Lwt.return_unit
let()=Lwt_main.run (main ())Capture request details for web applications:
openLwt.Syntaxlethandle_api_request()=(* Set request context *)let*()=Sentry.set_request_context
~headers:[
("content-type", "application/json");
("authorization", "Bearer token123");
("user-agent", "MyApp/1.0");
]
~query_string:"?page=1&limit=10"~data:[("action", "get_users"); ("filter", "active")]
~cookies:"session_id=abc123; theme=dark"~env:[
("REMOTE_ADDR", "192.168.1.100");
("HTTP_HOST", "api.example.com");
("SERVER_PORT", "443");
]
~body_size:1024~user_agent:"MyApp/1.0""GET""/api/users"in(* Simulate an API error *)try
raise (Failure"API rate limit exceeded")
withexn ->Sentry.capture_exception exnletmain()=let dsn =Unix.getenv "SENTRY_DSN"inlet* client_result =Sentry.init dsn inmatch client_result with|Ok_client -> handle_api_request ()|Errormsg -> Printf.printf "Sentry init failed: %s\n" msg;
Lwt.return_unit
let()=Lwt_main.run (main ())Check out the examples/ directory for complete working examples:
basic_exn_1.ml- Basic exception capturebasic_exn_2.ml- Exception capture with error handlingbasic_msg.ml- Message capturestack_trace.ml- Stack trace capturehttp_request.ml- HTTP request contextperformance.ml- Performance monitoring (WIP)
NOTE: these environment variables are NOT read automatically by the SDK (yet).
SENTRY_DSN: Your Sentry project DSN (required)SENTRY_ENVIRONMENT: Environment name (optional, can be set programmatically)SENTRY_RELEASE: Release version (optional, can be set programmatically)
openLwt.Syntaxletconfigure_sentry()=let dsn =Unix.getenv "SENTRY_DSN"inlet* client_result =Sentry.init dsn inmatch client_result with|Ok_client -> (* Set global configuration *)let*()=Sentry.set_environment "staging"inlet*()=Sentry.set_release "v1.2.3"inlet*()=Sentry.set_tag "service""my_ocaml_app"inLwt.return_unit
|Errormsg -> Printf.printf "Sentry init failed: %s\n" msg;
Lwt.return_unitSentry.init dsn- Initialize the Sentry clientSentry.capture_exception ?level exn- Capture an exceptionSentry.capture_message ?level message- Capture a custom message
Sentry.start_transaction ~name ~operation- Start a new transactionSentry.start_child transaction ~name ~operation- Start a child spanSentry.finish_span span- Finish a spanSentry.finish_transaction transaction- Finish and send a transaction
Sentry.set_user user- Set user informationSentry.set_tag key value- Add a tagSentry.set_extra key value- Add extra dataSentry.set_environment env- Set environmentSentry.set_release release- Set release versionSentry.set_request_context ...- Set HTTP request context
Run the test suite:
dune runtestThis project is licensed under the MIT License - see the LICENSE file for details.
Note: This SDK was created during Sentry Hack Week and is not officially supported by Sentry.