Code Monkey home page Code Monkey logo

rustracing_jaeger's Introduction

rustracing_jaeger

Crates.io: rustracing_jaeger Documentation Actions Status Coverage Status License: MIT

Jaeger client library created on top of rustracing.

Documentation

Examples

Basic Usage

use rustracing::sampler::AllSampler;
use rustracing_jaeger::Tracer;
use rustracing_jaeger::reporter::JaegerCompactReporter;

// Creates a tracer
let (span_tx, span_rx) = crossbeam_channel::bounded(10);
let tracer = Tracer::with_sender(AllSampler, span_tx);
{
    let span = tracer.span("sample_op").start();
    // Do something

} // The dropped span will be sent to `span_rx`

let span = span_rx.try_recv().unwrap();
assert_eq!(span.operation_name(), "sample_op");

// Reports this span to the local jaeger agent
let reporter = JaegerCompactReporter::new("sample_service").unwrap();
reporter.report(&[span]).unwrap();

Executes report.rs example

# Run jaeger in background
$ docker run -d -p6831:6831/udp -p6832:6832/udp -p16686:16686 jaegertracing/all-in-one:latest

# Report example spans
$ cargo run --example report

# View spans (see the image below)
$ firefox http://localhost:16686/

Jaeger UI

References

rustracing_jaeger's People

Contributors

anirudhrowjee avatar bobrik avatar jyn514 avatar kornelski avatar matevz avatar mixalturek avatar renkai avatar sile avatar vavrusa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

rustracing_jaeger's Issues

Enable injectors and extractors bound to tracer

In jaeger-client-go propagators (injector + extractor concept) are bound to tracers, which makes it possible to wrap a default implementations. For example, we were able to sign HTTP headers with an HMAC key bound to tracer, with user working with an opaque OpenTracing interface.

It would be nice to have the same ability in rust implementation.

Bind to localhost instead of INADDR_ANY for reporter UDP socket creation

In

fn udp_socket(agent: SocketAddr) -> Result<UdpSocket> {
track!(UdpSocket::bind({
if agent.is_ipv6() {
SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), 0)
} else {
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0)
}
})
.map_err(error::from_io_error))
}
, we bind to all addresses (::0 and 0.0.0.0) to create an ephemeral port for reporting. Binding to INADDR_ANY for UDP ports increases the attack surface for potential denial of service since INADDR_ANY UDP ports will always accept all traffic that comes its way.

A proposed fix is to only bind to localhost for both ipv4 and ipv6. As far as I can tell, this won't change existing functionality & will still pass tests. This will ultimately just be two lines changed:
src/reporter.rs line 167: SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 0)
src/reporter.rs line 169: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0)

I understand that since we're using an ephemeral port the risk isn't quite as big for DoS as a privileged port, however we're doing some network cleanup and found that a few of our applications unnecessarily use INADDR_ANY, so making this fix would clean up a lot of these patterns.

Make it possible to retrieve `flags`

Right now, SpanContextState::flags() is crate-private, making it impossible to retrieve the flags (e.g. for serialization to another service). It would be nice for it to be public instead; I'm having to use opentelemetry-jaeger instead in the meantime.

Help wanted: Use span and Sub-span

Hi,

Could you help me regarding child span?

I try to have span:

  • Span: Get-mydemoapp
    • SubSpan: get-version

I don't really understand how to do that.

Thanks a lot.

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;


use iron::prelude::*;
use iron::status;
use iron::mime::Mime;
use std::io::Read;

use rustracing_jaeger::span::Span;
use rustracing_jaeger::Tracer;
use rustracing::sampler::AllSampler;
use rustracing_jaeger::reporter::JaegerCompactReporter;
use rustracing::tag::Tag;





#[derive(Serialize, Deserialize, Debug)]
struct User {
    user: String
}

