Skip to content

Repository files navigation

(Experimental) Sentry SDK for OCaml 🚀

CIOCamlLicense: MIT

A native OCaml SDK for Sentry error monitoring and performance tracking. Built with modern OCaml features and Lwt for asynchronous operations.

⚠️ This SDK was created as a Sentry Hack Week (hackathon) project and is currently experimental / not production-ready.

✨ Features

  • 🚨 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

📦 Installation

From Source

git clone https://github.com/getsentry/sentry-ocaml.git
cd sentry-ocaml
dune build
dune install

Development Setup

For 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-project

🚀 Quick Start

openLwt.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 ())

📝 Usage Examples

Exception Capture

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 ())

Message Capture

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 ())

Performance Monitoring (WIP)

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 ())

User Context & Metadata

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 ())

HTTP Request Context

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 ())

📖 Examples

Check out the examples/ directory for complete working examples:

  • basic_exn_1.ml - Basic exception capture
  • basic_exn_2.ml - Exception capture with error handling
  • basic_msg.ml - Message capture
  • stack_trace.ml - Stack trace capture
  • http_request.ml - HTTP request context
  • performance.ml - Performance monitoring (WIP)

🔧 Configuration

Environment Variables

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)

Programmatic Configuration

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_unit

📚 API Reference

Core Functions

  • Sentry.init dsn - Initialize the Sentry client
  • Sentry.capture_exception ?level exn - Capture an exception
  • Sentry.capture_message ?level message - Capture a custom message

Performance Monitoring

  • Sentry.start_transaction ~name ~operation - Start a new transaction
  • Sentry.start_child transaction ~name ~operation - Start a child span
  • Sentry.finish_span span - Finish a span
  • Sentry.finish_transaction transaction - Finish and send a transaction

Context Management

  • Sentry.set_user user - Set user information
  • Sentry.set_tag key value - Add a tag
  • Sentry.set_extra key value - Add extra data
  • Sentry.set_environment env - Set environment
  • Sentry.set_release release - Set release version
  • Sentry.set_request_context ... - Set HTTP request context

🧪 Testing

Run the test suite:

dune runtest

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🔗 Links


Note: This SDK was created during Sentry Hack Week and is not officially supported by Sentry.

About

Hack Week Project: Sentry SDK for OCaml

Topics

Resources

Code of conduct

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages