Code Monkey home page Code Monkey logo

jaeger-client-ruby's Introduction

Jaeger::Client

Gem Version Build Status

This project is not actively maintained. Please consider using OpenTelemetry

OpenTracing Tracer implementation for Jaeger in Ruby

Installation

Add this line to your application's Gemfile:

gem 'jaeger-client'

Usage

require 'jaeger/client'
OpenTracing.global_tracer = Jaeger::Client.build(host: 'localhost', port: 6831, service_name: 'echo')

OpenTracing.start_active_span('span name') do
  # do something

  OpenTracing.start_active_span('inner span name') do
    # do something else
  end
end

# don't kill the program too soon, allow time for the background reporter to send the traces
sleep 2

See opentracing-ruby for more examples.

Reporters

RemoteReporter (default)

RemoteReporter buffers spans in memory and sends them out of process using Sender.

There are two senders: UdpSender (default) and HttpSender.

To use HttpSender:

OpenTracing.global_tracer = Jaeger::Client.build(
  service_name: 'service_name',
  reporter: Jaeger::Reporters::RemoteReporter.new(
    sender: Jaeger::HttpSender.new(
      url: 'http://localhost:14268/api/traces',
      headers: { 'key' => 'value' }, # headers key is optional
      encoder: Jaeger::Encoders::ThriftEncoder.new(service_name: 'service_name')
    ),
    flush_interval: 10
  )
)

NullReporter

NullReporter ignores all spans.

OpenTracing.global_tracer = Jaeger::Client.build(
  service_name: 'service_name',
  reporter: Jaeger::Reporters::NullReporter.new
)

LoggingReporter

LoggingReporter prints some details about the span using logger. This is meant only for debugging. Do not parse and use this information for anything critical. The implemenation can change at any time.

OpenTracing.global_tracer = Jaeger::Client.build(
  service_name: 'service_name',
  reporter: Jaeger::Reporters::LoggingReporter.new
)

LoggingReporter can also use a custom logger. For this provide logger using logger keyword argument.

Samplers

Const sampler

Const sampler always makes the same decision for new traces depending on the initialization value. Set sampler to: Jaeger::Samplers::Const.new(true) to mark all new traces as sampled.

Probabilistic sampler

Probabilistic sampler samples traces with probability equal to rate (must be between 0.0 and 1.0). This can be enabled by setting Jaeger::Samplers::Probabilistic.new(rate: 0.1)

RateLimiting sampler

RateLimiting sampler samples at most max_traces_per_second. The distribution of sampled traces follows burstiness of the service, i.e. a service with uniformly distributed requests will have those requests sampled uniformly as well, but if requests are bursty, especially sub-second, then a number of sequential requests can be sampled each second.

Set sampler to Jaeger::Samplers::RateLimiting.new(max_traces_per_second: 100)

GuaranteedThroughputProbabilistic sampler

GuaranteedThroughputProbabilistic is a sampler that guarantees a throughput by using a Probabilistic sampler and RateLimiting sampler The RateLimiting sampler is used to establish a lower_bound so that every operation is sampled at least once in the time interval defined by the lower_bound.

Set sampler to Jaeger::Samplers::GuaranteedThroughputProbabilistic.new(lower_bound: 10, rate: 0.001)

PerOperation sampler

PerOperation sampler leverages both Probabilistic sampler and RateLimiting sampler via the GuaranteedThroughputProbabilistic sampler. This sampler keeps track of all operations and delegates calls the the respective GuaranteedThroughputProbabilistic sampler.

Set sampler to

  Jaeger::Samplers::PerOperation.new(
    strategies: {
      per_operation_strategies: [
        { operation: 'GET /articles', probabilistic_sampling: { sampling_rate: 0.5 } },
        { operation: 'POST /articles', probabilistic_sampling: { sampling_rate: 1.0 } }
      ],
      default_sampling_probability: 0.001,
      default_lower_bound_traces_per_second: 1.0 / (10.0 * 60.0)
    },
    max_operations: 1000
  )

RemoteControlled sampler

RemoteControlled sampler is a sampler that is controller by jaeger agent. It starts out with Probabilistic sampler. It polls the jaeger-agent and changes sampling strategy accordingly. Set sampler to Jaeger::Client::Samplers::RemoteControlled.new(service_name: 'service_name').