pub fn get_form(req: &mut Request) -> IronResult<Response> {
    
    let mut ver = String::new();
    let raw_content_type = req.headers.get_raw("");
    println!("Headers: {:?}", raw_content_type);

    let (tracer, span_rx) = Tracer::new(AllSampler);
    {
        let span = tracer.span("Get-mydemoapp").start();
        ver = get_version(span, tracer);
    }
    
    let span = span_rx.try_recv().unwrap();
    println!("Span_RX {:?}", span_rx);

    // assert_eq!(span.operation_name(), "Get-mydemoapp");
    let reporter = JaegerCompactReporter::new("MyDemoApp").unwrap();
    for span in span_rx {
        reporter.report(&[span]);
    }
    // reporter.report(&[span]).unwrap();

    let mime = "application/json".parse::<Mime>().unwrap();
    Ok(Response::with((mime, status::Ok, ver)))
}

fn get_version(context: Span, tracer: Tracer) -> String {
    let mut ver = String::new();
    // let tracer = tracer.clone();  
    let mut span1 = tracer
                .span("get-version")
                .child_of(&context)
                .tag(Tag::new("Version", "0.1"))
                .start();
    span1.log(|log| {
        log.error().message("something wrong");
        });
    println!("Span0 {:?}", context);
    println!("Span1 {:?}", span1);
    ver.push_str("Version v0.1.0");
    ver
}```

Remove the requirement to use `crossbeam`

Right now, Tracer requires that you pass in a crossbeam channel. Because crossbeam is blocking, this makes it impossible to use rustracing_jaeger with an async application; you have to instead spawn a thread to avoid blocking the task. It would be nice to have the tracer just take spans directly, which lets the user decide whether they want to use threads or async (or just block on sending the span).

(maybe this should be an issue in https://github.com/sile/rustracing instead?)

Allow generating span from known TraceId

I'm instrumenting a system that's already using trace IDs, and would like a clean way to use that existing trace ID to generate a span (right now only way I'm aware of is to generate a fake header string and use SpanContextState's FromStr impl).

In general this would allow broader support of custom carrier formats (even if it's just custom header names).

From what I can see, the easiest way to do that would be to make SpanContextState::with_trace_id public, but there might be better ways to do it in order to keep the api clean.

Constructing TraceId from String

How can I generate a 128-bit TraceId from a string like 129fb82c233ed2ae7782257c92481779%3A7782257c92481779%3A0%3A1? The TraceId accepts a high and low number, but I'm not sure of how to extract those in Rust.

Running into an error when using an alternative SocketAddr.

When using set_agent_addr using both the compact and binary reporter, the system seems to be failing.

I am using the all-in-one agent, running in docker. The all-in-one and the service which is generating this stacktrace, are both on the same docker network, and can route to each other. The all-in-one is configured as described in the jaeger docs.

thread '<unnamed>' panicked at 'Failed to send trace.: Error(TrackableError { kind: Other,
cause: Some(Os { code: 22, kind: InvalidInput, message: "Invalid argument" }),
history: History([Track(Location { module_path: "rustracing_jaeger::reporter",
file: "/usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/rustracing_jaeger-0.1.4/src/reporter.rs",
line: 159, message: "" }), Track(Location { module_path: "rustracing_jaeger::reporter",
file: "/usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/rustracing_jaeger-0.1.4/src/reporter.rs",
line: 102, message: "" })]) })', libcore/result.rs:945:5
stack backtrace:
   0:     0x559a3940f9b3 - std::sys::unix::backtrace::tracing::imp::unwind_backtrace::h8b81594645a24a27
                               at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1:     0x559a39409ce4 - std::sys_common::backtrace::_print::h9bc07d566820e560
                               at libstd/sys_common/backtrace.rs:71
   2:     0x559a3940e3ed - std::panicking::default_hook::{{closure}}::h8061f115b067df97
                               at libstd/sys_common/backtrace.rs:59
                               at libstd/panicking.rs:380
   3:     0x559a3940e0f2 - std::panicking::default_hook::hd067eb3eb1a62c48
                               at libstd/panicking.rs:396
   4:     0x559a3940e860 - std::panicking::rust_panic_with_hook::h45183031f05ee04c
                               at libstd/panicking.rs:576
   5:     0x559a3940e6ae - std::panicking::begin_panic::h9ee67e5b096c21ab
                               at libstd/panicking.rs:537
   6:     0x559a3940e619 - std::panicking::begin_panic_fmt::he72e33953442af8b
                               at libstd/panicking.rs:521
   7:     0x559a3940e5a2 - rust_begin_unwind
                               at libstd/panicking.rs:497
   8:     0x559a39453fb0 - core::panicking::panic_fmt::hc4dea8542bac164c
                               at libcore/panicking.rs:71
   9:     0x559a38dbf5a7 - core::result::unwrap_failed::he9a5bc32c056badf
                               at /checkout/src/libcore/macros.rs:23
  10:     0x559a38dbd6d0 - <core::result::Result<T, E>>::expect::h84035c0c3a5db2a4
                               at /checkout/src/libcore/result.rs:809
  11:     0x559a38dc1824 - gateway_service::trace_emitter::h4616a61519895d37
                               at src/bin/gateway-service.rs:82
  12:     0x559a38e06e1b - gateway_service::main::{{closure}}::h34a8ef0f05e0c94d
                               at src/bin/gateway-service.rs:55
  13:     0x559a38e17f1b - std::sys_common::backtrace::__rust_begin_short_backtrace::h1417833fefa4bd66
                               at /checkout/src/libstd/sys_common/backtrace.rs:136
  14:     0x559a38dc39c5 - std::thread::Builder::spawn::{{closure}}::{{closure}}::h408105891343468a
                               at /checkout/src/libstd/thread/mod.rs:406
  15:     0x559a38e06fc1 - <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once::hc17189e1209a3c76
                               at /checkout/src/libstd/panic.rs:293
  16:     0x559a38de8591 - std::panicking::try::do_call::h96cb67a132d1ade4
                               at /checkout/src/libstd/panicking.rs:479
  17:     0x559a3941994e - __rust_maybe_catch_panic
                               at libpanic_unwind/lib.rs:102
  18:     0x559a38de825c - std::panicking::try::hc3afa170fb79ed25
                               at /checkout/src/libstd/panicking.rs:458
  19:     0x559a38e070f3 - std::panic::catch_unwind::had632088dcfd6bc2
                               at /checkout/src/libstd/panic.rs:358
  20:     0x559a38dc351a - std::thread::Builder::spawn::{{closure}}::hd348c61cc1485b06
                               at /checkout/src/libstd/thread/mod.rs:405
  21:     0x559a38dc3a15 - <F as alloc::boxed::FnBox<A>>::call_box::hc6c90317650b9686
                               at /checkout/src/liballoc/boxed.rs:788
  22:     0x559a394118bb - std::sys::unix::thread::Thread::new::thread_start::hdd261da30813e955
                               at /checkout/src/liballoc/boxed.rs:798
                               at libstd/sys_common/thread.rs:24
                               at libstd/sys/unix/thread.rs:90
  23:     0x7f0a7aa18493 - start_thread
  24:     0x7f0a7a543afe - __clone
  25:                0x0 - <unknown>

Any ideas?

Ability to send spans directly to collector over HTTP

First of all, I'm new to Jaeger so I don't know if I'm asking exactly the right question. But, it seems like rustracing_jaeger is a client which requires a jaeger-agent to be running on the same machine (or the jaeger-all-in-one docker image which also includes a jaeger-agent).

Is there any way to configure the client to bypass the Agent and send spans to a remote Collector directly over HTTP, i.e. using port 14268 in the default Collector config? If not, how hard would this be to add? I would consider adding it if you don't want to, and if it would be beneficial for others, because it would certainly be beneficial for me. Any advice on this?

Logs & Tags not coming through to Jaeger UI.

When adding tags or logs to a span, it appears as though they are not set.

  • the traces are properly emitted to the collector.
  • they show up in the Jaeger UI as expected.
  • none of the logs or tags show up at all (operation name is good though).

I would love to add more context, but I'm not really doing anything other than what is shown in the example. I'll add more context if needed.

I did notice that the set_tag method calls this on the inside: if let Some(inner) = self.0.as_mut() {. Perhaps the Span's inner value is not being properly set. It is optional after all. Are there any paths you are aware of which could cause this to take place???

Automatically set ip tag

There's already a constant for it: TRACER_IP_TAG_KEY.

Jaeger uses ip tag to group spans around individual machines for clock skew adjustment and with futures it's easy to mess up and make child spans outlive parents, triggering time travel bamboozle:

It's probably best to infer ip tag automatically just like C++ and Go clients do.

reporter: support for async futures-based report()

I'm still learning/experimenting with this crate, so sorry if this is already covered somehow and I missed it.

I'd like to integrate span-tracing and report-sending logic into an existing futures-based asynchronous application, however it looks like all existing reporters here only have a synchronous/blocking report() method. Would you consider expanding this library to be easily pluggable into futures-based chains? Also having a simple example on how to to plug together tracing, asynchronous tasks and jaeger reporting would help.

Last but not least, thanks for writing this library!

Example panics

Running cargo run --example report produces:

>pop-os:~/projects/tracing-opentelemetry$ cargo run --example report
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/examples/report`
thread 'main' panicked at 'trace_id should exist', src/layer.rs:51:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

