Skip to content
This repository was archived by the owner on Apr 8, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ end
```

And add the middleware in `Rack::Builder`:

``` ruby
Rack::Builder.app do
use OpenTelemetry::Instrumentation::Rack::Middlewares::TracerMiddleware
Expand All @@ -227,6 +227,14 @@ To disable the response headers being added the environment variable
`SPLUNK_TRACE_RESPONSE_HEADER_ENABLED` can be set to `false`, or pass
`trace_response_header_enabled: false` to `Splunk::Otel.configure`.

## Configure for use with Smart Agent

This distribution includes the `jaeger-thrift-splunk` exporter, which is preconfigured to send data to local instance of the [SignalFx Smart Agent](https://github.com/signalfx/signalfx-agent).

To use the `jaeger-thrift-splunk` exporter, set the`OTEL_TRACES_EXPORTER` environment variable to `jaeger-thrift-splunk`, or append the exporter to the existing values. For example, `OTEL_TRACES_EXPORTER=otlp,jaeger-thrift-splunk`.

If the `SPLUNK_REALM` or the `OTEL_EXPORTER_JAEGER_ENDPOINT` environmental variables are set, the default endpoint is overwritten.

## Troubleshooting

For troubleshooting information, see the [Troubleshooting](docs/troubleshooting.md) documentation.
Expand Down
1 change: 1 addition & 0 deletions examples/smart-agent/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Gemfile.lock
6 changes: 6 additions & 0 deletions examples/smart-agent/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

source "https://rubygems.org"

gem "opentelemetry-exporter-jaeger"
gem "splunk-otel", path: "../../"
8 changes: 8 additions & 0 deletions examples/smart-agent/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: "3"
services:
otel:
image: quay.io/signalfx/signalfx-agent:5
ports:
- 9080:9080
volumes:
- ./smart-agent-config.yaml:/etc/signalfx/agent.yaml
22 changes: 22 additions & 0 deletions examples/smart-agent/runner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require "rubygems"
require "bundler/setup"
Bundler.require(:default)

Splunk::Otel.configure do |configurator|
$configurator = configurator # rubocop:disable Style/GlobalVars

class << configurator
def test_shutdown
@span_processors.each(&:shutdown)
end
end
end

tracer = OpenTelemetry.tracer_provider.tracer("test", "1.0")
tracer.in_span("test-span") do
puts "test-span execution"
end

$configurator.test_shutdown # rubocop:disable Style/GlobalVars
5 changes: 5 additions & 0 deletions examples/smart-agent/smart-agent-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
signalFxAccessToken: ""
ingestUrl: "https://ingest.lab0.signalfx.com"
signalFxRealm: "lab0"
monitors:
- type: trace-forwarder
36 changes: 22 additions & 14 deletions lib/splunk/otel.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

require_relative "otel/version"
require "opentelemetry/sdk"

# FIXME: without this, otlp doesn't work out-of-the-box
require "opentelemetry-exporter-otlp"

require_relative "otel/version"
require_relative "otel/proprietary_exporters"

module Splunk
# main module for application startup configuration
module Otel
module Otel # rubocop:disable Metrics/ModuleLength
# custom exception types in this gem must inherit from Splunk::Otel::Error
# this allows the user to rescue a generic exception type to catch all exceptions
class Error < StandardError; end
Expand Down Expand Up @@ -57,20 +57,21 @@ def configure(service_name: ENV.fetch("OTEL_SERVICE_NAME", "unnamed-ruby-service
trace_response_header_enabled: ENV.fetch("SPLUNK_TRACE_RESPONSE_HEADER_ENABLED", "true"))
@trace_response_header_enabled = to_boolean(trace_response_header_enabled)

set_default_propagators
set_access_token_header
set_default_exporter
set_default_span_limits
set_defaults

# run SDK's setup function
OpenTelemetry::SDK.configure do |c|
c.service_name = service_name
c.resource = OpenTelemetry::SDK::Resources::Resource.create(
OpenTelemetry::SDK.configure do |configurator|
class << configurator
include Splunk::Otel::ExporterExtensions
end

configurator.service_name = service_name
configurator.resource = OpenTelemetry::SDK::Resources::Resource.create(
"splunk.distro.version" => Splunk::Otel::VERSION
)

c.use_all if auto_instrument
yield c if block_given?
configurator.use_all if auto_instrument
yield configurator if block_given?
end

# set span limits to GDI defaults if not set by the user
Expand All @@ -79,6 +80,13 @@ def configure(service_name: ENV.fetch("OTEL_SERVICE_NAME", "unnamed-ruby-service
verify_service_name
end

def set_defaults
set_default_propagators
set_access_token_header
set_default_exporter
set_default_span_limits
end

# verify `service.name` is set and print a warning if it is still the default
def verify_service_name
provider_resource = OpenTelemetry.tracer_provider.instance_variable_get(:@resource)
Expand Down Expand Up @@ -183,7 +191,7 @@ def service_name_warning
module_function :configure, :gdi_span_limits, :set_default_propagators, :set_default_exporter,
:verify_service_name, :service_name_warning, :default_env_vars,
:set_default_span_limits, :set_access_token_header, :set_endpoint,
:to_boolean, :trace_response_header_enabled
:to_boolean, :trace_response_header_enabled, :set_defaults
end
end

Expand Down
54 changes: 54 additions & 0 deletions lib/splunk/otel/proprietary_exporters.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# frozen_string_literal: true

module Splunk
module Otel
OUR_EXPORTERS_KEYS = ["jaeger-thrift-splunk"].freeze
private_constant :OUR_EXPORTERS_KEYS

# internal module for allowing our exporters to be set via ENV
module ExporterExtensions
def effective_splunk_jaeger_endpoint
return "https://ingest.#{ENV["SPLUNK_REALM"]}.signalfx.com/v1/trace" if ENV["SPLUNK_REALM"]
return ENV["OTEL_EXPORTER_JAEGER_ENDPOINT"] if ENV["OTEL_EXPORTER_JAEGER_ENDPOINT"]

"http://127.0.0.1:9080/v1/trace"
end

def wrapped_exporters_from_env
original_env_value = ENV.fetch("OTEL_TRACES_EXPORTER", "otlp")
exporters_keys = original_env_value.split(",").map(&:strip)
non_proprietary_exporters_keys = exporters_keys - OUR_EXPORTERS_KEYS

ENV["OTEL_TRACES_EXPORTER"] = non_proprietary_exporters_keys.join(",")
original_exporters = super
ENV["OTEL_TRACES_EXPORTER"] = original_env_value

original_exporters + proprietary_exporters(exporters_keys)
end

def proprietary_exporters(exporters_keys)
(exporters_keys & OUR_EXPORTERS_KEYS).map do |exporter_key|
case exporter_key
when "jaeger-thrift-splunk"
args = {
endpoint: effective_splunk_jaeger_endpoint
}
fetch_exporter_with_args("jaeger-thrift-splunk", "OpenTelemetry::Exporter::Jaeger::CollectorExporter",
**args)
end
end.compact
end

def fetch_exporter_with_args(name, class_name, **args)
# TODO: warn if jaeger exporter gem is not present
exporter = Kernel.const_get(class_name).new(**args)
OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new exporter
rescue NameError
OpenTelemetry.logger.warn "The #{name} exporter cannot be configured" \
"- please add opentelemetry-exporter-#{name} to your Gemfile" \
", spans will not be exported.."
nil
end
end
end
end
25 changes: 25 additions & 0 deletions test/splunk/otel/proprietary_exporters_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

require "test_helper"
require "opentelemetry/sdk"
require "opentelemetry-exporter-jaeger"

module Splunk
class OtelProprietaryExportersTest < Test::Unit::TestCase
def setup
with_env("OTEL_TRACES_EXPORTER" => "jaeger-thrift-splunk") do
Splunk::Otel.configure
end
end

def teardown
OpenTelemetry.tracer_provider.shutdown
end

test "check that jaeger exporter is present" do
processors = OpenTelemetry.tracer_provider.instance_variable_get("@span_processors")
exporter = processors[0].instance_variable_get("@exporter")
assert_instance_of OpenTelemetry::Exporter::Jaeger::CollectorExporter, exporter
end
end
end
3 changes: 1 addition & 2 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
require "simplecov-cobertura"
SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter

$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
require "splunk/otel"
require_relative "../lib/splunk/otel"

require "test-unit"

Expand Down