tushare-api

Crates.iotushare-api
lib.rstushare-api
version1.2.7
created_at2025-07-29 03:39:11.319538+00
updated_at2026-01-21 16:04:05.668347+00
descriptionA comprehensive Rust client library for accessing Tushare financial data APIs
homepagehttps://github.com/rock117/tushare-api
repositoryhttps://github.com/rock117/tushare-api
max_upload_size
id1771885
size279,000
rock huang (rock117)

documentation

https://docs.rs/tushare-api

README

Tushare API - Rust 库

Crates.io Documentation License: MIT

一个用于访问 Tushare 金融数据 API的Rust 客户端库。该库提供类型安全的异步访问所有 Tushare 数据接口,并提供高级功能,支持对API级别进行限流和重试。

目录

✨ 特性

  • 🚀 异步:为高性能异步操作而构建
  • 🔒 类型安全:强类型 API 枚举和全面的错误处理
  • 🔧 开发者友好:便捷的宏和构建器模式
  • 📊 第三方类型支持:内置支持 rust_decimalchronouuidbigdecimal
  • 🌍 生产就绪:全面的错误处理和安全特性

📋 前置条件

  • Tushare API Token:在 Tushare Pro 注册以获取API token

📦 安装

Cargo.toml 中添加:

[dependencies]
tushare-api = "1.2.7"

# 可选:启用第三方类型支持
# tushare-api = { version = "1.2.7", features = ["rust_decimal", "chrono"] }

# 或启用所有第三方类型
# tushare-api = { version = "1.2.7", features = ["all_types"] }

# 可选:启用 tracing 支持
# tushare-api = { version = "1.2.7", features = ["tracing"] }

🚀 快速开始

use tushare_api::TushareClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 设置环境变量
    std::env::set_var("TUSHARE_TOKEN", "your_token_here");
    
    // 创建客户端
    let client = TushareClient::from_env()?;
    
    // 调用 API
    let response = client
        .call_api(
            r#"
            {
                "api_name": "stock_basic",
                "params": { "list_status": "L" },
                "fields": ["ts_code", "name", "industry"]
            }
            "#,
        )
        .await?;
    
    if let Some(data) = response.data {
        println!("获取到 {} 条记录", data.items.len());
    }
    Ok(())
}

📖 API 使用指南

1. 如何导入 Tushare API

// 基础导入
use tushare_api::{TushareClient, TushareRequest, TushareResponse, Api, TushareResult};

// 便捷宏
use tushare_api::{params, fields, request};

// 日志配置
use tushare_api::{LogLevel, LogConfig, Logger};

// HTTP 客户端配置和连接池设置
use tushare_api::{TushareClientBuilder, HttpClientConfig};

// 自定义超时
use std::time::Duration;

2. 如何创建 Tushare 客户端

库提供多种创建客户端的方式:

方法 1:使用环境变量(推荐)

// 首先设置环境变量
std::env::set_var("TUSHARE_TOKEN", "your_token_here");

// 使用默认超时设置
let client = TushareClient::from_env()?;

// 使用自定义超时设置
let client = TushareClient::from_env_with_timeout(
    Duration::from_secs(10),  // 连接超时 10 秒
    Duration::from_secs(60)   // 请求超时 60 秒
)?;

方法 2:直接使用 Token

// 使用默认超时设置
let client = TushareClient::new("your_token_here");

// 使用自定义超时设置
let client = TushareClient::with_timeout(
    "your_token_here",
    Duration::from_secs(5),   // 连接超时 5 秒
    Duration::from_secs(60)   // 请求超时 60 秒
);

方法 3:使用构建器模式

// 基础构建器,包含超时和日志
let client = TushareClient::builder()
    .with_token("your_token_here")
    .with_connect_timeout(Duration::from_secs(10))
    .with_timeout(Duration::from_secs(60))
    .with_log_level(LogLevel::Debug)
    .log_requests(true)
    .log_responses(false)
    .log_sensitive_data(false)
    .log_performance(true)
    .build()?;

// 高级构建器,包含连接池设置
let client = TushareClient::builder()
    .with_token("your_token_here")
    .with_connect_timeout(Duration::from_secs(5))
    .with_timeout(Duration::from_secs(60))
    .with_pool_max_idle_per_host(20)  // 每个主机最多 20 个空闲连接
    .with_pool_idle_timeout(Duration::from_secs(60))  // 连接保持 60 秒
    .with_log_level(LogLevel::Info)
    .build()?;