rustc 1.43.0-nightly (c20d7eecb 2020-03-11)
commit d803c9e81ad4c04ffc45de0434706c75cc2c7b05

Example incorrect

Sorry to bother you, I'm just a newbie about both Rust and OpenTracing, but the correct command to launch jaeger's container is:
docker run -d -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p5775:5775/udp -p6831:6831/udp -p6832:6832/udp -p5778:5778 -p16686:16686 -p14268:14268 -p9411:9411 jaegertracing/all-in-one:latest

Using the command written on your example ends on a non-collecting jaeger.
Sorry again,
best regards

Help wanted: Span never received from actix-web thread

Hello. Please push me in the right direction. I'm not asking for a full-working code, just give me a hint, please.

init code:

        let (span_tx, span_rx) = crossbeam_channel::unbounded();
        let tracer = web::Data::new(Mutex::new(Tracer::with_sender(AllSampler, span_tx)));

        let app = App::new()
            .app_data(tracer)
            .route("/path", web::get().to(route_handler));

        if let Ok(reporter) = JaegerCompactReporter::new("name") {
            while let Ok(span) = span_rx.try_recv() {
                //     this never happens
                println!("span: {:?}", &span); 
                let _ = reporter.report(&[span]);
            }
        }

route_handler:

pub async fn route_handler(tracer: web::Data<Mutex<Tracer>>) -> HttpResponse {
    let _span = match tracer.lock() {
        Ok(guard_tracer) => Some(guard_tracer.span("example_span").start()),
        Err(_) => None
    };
   // ...
}

