{"id":46930545,"url":"https://github.com/enaboapps/timberlogs-rust-sdk","last_synced_at":"2026-03-11T04:33:08.395Z","repository":{"id":340660574,"uuid":"1162817263","full_name":"enaboapps/timberlogs-rust-sdk","owner":"enaboapps","description":"Rust SDK for Timberlogs - structured logging made simple","archived":false,"fork":false,"pushed_at":"2026-02-25T21:57:20.000Z","size":14,"stargazers_count":1,"open_issues_count":7,"forks_count":0,"subscribers_count":0,"default_branch":"dev","last_synced_at":"2026-02-26T00:39:44.776Z","etag":null,"topics":["logging","observability","rust","structured-logging","timberlogs"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/enaboapps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-20T18:24:18.000Z","updated_at":"2026-02-20T19:41:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/enaboapps/timberlogs-rust-sdk","commit_stats":null,"previous_names":["enaboapps/timberlogs-rust-sdk"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/enaboapps/timberlogs-rust-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enaboapps%2Ftimberlogs-rust-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enaboapps%2Ftimberlogs-rust-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enaboapps%2Ftimberlogs-rust-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enaboapps%2Ftimberlogs-rust-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/enaboapps","download_url":"https://codeload.github.com/enaboapps/timberlogs-rust-sdk/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enaboapps%2Ftimberlogs-rust-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30370801,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"online","status_checked_at":"2026-03-11T02:00:07.027Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["logging","observability","rust","structured-logging","timberlogs"],"created_at":"2026-03-11T04:33:06.564Z","updated_at":"2026-03-11T04:33:08.387Z","avatar_url":"https://github.com/enaboapps.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# timberlogs\n\nRust SDK for [Timberlogs](https://timberlogs.dev) — structured logging made simple.\n\n## Installation\n\n```toml\n[dependencies]\ntimberlogs = \"1\"\ntokio = { version = \"1\", features = [\"rt-multi-thread\", \"macros\"] }\n```\n\n## Quick Start\n\n```rust\nuse timberlogs::{TimberlogsClient, TimberlogsConfig, Environment};\n\n#[tokio::main]\nasync fn main() {\n    let mut client = TimberlogsClient::new(TimberlogsConfig {\n        source: \"my-service\".into(),\n        environment: Environment::Production,\n        api_key: \"tb_live_xxxxx\".into(),\n        version: Some(\"1.0.0\".into()),\n        ..Default::default()\n    });\n\n    client.info(\"Server started\", None).await.unwrap();\n    client.error(\"Something went wrong\", None).await.unwrap();\n\n    client.disconnect().await.unwrap();\n}\n```\n\n## Configuration\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `source` | `String` | required | Application/service name |\n| `environment` | `Environment` | required | `Development`, `Staging`, or `Production` |\n| `api_key` | `String` | required | Your Timberlogs API key |\n| `version` | `Option\u003cString\u003e` | `None` | Application version |\n| `user_id` | `Option\u003cString\u003e` | `None` | Default user ID |\n| `session_id` | `Option\u003cString\u003e` | `None` | Default session ID |\n| `dataset` | `Option\u003cString\u003e` | `None` | Default dataset |\n| `batch_size` | `Option\u003cusize\u003e` | `10` | Logs to batch before sending |\n| `flush_interval_ms` | `Option\u003cu64\u003e` | `5000` | Auto-flush interval in ms |\n| `min_level` | `Option\u003cLogLevel\u003e` | `Debug` | Minimum level to send |\n| `retry` | `Option\u003cRetryConfig\u003e` | 3 retries, exponential backoff | Retry configuration |\n| `on_error` | `Option\u003cErrorCallback\u003e` | `None` | Callback invoked on flush failures |\n\n## Log Levels\n\n```rust\nclient.debug(\"Debug message\", None).await?;\nclient.info(\"Info message\", None).await?;\nclient.warn(\"Warning message\", None).await?;\nclient.error(\"Error message\", None).await?;\n```\n\n## Structured Data\n\n```rust\nuse std::collections::HashMap;\nuse serde_json::json;\n\nlet mut data = HashMap::new();\ndata.insert(\"port\".into(), json!(3000));\ndata.insert(\"host\".into(), json!(\"0.0.0.0\"));\n\nclient.info(\"Server started\", Some(data)).await?;\n```\n\n## Tags\n\n```rust\nuse timberlogs::{LogEntry, LogLevel};\n\nclient.log(LogEntry {\n    level: LogLevel::Info,\n    message: \"User signed in\".into(),\n    tags: Some(vec![\"auth\".into(), \"login\".into()]),\n    ..Default::default()\n}).await?;\n```\n\n## Full LogEntry Fields\n\n```rust\nuse timberlogs::{LogEntry, LogLevel};\n\nclient.log(LogEntry {\n    level: LogLevel::Error,\n    message: \"Request failed\".into(),\n    data: Some(HashMap::from([(\"url\".into(), json!(\"/api/users\"))])),\n    user_id: Some(\"user_123\".into()),\n    session_id: Some(\"sess_abc\".into()),\n    request_id: Some(\"req_xyz\".into()),\n    error_name: Some(\"TimeoutError\".into()),\n    error_stack: Some(\"at handler:42\".into()),\n    tags: Some(vec![\"api\".into()]),\n    dataset: Some(\"web-logs\".into()),\n    timestamp: Some(1700000000000), // Unix ms, defaults to now if omitted\n    ip_address: Some(\"192.168.1.1\".into()),\n    country: Some(\"US\".into()),\n    ..Default::default()\n}).await?;\n```\n\n## Dynamic User \u0026 Session\n\nSet or update user/session IDs at runtime. These are applied to all subsequent logs.\n\n```rust\nclient.set_user_id(Some(\"user_123\".into())).await;\nclient.set_session_id(Some(\"sess_abc\".into())).await;\n\nclient.info(\"Now associated with user\", None).await?;\n\n// Clear them\nclient.set_user_id(None).await;\n```\n\n## Flow Tracking\n\nFlows group related logs into a named sequence with auto-incrementing step indices.\n\n```rust\nlet mut flow = client.flow(\"user-checkout\").await?;\n\nflow.info(\"Cart loaded\", None).await?;       // step 0\nflow.info(\"Payment started\", None).await?;   // step 1\nflow.info(\"Order confirmed\", None).await?;   // step 2\n```\n\nEach flow gets a server-generated ID. The `Flow` struct provides the same convenience methods as the client (`debug`, `info`, `warn`, `error`) plus `log_with_level` for custom levels and tags.\n\n## Raw Ingestion\n\nIngest logs in alternative formats without structured parsing.\n\n```rust\nuse timberlogs::{RawFormat, IngestRawOptions, Environment};\n\n// Simple raw JSON\nclient.ingest_raw(\n    r#\"{\"msg\":\"hello\",\"level\":\"info\"}\"#,\n    RawFormat::Json,\n    None,\n).await?;\n\n// CSV with options\nclient.ingest_raw(\n    \"level,message\\ninfo,hello\\nerror,fail\",\n    RawFormat::Csv,\n    Some(IngestRawOptions {\n        source: Some(\"import-job\".into()),\n        environment: Some(Environment::Production),\n        level: Some(LogLevel::Info),\n        dataset: Some(\"csv-import\".into()),\n    }),\n).await?;\n```\n\nSupported formats: `Json`, `Jsonl`, `Syslog`, `Text`, `Csv`, `Obl`.\n\n## Error Handling\n\n### on_error Callback\n\nBackground flushes run on a timer and can fail silently. Use `on_error` to capture these failures.\n\n```rust\nlet client = TimberlogsClient::new(TimberlogsConfig {\n    on_error: Some(Box::new(|err| {\n        eprintln!(\"Timberlogs flush error: {err}\");\n    })),\n    ..Default::default()\n});\n```\n\n### Handling Errors Directly\n\nAll async methods return `Result\u003c_, TimberlogsError\u003e`:\n\n```rust\nuse timberlogs::TimberlogsError;\n\nmatch client.info(\"test\", None).await {\n    Ok(()) =\u003e {},\n    Err(TimberlogsError::Validation(msg)) =\u003e eprintln!(\"Invalid: {msg}\"),\n    Err(TimberlogsError::Http { status, body }) =\u003e eprintln!(\"HTTP {status}: {body}\"),\n    Err(TimberlogsError::Request(e)) =\u003e eprintln!(\"Network error: {e}\"),\n    Err(e) =\u003e eprintln!(\"Other: {e}\"),\n}\n```\n\n## Flush \u0026 Disconnect\n\nLogs are batched and sent automatically. You can also flush manually or disconnect gracefully.\n\n```rust\n// Force send all buffered logs\nclient.flush().await?;\n\n// Flush and stop the background timer\nclient.disconnect().await?;\n```\n\nAlways call `disconnect()` before your application exits to ensure all buffered logs are sent.\n\n## Retry Configuration\n\n```rust\nuse timberlogs::RetryConfig;\n\nlet client = TimberlogsClient::new(TimberlogsConfig {\n    retry: Some(RetryConfig {\n        max_retries: 5,\n        initial_delay_ms: 500,\n        max_delay_ms: 60000,\n    }),\n    ..Default::default()\n});\n```\n\nRetries use exponential backoff, doubling the delay on each attempt up to `max_delay_ms`.\n\n## API Reference\n\n### TimberlogsClient\n\n| Method | Description |\n|--------|-------------|\n| `new(config)` | Create a new client with the given configuration |\n| `debug(msg, data)` | Log at Debug level |\n| `info(msg, data)` | Log at Info level |\n| `warn(msg, data)` | Log at Warn level |\n| `error(msg, data)` | Log at Error level |\n| `log(entry)` | Log a full `LogEntry` |\n| `flow(name)` | Create a new flow and return a `Flow` handle |\n| `ingest_raw(body, format, options)` | Ingest raw-formatted logs |\n| `set_user_id(id)` | Set or clear the default user ID |\n| `set_session_id(id)` | Set or clear the default session ID |\n| `flush()` | Manually flush all buffered logs |\n| `disconnect()` | Flush and stop the background flush timer |\n\n### Flow\n\n| Method | Description |\n|--------|-------------|\n| `debug(msg, data)` | Log at Debug level within the flow |\n| `info(msg, data)` | Log at Info level within the flow |\n| `warn(msg, data)` | Log at Warn level within the flow |\n| `error(msg, data)` | Log at Error level within the flow |\n| `log_with_level(level, msg, data, tags)` | Log with custom level and tags |\n\n### Enums\n\n| Enum | Variants |\n|------|----------|\n| `LogLevel` | `Debug`, `Info`, `Warn`, `Error` |\n| `Environment` | `Development`, `Staging`, `Production` |\n| `RawFormat` | `Json`, `Jsonl`, `Syslog`, `Text`, `Csv`, `Obl` |\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenaboapps%2Ftimberlogs-rust-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenaboapps%2Ftimberlogs-rust-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenaboapps%2Ftimberlogs-rust-sdk/lists"}