// 使用 HttpClientConfig 进行高级 HTTP 设置
let http_config = HttpClientConfig::new()
    .with_connect_timeout(Duration::from_secs(3))
    .with_timeout(Duration::from_secs(30))
    .with_pool_max_idle_per_host(15)
    .with_pool_idle_timeout(Duration::from_secs(45));

let client = TushareClient::builder()
    .with_token("your_token_here")
    .with_http_config(http_config)
    .with_log_level(LogLevel::Debug)
    .build()?;

2.1 使用 TushareClientEx

TushareClientEx 是对 TushareClient 的包装,用于提供额外能力(如按 API 的最小间隔限流、失败重试等)。

use std::time::Duration;
use tushare_api::{Api, TushareClient, TushareClientEx, TushareEntityList, request};
use tushare_api::client_ex::RetryConfig;
use tushare_api::DeriveFromTushareData;

#[derive(Debug, Clone, DeriveFromTushareData)]
struct Stock {
    ts_code: String,
    name: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let inner = TushareClient::from_env()?;

    let client = TushareClientEx::new(inner)
        .with_api_min_interval(Api::Daily, Duration::from_secs(10))
        .with_retry_config(RetryConfig {
            max_retries: 3,
            base_delay: Duration::from_millis(200),
            max_delay: Duration::from_secs(5),
        });

    let req = request!(Api::StockBasic, {
        "list_status" => "L"
    }, [
        "ts_code", "name"
    ]);

    let stocks: TushareEntityList<Stock> = client.call_api_as(&req).await?;
    println!("{}", stocks.len());

    Ok(())
}

3. 如何发送请求

方法 1:使用便捷宏(推荐)

use tushare_api::{request, Api};

// 带参数和字段的单个 API 调用
let response = client.call_api(request!(Api::StockBasic, {
    "list_status" => "L",
    "exchange" => "SSE"
}, [
    "ts_code", "name", "industry", "area"
])).await?;

// 无参数的 API 调用
let response = client.call_api(request!(Api::TradeCal, {}, [
    "exchange", "cal_date", "is_open"
])).await?;

// 无字段的 API 调用(获取所有字段)
let response = client.call_api(request!(Api::StockBasic, {
    "list_status" => "L"
}, [])).await?;

方法 2:使用单独的宏

use tushare_api::{TushareRequest, Api, params, fields};

let request = TushareRequest {
    api_name: Api::StockBasic,
    params: params!("list_status" => "L", "exchange" => "SSE"),
    fields: fields!("ts_code", "name", "industry"),
};

let response = client.call_api(request).await?;

方法 3:手动构建

use std::collections::HashMap;

let mut params = HashMap::new();
params.insert("list_status".to_string(), "L".to_string());

let request = TushareRequest {
    api_name: Api::StockBasic,
    params,
    fields: vec!["ts_code".to_string(), "name".to_string()],
};

let response = client.call_api(request).await?;

方法 4:直接使用字符串参数

// 直接传 JSON 字符串(适合快速调试/复制粘贴 API 请求)
let response = client
    .call_api(
        r#"
        {
            "api_name": "stock_basic",
            "params": { "list_status": "L", "exchange": "SSE" },
            "fields": ["ts_code", "name", "industry", "area"]
        }
        "#,
    )
    .await?;

方法 5:任何实现了 TryInto<TushareRequest> 的类型都可以作为参数

call_api 的签名是泛型的:

pub async fn call_api<T>(&self, request: T) -> TushareResult<TushareResponse>
where
    T: TryInto<TushareRequest>,
    <T as TryInto<TushareRequest>>::Error: Into<TushareError>,

所以你可以直接传入:

// 1) 直接传 TushareRequest
let req = TushareRequest {
    api_name: Api::StockBasic,
    params: params!("list_status" => "L"),
    fields: fields!("ts_code", "name"),
};
let response = client.call_api(req).await?;

// 2) 直接传 &str 
let response = client.call_api(r#"{
    "api_name": "stock_basic",
    "params": { "list_status": "L" },
    "fields": ["ts_code", "name"]
}"#).await?;

// 3) 直接传 String
let json = r#"{
    "api_name": "stock_basic",
    "params": { "list_status": "L" },
    "fields": ["ts_code", "name"]
}"#.to_string();
let response = client.call_api(json).await?;

4. 将返回的数据转换为自定义结构体