By debugging I found that everything is ok with the reporter and span, the only issue that span_rx.try_recv() never yields a non-empty result.
Maybe it's somehow related to the async-await, I don't know.

What is the expected way of using this library across threads?

For example, given a gRPC server using a thread based concurrency model, is it expected that each request (being handled on a separate thread) would instantiate a new Tracer::new(AllSampler)?

I would prefer to be able to inject the tracer as a middleware, and then clone it per thread or something of the sort.

Any ideas? I may be totally missing something as well.

Impl OpenTracing default carrier traits for SpanContextState.

So, after lots of digging through this lib, and refining the original issue that I opened here, it seems that one of the main things that needs to be finished up with this lib is to:

  1. finish up the impl of InjectToHttpHeader for SpanContextState.
  2. finish up the impls of the other OpenTracing default carrier types for SpanContextState as well (the inject & extract for TextMap & Binary).

Also, after evaluating the code a bit, it looks like we just need to come up with a convention for how to consistently communicate the different fields of the carrier.

A few other OT libs that I looked at in other languages seem to be using a key naming convention, and baggage items are simply prefixed with something like baggage- and then when extracted the prefix is removed.

We could certainly do something like that. Seems as though there is no standard for how that is supposed to be done according to the OT spec. Using a common nomenclature for the keys & baggage prefix should do the trick though.

Thoughts?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.