RemoteControlled sampler options:

Param Required Description
service_name x name of the current service / application, same as given to Tracer
sampler initial sampler to use prior to retrieving strategies from Agent
refresh_interval interval in seconds before sampling strategy refreshes (0 to not refresh, defaults to 60)
host host for jaeger-agent (defaults to 'localhost')
port port for jaeger-agent for SamplingManager endpoint (defaults to 5778)
logger logger for communication between jaeger-agent (default to $stdout logger)

TraceContext compatible header propagation

It is possible to use W3C Trace Context headers to propagate the tracing information.

To set it up you need to change FORMAT_RACK injector and extractor.

OpenTracing.global_tracer = Jaeger::Client.build(
  service_name: 'service_name',
  injectors: {
    OpenTracing::FORMAT_RACK => [Jaeger::Injectors::TraceContextRackCodec]
  },
  extractors: {
    OpenTracing::FORMAT_RACK => [Jaeger::Extractors::TraceContextRackCodec]
  }
)

Zipkin HTTP B3 compatible header propagation

Jaeger Tracer supports Zipkin B3 Propagation HTTP headers, which are used by a lot of Zipkin tracers. This means that you can use Jaeger in conjunction with OpenZipkin tracers.

To set it up you need to change FORMAT_RACK injector and extractor.

OpenTracing.global_tracer = Jaeger::Client.build(
  service_name: 'service_name',
  injectors: {
    OpenTracing::FORMAT_RACK => [Jaeger::Injectors::B3RackCodec]
  },
  extractors: {
    OpenTracing::FORMAT_RACK => [Jaeger::Extractors::B3RackCodec]
  }
)

It's also possible to set up multiple injectors and extractors. Each injector will be called in sequence. Note that if multiple injectors are using the same keys then the values will be overwritten.

If multiple extractors is used then the span context from the first match will be returned.

Process Tags

Jaeger Tracer allows you to define process level tags. By default the tracer provides jaeger.version, ip and hostname. You may want to overwrite ip or hostname if the tracer cannot auto-detect them.

OpenTracing.global_tracer = Jaeger::Client.build(
  service_name: 'service_name',
  tags: {
    'hostname' => 'custom-hostname',
    'custom_tag' => 'custom-tag-value'
  }
)

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/salemove/jaeger-client-ruby

License

The gem is available as open source under the terms of the MIT License.

jaeger-client-ruby's People

Contributors

achandras avatar c0va23 avatar chadmetcalf-cb avatar cmur2 avatar davidor avatar felipeelias avatar indrekj avatar jgpaiva avatar kamina-zzz avatar kruczjak avatar liukgg avatar luong-komorebi avatar meinac avatar seanlf avatar sliiser avatar tnir avatar tpltn avatar willmore 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

Watchers

 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

jaeger-client-ruby's Issues

Test 'Jaeger::Encoders::ThriftEncoder without custom tags has ip' fails if there is only IPv6 available

Hi,

as part of the packaging efforts in the Debian Linux project, we build and test all packages in IPv6-only environments. In such an environment, one test will fail, and we were wondering if you would be willing to have a look at it and deal with this:

...
Failures:

  1) Jaeger::Encoders::ThriftEncoder without custom tags has ip
     Failure/Error: expect(ip_tag.vStr).to be_a(String)

     NoMethodError:
       undefined method `vStr' for nil:NilClass
     # ./spec/jaeger/encoders/thrift_encoder_spec.rb:40:in `block (3 levels) in <top (required)>'

Finished in 0.30993 seconds (files took 0.58969 seconds to load)
187 examples, 1 failure
...

https://bugs.debian.org/1000649

how to read the trace id of a trace

The UI on the top left has a nice search box to search by trace ID and it's great that you can share a trace x for analysis with others by sharing the URL http://your-jaeger-host:16686/trace/x

However, it's not clear at least to me, how to read the trace id of a trace.

The following is a way to have it as a tag. This is at the call method of a custom rails middleware that takes env as an argument. I tried first to use 'set_baggage_item' but at the UI I only see tags.

tracer.start_active_span(...) do |scope|                                                                                                                                                                                      
  scope.span.set_tag('trace-id', scope.span.context.trace_id.to_s(16))                                                                                                                            
  result = @app.call(env).tap do |status_code, _headers, _body|                                                                                                                                   
  end                                                                                                                                                                                             