该库提供了强大的过程宏,可以自动将 Tushare API 响应转换为强类型的 Rust 结构体,无需手动解析。

使用过程宏

use tushare_api::{TushareClient, Api, request, TushareEntityList};
use tushare_api::DeriveFromTushareData;

// 使用自动转换定义您的结构体
#[derive(Debug, Clone, DeriveFromTushareData)]
pub struct Stock {
    pub ts_code: String,
    pub symbol: String,
    pub name: String,
    pub area: Option<String>,
    pub industry: Option<String>,
    pub market: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = TushareClient::from_env()?;
    
    // 使用 call_api_as 进行直接转换到 TushareEntityList<Stock>
    let stocks: TushareEntityList<Stock> = client.call_api_as(request!(Api::StockBasic, {
        "list_status" => "L",
        "exchange" => "SSE"
    }, [
        "ts_code", "symbol", "name", "area", "industry", "market"
    ])).await?;
    
    // 直接访问数据
    println!("找到 {} 只股票:", stocks.len());
    for stock in stocks.iter().take(5) {
        println!("  {}: {} ({})", stock.ts_code, stock.name, stock.market);
    }
    
    // 访问分页信息
    println!("当前页面: {} 条记录", stocks.len());
    println!("总记录数: {}", stocks.count());
    println!("是否还有更多页面: {}", stocks.has_more());
    
    Ok(())
}

字段映射和可选字段

use tushare_api::DeriveFromTushareData;

// 带字段映射和可选字段的高级结构体
#[derive(Debug, Clone, DeriveFromTushareData)]
pub struct StockInfo {
    pub ts_code: String,
    
    // 将 API 字段 "symbol" 映射到结构体字段 "stock_symbol"
    #[tushare(field = "symbol")]
    pub stock_symbol: String,
    
    pub name: String,
    
    // 可选字段会自动处理
    pub area: Option<String>,
    pub industry: Option<String>,
    
    // 跳过 API 响应中不存在的字段
    #[tushare(skip)]
    pub calculated_value: f64,
}

// 实现 Default 以便使用
impl Default for StockInfo {
    fn default() -> Self {
        Self {
            ts_code: String::new(),
            stock_symbol: String::new(),
            name: String::new(),
            area: None,
            industry: None,
            calculated_value: 0.0,
        }
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = TushareClient::from_env()?;
    
    let stock_info: TushareEntityList<StockInfo> = client.call_api_as(request!(Api::StockBasic, {
        "list_status" => "L"
    }, [
        "ts_code", "symbol", "name", "area", "industry"
    ])).await?;
    
    for info in stock_info.iter().take(3) {
        println!("股票: {} ({}) - 行业: {:?}", 
                 info.name, info.stock_symbol, info.industry);
    }
    
    Ok(())
}

生成的结构体说明

当您使用新的泛型分页容器时,您会得到一个清晰、类型安全的接口:

// 您的原始结构体
#[derive(Debug, Clone, DeriveFromTushareData)]
pub struct Stock {
    pub ts_code: String,
    pub name: String,
    pub area: Option<String>,
}

// 使用泛型 TushareEntityList<T> 容器:
// TushareEntityList<Stock> {
//     pub items: Vec<Stock>,        // 您的数据项
//     pub has_more: bool,           // 分页:是否还有更多页面?
//     pub count: i64,               // 分页:总记录数
// }

当您调用:

let stocks: TushareEntityList<Stock> = client.call_api_as(request).await?;
// 或者
let stocks = client.call_api_as::<Stock>(request).await?;

您会得到一个 TushareEntityList<Stock> 结构体,包含:

  • items - Vec<Stock> 包含实际转换后的数据
  • has_more - bool 表示是否还有更多页面可获取
  • count - i64 显示可用的总记录数

以及这些自动生成的方法:

  • stocks.len() - 当前页面的项目数量
  • stocks.is_empty() - 当前页面是否为空
  • stocks.items() - 获取项目切片
  • stocks.has_more() - 检查是否还有更多页面
  • stocks.count() - 获取总记录数
  • stocks.iter() - 遍历项目(通过 Deref)
  • for stock in &stocks { ... } - 直接迭代支持

分页支持

TushareEntityList<T> 容器提供内置分页支持,具有清晰直观的接口:

