1 unstable release

0.0.9 Mar 30, 2024

#349 in Debugging

32 downloads per month
Used in xray-lite-aws-sdk

MIT license

71KB
1.5K SLoC

xray-lite

AWS X-Ray daemon client for Rust applications on AWS Lambda

Installing xray-lite

Add the following to your Cargo.toml file:

[dependencies]
xray-lite = "0.0.9"

Usage

Subsegment of AWS service operation

The xray-lite-aws-sdk extension is recommended for tracing operations through AWS SDK for Rust.

Here is an example to record a subsegment of an AWS service operation within a Lambda function invocation instrumented with AWS X-Ray:

use xray_lite::{AwsNamespace, Context, DaemonClient, SubsegmentContext};

fn main() {
    // reads AWS_XRAY_DAEMON_ADDRESS
    let client = DaemonClient::from_lambda_env().unwrap();
    // reads _X_AMZN_TRACE_ID
    let context = SubsegmentContext::from_lambda_env(client).unwrap();

    do_s3_get_object(&context);
}

fn do_s3_get_object(context: &impl Context) {
    // subsegment will have the name "S3" and `aws.operation` "GetObject"
    let subsegment = context.enter_subsegment(AwsNamespace::new("S3", "GetObject"));

    // call S3 GetObject ...

    // if you are using `aws-sdk-s3` crate, you can update the subsegment
    // with the request ID. suppose `out` is the output of the `GetObject`
    // operation:
    //
    //     subsegment
    //         .namespace_mut()
    //         .zip(out.request_id())
    //         .map(|(ns, id)| ns.request_id(id));

    // the subsegment will be ended and reported when it is dropped
}

Subsegment of a remote service call

Here is an example to record a subsegment of a remote service call within a Lambda function invocation instrumented with AWS X-Ray:

use xray_lite::{Context, DaemonClient, RemoteNamespace, SubsegmentContext};

fn main() {
    // reads AWS_XRAY_DAEMON_ADDRESS
    let client = DaemonClient::from_lambda_env().unwrap();
    // reads _X_AMZN_TRACE_ID
    let context = SubsegmentContext::from_lambda_env(client).unwrap();

    do_some_request(&context);
}

fn do_some_request(context: &impl Context) {
    // subsegment will have the name "readme example",
    // `http.request.method` "POST", and `http.request.url` "https://codemonger.io/"
    let subsegment = context.enter_subsegment(RemoteNamespace::new(
        "readme example",
        "GET",
        "https://codemonger.io/",
    ));

    // do some request ...

    // the subsegment will be ended and reported when it is dropped
}

Custom subsegment

Here is an example to record a custom subsegment within a Lambda function invocation instrumented with AWS X-Ray:

use xray_lite::{Context, DaemonClient, CustomNamespace, SubsegmentContext};

fn main() {
    // reads AWS_XRAY_DAEMON_ADDRESS
    let client = DaemonClient::from_lambda_env().unwrap();
    // reads _X_AMZN_TRACE_ID
    let context = SubsegmentContext::from_lambda_env(client).unwrap()
        .with_name_prefix("readme_example.");

    do_something(&context);
}

fn do_something(context: &impl Context) {
    // subsegment will have the name "readme_example.do_something"
    let subsegment = context.enter_subsegment(CustomNamespace::new("do_something"));

    // do some thing ...

    // the subsegment will be ended and reported when it is dropped
}

Infallible client and context

As X-Ray tracing is likely a subsidiary feature of your Lambda function, you may want to ignore any error that might occur during the initialization of the client and the context. By using the helper traits IntoInfallibleClient and IntoInfallibleContext, you can ignore such errors without affecting the rest of your code:

use xray_lite::{
    AwsNamespace,
    Context,
    DaemonClient,
    IntoInfallibleClient as _,
    IntoInfallibleContext as _,
    SubsegmentContext,
};

fn main() {
    // Client creation error is ignored; e.g., AWS_XRAY_DAEMON_ADDRESS is not set
    let client = DaemonClient::from_lambda_env().into_infallible();
    // Context creation error is ignored; e.g., _X_AMZN_TRACE_ID is not set
    let context = SubsegmentContext::from_lambda_env(client).into_infallible();

    do_s3_get_object(&context);
}

fn do_s3_get_object(context: &impl Context) {
    let subsegment = context.enter_subsegment(AwsNamespace::new("S3", "GetObject"));

    // call S3 GetObject ...
}

Extensions

API Documentation

Acknowledgements

This project is built on top of the great work of Doug Tangren (softprops).

Dependencies

~1–2MB
~40K SLoC