end

Is there a better way?

logs reported twice

The logs 'Span reported' are reported twice in rails. Is the following instantiation of LoggingReporter correct?

Jaeger::Client.build(
  host: jaeger_host,
  port: 5775,
  service_name: 'CompleteService',
  reporter: Jaeger::Reporters::LoggingReporter.new
)

If I do not use the reported argument, then I do not see logs with the words "Span reported".

Build correct data type of each tag

At the moment, the Collector is building only string tags:

def build_tag(name, value)
  Jaeger::Thrift::Tag.new(
    'key' => name.to_s,
    'vType' => Jaeger::Thrift::TagType::STRING,
    'vStr' => value.to_s
  )
end

Probably a simple case statement for the value would solve the issue.

Process-level tags unsupported in rubygems version.

It appears that process-level tags, along with some other features, are unsupported in the latest release, but they are on master. Would it be possible for a new release to be cut and pushed to rubygems?

[question] How to inject extra headers

Hi,

I'm having some trouble figuring out how to set extra headers for the injectors and extractors. Would you mind providing an example for doing so?

These are the headers I need based on https://istio.io/docs/tasks/telemetry/distributed-tracing/#understanding-what-happened

x-request-id
x-b3-traceid
x-b3-spanid
x-b3-parentspanid
x-b3-sampled
x-b3-flags
x-ot-span-context

The following example seems to be configured globally so it'll be great if there's an way of how to inject/extract extra headers into the client without me having to fork and modify the code.

OpenTracing.global_tracer = Jaeger::Client.build(
  service_name: 'my-service',
  reporter: Jaeger::Reporters::RemoteReporter.new(
    sender: Jaeger::HttpSender.new(
      url: 'http://jaeger-collector.istio-system.svc.cluster.local:14268/api/traces',
      # headers: { 'test' => 'YOLO' }, # i won't be able to know the values beforehand
      encoder: Jaeger::Encoders::ThriftEncoder.new(service_name: 'my-service')
    ),
    flush_interval: 1
  ),
  injectors: {
    OpenTracing::FORMAT_RACK => [Jaeger::Injectors::B3RackCodec]
  },
  extractors: {
    OpenTracing::FORMAT_RACK => [Jaeger::Extractors::B3RackCodec]
  }
)
Jaeger::Samplers::Probabilistic.new(rate: 1.0)

get '/' do
  return 'hello world'
end

Follows_from references does not work

Hi!

I am trying to do an async span but it does not work. I am using the following snippet.

span_context = OpenTracing.extract(OpenTracing::FORMAT_TEXT_MAP, meta)

OpenTracing.start_active_span(
  "JOB PERFORM #{self.class.name}",
  references: [
    OpenTracing::Reference.follows_from(span_context)
  ],
  tags: {
    'component' => 'active-job',
    'span.kind' => 'consumer',
    'job_id' => self.job_id,
    'request_id' => request_id
  }
)

But in jaeger my span graph shows this span like a childOf instead of 'followsFrom'. See in the picture.
Screen Shot 2019-12-14 at 22 21 41

what am I doing wrong?
Thanks.

Jaeger::Thrift::Log::FIELDS is duplicating

when I tried to inject/extract, I got a problem as follow.

/trace-test/vendor/bundle/ruby/2.4.0/gems/jaeger-client-0.4.0/thrift/gen-rb/jaeger/thrift/jaeger_types.rb:66: warning: already initialized constant Jaeger::Thrift::Log::FIELDS
/trace-test/vendor/bundle/ruby/2.4.0/gems/jaeger-client-0.4.0/thrift/gen-rb/jaeger/thrift/jaeger_types.rb:64: warning: previous definition of FIELDS was here

I guess this warnings shows to duplicate FIELDS of variable name.

https://github.com/salemove/jaeger-client-ruby/blob/master/thrift/gen-rb/jaeger/thrift/jaeger_types.rb#L64-L66

 61     class Log
 62       include ::Thrift::Struct, ::Thrift::Struct_Union
 63       TIMESTAMP = 1
 64       FIELDS = 2
 65
 66       FIELDS = {
 67         TIMESTAMP => {:type => ::Thrift::Types::I64, :name => 'timestamp'},
 68         FIELDS => {:type => ::Thrift::Types::LIST, :name => 'fields', :element => {:type => ::Thrift::Types::STRUCT, :class => ::Jaeger::Thrift::Tag}}
 69       }