  • items: Vec<T> - 实际的数据项
  • has_more: bool - 是否还有更多页面可用
  • count: i64 - 总记录数
use tushare_api::{TushareClient, Api, request, TushareEntityList};
use tushare_api::DeriveFromTushareData;

#[derive(Debug, Clone, DeriveFromTushareData)]
pub struct Stock {
    pub ts_code: String,
    pub name: String,
    pub area: Option<String>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = TushareClient::from_env()?;
    
    // 获取分页结果
    let stocks: TushareEntityList<Stock> = client.call_api_as(request!(Api::StockBasic, {
        "list_status" => "L",
        "limit" => "100",
        "offset" => "0"
    }, [
        "ts_code", "name", "area"
    ])).await?;
    
    // 访问分页信息
    println!("当前页面: {} 只股票", stocks.len());
    println!("总可用数量: {} 只股票", stocks.count());
    println!("是否还有更多页面: {}", stocks.has_more());
    
    // 遍历当前页面的项目
    for stock in &stocks {
        println!("{}: {} ({})", 
                 stock.ts_code, 
                 stock.name, 
                 stock.area.as_deref().unwrap_or("未知"));
    }
    
    // 直接访问项目
    let first_stock = &stocks.items()[0];
    println!("第一只股票: {}", first_stock.name);
    
    Ok(())
}

支持的字段类型

过程宏支持以下 Rust 类型:

  • String - 必需的字符串字段
  • Option<String> - 可选的字符串字段
  • f64 - 必需的浮点数
  • Option<f64> - 可选的浮点数
  • i64 - 必需的整数
  • Option<i64> - 可选的整数
  • bool - 必需的布尔值
  • Option<bool> - 可选的布尔值

自定义日期格式支持

库支持使用 #[tushare(date_format = "...")] 属性进行自定义日期格式解析。这在处理返回非标准日期格式的 API 时特别有用。

use tushare_api::{TushareClient, Api, request, TushareEntityList, DeriveFromTushareData};

#[derive(Debug, Clone, DeriveFromTushareData)]
pub struct CustomDateFormats {
    #[tushare(field = "ts_code")]
    pub stock_code: String,
    
    // 标准日期格式(自动检测:YYYYMMDD、YYYY-MM-DD 等)
    #[tushare(field = "trade_date")]
    pub trade_date: chrono::NaiveDate,
    
    // 欧洲日期格式:DD/MM/YYYY
    #[tushare(field = "european_date", date_format = "%d/%m/%Y")]
    pub european_date: chrono::NaiveDate,
    
    // 美国日期格式:MM-DD-YYYY
    #[tushare(field = "us_date", date_format = "%m-%d-%Y")]
    pub us_date: chrono::NaiveDate,
    
    // 德国日期格式:DD.MM.YYYY
    #[tushare(field = "german_date", date_format = "%d.%m.%Y")]
    pub german_date: Option<chrono::NaiveDate>,
    
    // 自定义日期时间格式:YYYY/MM/DD HH:MM
    #[tushare(field = "custom_datetime", date_format = "%Y/%m/%d %H:%M")]
    pub custom_datetime: chrono::NaiveDateTime,
    
    // 中文日期格式:YYYY年MM月DD日
    #[tushare(field = "chinese_date", date_format = "%Y年%m月%d日")]
    pub chinese_date: Option<chrono::NaiveDate>,
    
    // UTC 日期时间格式:YYYY-MM-DD HH:MM:SS +ZZZZ
    #[tushare(field = "utc_datetime", date_format = "%Y-%m-%d %H:%M:%S %z")]
    pub utc_datetime: chrono::DateTime<chrono::Utc>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = TushareClient::from_env()?;
    
    // API 调用示例(注意:实际 API 可能不返回这些确切格式)
    let data: TushareEntityList<CustomDateFormats> = client.call_api_as(request!(
        Api::StockBasic, {
            "list_status" => "L",
            "limit" => "10"
        }, [
            "ts_code", "trade_date", "european_date", "us_date", 
            "german_date", "custom_datetime", "chinese_date", "utc_datetime"
        ]
    )).await?;
    
    for record in data.iter() {
        println!("股票: {} - 交易日期: {}", record.stock_code, record.trade_date);
        println!("  欧洲格式: {}", record.european_date);
        println!("  美国格式: {}", record.us_date);
        println!("  德国格式: {:?}", record.german_date);
        println!("  自定义日期时间: {:?}", record.custom_datetime);
        println!("  中文格式: {:?}", record.chinese_date);
        println!("  UTC 时间: {}", record.utc_datetime);
        println!("---");
    }
    
    Ok(())
}
常用日期格式模式
格式字符串 示例输入 说明
"%Y-%m-%d" "2024-03-15" ISO 日期格式
"%d/%m/%Y" "15/03/2024" 欧洲格式
"%m-%d-%Y" "03-15-2024" 美国格式
"%d.%m.%Y" "15.03.2024" 德国格式
"%Y年%m月%d日" "2024年03月15日" 中文格式
"%Y%m%d" "20240315" 紧凑格式
"%Y-%m-%d %H:%M:%S" "2024-03-15 14:30:00" 日期时间格式
"%Y/%m/%d %H:%M" "2024/03/15 14:30" 自定义日期时间
"%Y-%m-%d %H:%M:%S %z" "2024-03-15 14:30:00 +0800" 带时区格式
自定义日期格式的优势
  • 精确控制:为每个字段指定确切的格式
  • 无需包装类型:直接使用 chrono 类型
  • 类型安全:编译时格式验证
  • 灵活性:支持可选字段
  • 清晰语法:声明式且直观
  • 错误处理:详细的错误信息便于调试

第三方类型支持

库通过可选的特性标志为流行的第三方类型提供内置支持。这对于需要高精度算术或日期/时间处理的金融应用程序特别有用。

启用第三方类型

在您的 Cargo.toml 中添加所需的特性:

[dependencies]
# 启用特定类型
tushare-api = { version = "1.2.7", features = ["rust_decimal", "chrono"] }

# 或启用所有第三方类型
tushare-api = { version = "1.2.7", features = ["all_types"] }
高精度小数示例
use tushare_api::{TushareClient, Api, request, TushareEntityList, DeriveFromTushareData};

#[derive(Debug, Clone, DeriveFromTushareData)]
pub struct FinancialData {
    #[tushare(field = "ts_code")]
    pub stock_code: String,
    
    #[tushare(field = "trade_date")]
    pub date: String,
    
    // 用于金融计算的高精度小数
    #[tushare(field = "close")]
    pub close_price: rust_decimal::Decimal,
    
    #[tushare(field = "vol")]
    pub volume: Option<rust_decimal::Decimal>,
    
    #[tushare(field = "amount")]
    pub amount: Option<rust_decimal::Decimal>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = TushareClient::from_env()?;
    
    let data: TushareEntityList<FinancialData> = client.call_api_as(request!(
        Api::Daily, {
            "ts_code" => "000001.SZ",
            "trade_date" => "20240315"
        }, [
            "ts_code", "trade_date", "close", "vol", "amount"
        ]
    )).await?;
    
    for record in data.iter() {
        println!("股票: {} - 价格: {} 日期: {}", 
                 record.stock_code, 
                 record.close_price, 
                 record.date);
    }
    
    Ok(())
}
日期/时间类型示例
use tushare_api::{TushareClient, Api, request, TushareEntityList, DeriveFromTushareData};

#[derive(Debug, Clone, DeriveFromTushareData)]
pub struct DateTimeData {
    #[tushare(field = "ts_code")]
    pub stock_code: String,
    
    // 从 YYYYMMDD 格式自动解析
    #[tushare(field = "trade_date")]
    pub trade_date: chrono::NaiveDate,
    
    // 可选的日期时间字段
    #[tushare(field = "update_time")]
    pub update_time: Option<chrono::NaiveDateTime>,
    