jaeger agent processor faillure

Hi,

I'm implementing the jaeger client + opentracing in my app.
With the following code:

require 'jaeger/client'

OpenTracing.global_tracer = Jaeger::Client.build(
  service_name: ENV.fetch("JAEGER_SERVICE_NAME", Rails.application.class.parent_name),
  host: ENV.fetch("JAEGER_HOST", "jaeger"),
  port: 6831,
  tags: {env: ENV.fetch("JAEGER_ENV", "local"), cluster: ENV.fetch("JAEGER_CLUSTER", "local")},
  injectors: {
      OpenTracing::FORMAT_RACK => [Jaeger::Injectors::TraceContextRackCodec]
  },
  extractors: {
      OpenTracing::FORMAT_RACK => [Jaeger::Extractors::TraceContextRackCodec]
  })

require 'rack/tracer'
Rails.application.middleware.use Rack::Tracer

require 'active_record/opentracing'
ActiveRecord::OpenTracing.instrument

require 'redis/instrumentation'
Redis::Instrumentation.instrument

But with that I have some errors on the jaeger agent side:

{
   "level":"error",
   "ts":1580920392.2683513,
   "caller":"processors/thrift_processor.go:119",
   "msg":"Processor failed",
   "error":"*jaeger.Batch error reading struct: *jaeger.Span error reading struct: *jaeger.Tag error reading struct: error reading field 3: Invalid data length",
   "stacktrace":"github.com/jaegertracing/jaeger/cmd/agent/app/processors.(*ThriftProcessor).processBuffer\n\t/home/travis/gopath/src/github.com/jaegertracing/jaeger/cmd/agent/app/processors/thrift_processor.go:119\ngithub.com/jaegertracing/jaeger/cmd/agent/app/processors.NewThriftProcessor.func2\n\t/home/travis/gopath/src/github.com/jaegertracing/jaeger/cmd/agent/app/processors/thrift_processor.go:83"
}

The issue is not on all my traces.

Also I'm not sure there is a relation but I can find some traces with the trace-without-root-span, inside the span I have some warning: invalid parent span IDs=a6184ebb3cbe6de6; skipping clock skew adjustment

Do you have an idea why I have this kind of errors ?

how to generate a custom span

I'd like to generate a span like following

{
                    "traceID": "aecb1062c1832918",
                    "spanID": "aecb1062c1832918",
                    "flags": 1,
                    "operationName": "/",
                    "references": [],
                    "startTime": 1608616011590916,
                    "duration": 78,
                    "tags": [
                        {
                            "key": "sampler.type",
                            "type": "string",
                            "value": "const"
                        },
                        {
                            "key": "sampler.param",
                            "type": "int64",
                            "value": 1
                        },
                        {
                            "key": "http.method",
                            "type": "string",
                            "value": "GET"
                        },
                        {
                            "key": "http.status_code",
                            "type": "int64",
                            "value": 200
                        },
                        {
                            "key": "tenant.id",
                            "type": "string",
                            "value": "id-mycluster-account"
                        },
                        {
                            "key": "internal.span.format",
                            "type": "string",
                            "value": "jaeger"
                        }
                    ],
                    "container": "quickstart.svc.cluster.local",
                    "message_bus_destination": "SYSTEM.REST.REPLY.QUEUE",
                    "sourceNamespace": "cp4i",
                    "logs": [],
                    "processID": "p1",
                    "warnings": null
                }

From the above span, we can see there are three customized attribute "container": "quickstart.svc.cluster.local", "message_bus_destination": "SYSTEM.REST.REPLY.QUEUE", "sourceNamespace": "cp4i",

How should I do to add these attributes correctly.
I tried to use following code, but the attribute container was not been included in span

OpenTracing.start_active_span("/") do |scope|
    # set the method and status code tags
    scope.span.set_tag("http.method", "GET")
    scope.span.set_tag("http.status_code", 200)
    # set the span kind to "server" since this handles an incoming request
    scope.span.set_tag("span.kind", "server")
    scope.span.set_baggage_item("container","quickstart.svc.cluster.local")
  end

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.