    // 高精度价格
    #[tushare(field = "close")]
    pub close_price: rust_decimal::Decimal,
}
支持的第三方类型
类型 特性标志 说明 示例值
rust_decimal::Decimal rust_decimal 高精度小数 "123.456", 123.456
bigdecimal::BigDecimal bigdecimal 任意精度 "999999999999999999999.123"
chrono::NaiveDate chrono 无时区日期 "20240315", "2024-03-15"
chrono::NaiveDateTime chrono 无时区日期时间 "2024-03-15 14:30:00"
chrono::DateTime<Utc> chrono UTC 日期时间 RFC3339 格式
uuid::Uuid uuid UUID 类型 "550e8400-e29b-41d4-a716-446655440000"

详细文档和示例请参阅 第三方类型指南

手动转换(替代方法)

如果您不想使用过程宏,仍然可以使用手动方法:

use tushare_api::{TushareClient, Api, request, utils::response_to_vec, traits::FromTushareData};
use tushare_api::error::TushareError;
use serde_json::Value;

#[derive(Debug, Clone)]
pub struct Stock {
    pub ts_code: String,
    pub name: String,
    pub area: Option<String>,
}

// 手动实现 FromTushareData
impl FromTushareData for Stock {
    fn from_row(fields: &[String], values: &[Value]) -> Result<Self, TushareError> {
        let ts_code_idx = fields.iter().position(|f| f == "ts_code")
            .ok_or_else(|| TushareError::ParseError("缺少 ts_code 字段".to_string()))?;
        let name_idx = fields.iter().position(|f| f == "name")
            .ok_or_else(|| TushareError::ParseError("缺少 name 字段".to_string()))?;
        let area_idx = fields.iter().position(|f| f == "area");
            
        Ok(Stock {
            ts_code: values[ts_code_idx].as_str()
                .ok_or_else(|| TushareError::ParseError("无效的 ts_code".to_string()))?
                .to_string(),
            name: values[name_idx].as_str()
                .ok_or_else(|| TushareError::ParseError("无效的 name".to_string()))?
                .to_string(),
            area: area_idx.and_then(|idx| values[idx].as_str().map(|s| s.to_string())),
        })
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = TushareClient::from_env()?;
    
    // 获取原始响应
    let response = client.call_api(request!(Api::StockBasic, {
        "list_status" => "L"
    }, [
        "ts_code", "name", "area"
    ])).await?;
    
    // 转换为 Vec<Stock>
    let stocks = response_to_vec::<Stock>(response)?;
    
    println!("找到 {} 只股票", stocks.len());
    for stock in stocks.iter().take(3) {
        println!("  {}: {} - 地区: {:?}", stock.ts_code, stock.name, stock.area);
    }
    
    Ok(())
}

5. 如何设置日志

使用 env_logger

// 设置日志级别并初始化日志器
std::env::set_var("RUST_LOG", "tushare_api=debug");
env_logger::init();

// 创建带日志配置的客户端
let client = TushareClient::builder()
    .with_token("your_token_here")
    .with_log_level(LogLevel::Debug)
    .log_requests(true)        // 记录请求详情
    .log_responses(false)      // 不记录响应内容(可能很大)
    .log_sensitive_data(false) // 不记录敏感数据如 token
    .log_performance(true)     // 记录性能指标
    .build()?;

使用 tracing(可选特性)

首先,在您的 Cargo.toml 中启用 tracing 特性:

[dependencies]
tushare-api = { version = "1.2.7", features = ["tracing"] }
tracing = "0.1"
tracing-subscriber = "0.3"

然后在您的代码中:

use tracing_subscriber;

// 初始化 tracing 订阅器
std::env::set_var("RUST_LOG", "tushare_api=trace");
tracing_subscriber::fmt()
    .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
    .init();

// 客户端配置保持不变
let client = TushareClient::builder()
    .with_token("your_token_here")
    .with_log_level(LogLevel::Trace)
    .build()?;

使用 tracing-log 桥接

use tracing_subscriber;
use tracing_log::LogTracer;

// 初始化 log-to-tracing 桥接
LogTracer::init()?;

// 设置 tracing 订阅器
std::env::set_var("RUST_LOG", "tushare_api=debug");
tracing_subscriber::fmt()
    .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
    .init();

日志级别和输出

  • LogLevel::Off:无日志
  • LogLevel::Error:仅错误
  • LogLevel::Warn:错误和警告
  • LogLevel::Info:基本 API 调用信息(默认)
  • LogLevel::Debug:详细的请求/响应信息
  • LogLevel::Trace:所有信息,包括原始响应内容

示例日志输出:

INFO  [abc123] Starting Tushare API call: stock_basic, params count: 2, fields count: 3
DEBUG [abc123] API request details - API: stock_basic, params: {...}, fields: [...]
DEBUG [abc123] Sending HTTP request to Tushare API
DEBUG [abc123] Received HTTP response, status code: 200
INFO  [abc123] API call successful, duration: 245ms, data rows returned: 100

🧪 运行示例

# 设置您的 token
export TUSHARE_TOKEN="your_token_here"

# 运行基础示例
cargo run --example basic_usage

# 运行日志示例
cargo run --example logging_example

# 运行 tracing 示例(需要 tracing 特性)
cargo run --example tracing_example --features tracing

📄 许可证

本项目采用 MIT 许可证 - 详情请参阅 LICENSE 文件。

📞 支持

Commit count: 43

cargo fmt