opentelemetry-api 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +9 -0
- data/OVERVIEW.md +66 -0
- data/lib/{opentelemetry/distributed_context/manager.rb → opentelemetry-api.rb} +1 -6
- data/lib/opentelemetry.rb +34 -16
- data/lib/opentelemetry/context.rb +138 -15
- data/lib/opentelemetry/context/key.rb +29 -0
- data/lib/opentelemetry/context/propagation.rb +22 -0
- data/lib/opentelemetry/context/propagation/composite_propagator.rb +77 -0
- data/lib/opentelemetry/context/propagation/default_getter.rb +26 -0
- data/lib/opentelemetry/context/propagation/default_setter.rb +26 -0
- data/lib/opentelemetry/context/propagation/noop_extractor.rb +26 -0
- data/lib/opentelemetry/context/propagation/noop_injector.rb +26 -0
- data/lib/opentelemetry/context/propagation/propagation.rb +27 -0
- data/lib/opentelemetry/context/propagation/propagator.rb +64 -0
- data/lib/opentelemetry/correlation_context.rb +16 -0
- data/lib/opentelemetry/correlation_context/builder.rb +18 -0
- data/lib/opentelemetry/correlation_context/manager.rb +36 -0
- data/lib/opentelemetry/correlation_context/propagation.rb +57 -0
- data/lib/opentelemetry/correlation_context/propagation/context_keys.rb +27 -0
- data/lib/opentelemetry/correlation_context/propagation/text_extractor.rb +60 -0
- data/lib/opentelemetry/correlation_context/propagation/text_injector.rb +55 -0
- data/lib/opentelemetry/instrumentation.rb +15 -0
- data/lib/opentelemetry/instrumentation/adapter.rb +244 -0
- data/lib/opentelemetry/instrumentation/registry.rb +87 -0
- data/lib/opentelemetry/metrics.rb +1 -1
- data/lib/opentelemetry/metrics/handles.rb +5 -15
- data/lib/opentelemetry/metrics/instruments.rb +18 -69
- data/lib/opentelemetry/metrics/meter.rb +2 -39
- data/lib/opentelemetry/metrics/{meter_factory.rb → meter_provider.rb} +2 -2
- data/lib/opentelemetry/trace.rb +2 -2
- data/lib/opentelemetry/trace/event.rb +4 -3
- data/lib/opentelemetry/trace/link.rb +4 -3
- data/lib/opentelemetry/trace/propagation.rb +17 -0
- data/lib/opentelemetry/trace/propagation/context_keys.rb +35 -0
- data/lib/opentelemetry/trace/propagation/trace_context.rb +59 -0
- data/lib/opentelemetry/trace/propagation/trace_context/text_extractor.rb +58 -0
- data/lib/opentelemetry/trace/propagation/trace_context/text_injector.rb +55 -0
- data/lib/opentelemetry/trace/propagation/trace_context/trace_parent.rb +126 -0
- data/lib/opentelemetry/trace/span.rb +14 -6
- data/lib/opentelemetry/trace/status.rb +7 -2
- data/lib/opentelemetry/trace/tracer.rb +47 -13
- data/lib/opentelemetry/trace/tracer_provider.rb +22 -0
- data/lib/opentelemetry/trace/util/http_to_status.rb +47 -0
- data/lib/opentelemetry/version.rb +1 -1
- metadata +33 -13
- data/lib/opentelemetry/distributed_context.rb +0 -19
- data/lib/opentelemetry/distributed_context/distributed_context.rb +0 -24
- data/lib/opentelemetry/distributed_context/entry.rb +0 -66
- data/lib/opentelemetry/distributed_context/propagation.rb +0 -19
- data/lib/opentelemetry/distributed_context/propagation/binary_format.rb +0 -26
- data/lib/opentelemetry/distributed_context/propagation/text_format.rb +0 -76
- data/lib/opentelemetry/distributed_context/propagation/trace_parent.rb +0 -124
- data/lib/opentelemetry/trace/sampling_hint.rb +0 -22
- data/lib/opentelemetry/trace/tracer_factory.rb +0 -45
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module OpenTelemetry
|
8
|
+
class Context
|
9
|
+
module Propagation
|
10
|
+
# The default getter module provides a common method for reading
|
11
|
+
# a key from a carrier that implements +[]+
|
12
|
+
module DefaultGetter
|
13
|
+
DEFAULT_GETTER = ->(carrier, key) { carrier[key] }
|
14
|
+
private_constant :DEFAULT_GETTER
|
15
|
+
|
16
|
+
# Returns a callable that can read a key from a carrier that implements
|
17
|
+
# +[]+. Useful for extract operations.
|
18
|
+
#
|
19
|
+
# @return [Callable]
|
20
|
+
def default_getter
|
21
|
+
DEFAULT_GETTER
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module OpenTelemetry
|
8
|
+
class Context
|
9
|
+
module Propagation
|
10
|
+
# The default setter module provides a common method for writing
|
11
|
+
# a key into a carrier that implements +[]=+
|
12
|
+
module DefaultSetter
|
13
|
+
DEFAULT_SETTER = ->(carrier, key, value) { carrier[key] = value }
|
14
|
+
private_constant :DEFAULT_SETTER
|
15
|
+
|
16
|
+
# Returns a callable that can write a key into a carrier that implements
|
17
|
+
# +[]=+. Useful for inject operations.
|
18
|
+
#
|
19
|
+
# @return [Callable]
|
20
|
+
def default_setter
|
21
|
+
DEFAULT_SETTER
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2020 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module OpenTelemetry
|
8
|
+
class Context
|
9
|
+
module Propagation
|
10
|
+
# A no-op extractor implementation
|
11
|
+
class NoopExtractor
|
12
|
+
# Extract a context from the given carrier
|
13
|
+
#
|
14
|
+
# @param [Object] carrier The carrier to extract the context from
|
15
|
+
# @param [Context] context The context to be upated with the extracted
|
16
|
+
# context
|
17
|
+
# @param [optional Callable] getter An optional callable that takes a carrier and a key and
|
18
|
+
# and returns the value associated with the key
|
19
|
+
# @return [Context]
|
20
|
+
def extract(carrier, context, &getter)
|
21
|
+
context
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2020 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module OpenTelemetry
|
8
|
+
class Context
|
9
|
+
module Propagation
|
10
|
+
# A no-op injector implementation
|
11
|
+
class NoopInjector
|
12
|
+
# Inject the given context into the specified carrier
|
13
|
+
#
|
14
|
+
# @param [Object] carrier The carrier to inject the provided context
|
15
|
+
# into
|
16
|
+
# @param [Context] context The context to be injected
|
17
|
+
# @param [optional Callable] setter An optional callable that takes a carrier and a key and
|
18
|
+
# a value and assigns the key-value pair in the carrier
|
19
|
+
# @return [Object] carrier
|
20
|
+
def inject(carrier, context, &setter)
|
21
|
+
carrier
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module OpenTelemetry
|
8
|
+
class Context
|
9
|
+
module Propagation
|
10
|
+
# The Propagation class provides methods to inject and extract context
|
11
|
+
# to pass across process boundaries
|
12
|
+
class Propagation
|
13
|
+
# Get or set the global http propagator. Use a CompositePropagator
|
14
|
+
# to propagate multiple formats.
|
15
|
+
attr_accessor :http
|
16
|
+
|
17
|
+
# Get or set the global text propagator. Use a CompositePropagator
|
18
|
+
# to propagate multiple formats.
|
19
|
+
attr_accessor :text
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@http = @text = Propagator.new(NoopInjector.new, NoopExtractor.new)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2020 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module OpenTelemetry
|
8
|
+
class Context
|
9
|
+
module Propagation
|
10
|
+
# A propagator composes an extractor and injector into a single interface
|
11
|
+
# exposing inject and extract methods
|
12
|
+
class Propagator
|
13
|
+
# Returns a Propagator that delegates inject and extract to the provided
|
14
|
+
# injector and extractor
|
15
|
+
#
|
16
|
+
# @param [#inject] injector
|
17
|
+
# @param [#extract] extractor
|
18
|
+
def initialize(injector, extractor)
|
19
|
+
@injector = injector
|
20
|
+
@extractor = extractor
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns a carrier with the provided context injected according the
|
24
|
+
# underlying injector. Returns the carrier and logs a warning if
|
25
|
+
# injection fails.
|
26
|
+
#
|
27
|
+
# @param [Object] carrier A carrier to inject context into
|
28
|
+
# context into
|
29
|
+
# @param [optional Context] context Context to be injected into carrier. Defaults
|
30
|
+
# to +Context.current+
|
31
|
+
# @param [optional Callable] setter An optional callable that takes a carrier, a key and
|
32
|
+
# a value and assigns the key-value pair in the carrier. If omitted the default setter
|
33
|
+
# will be used which expects the carrier to respond to [] and []=.
|
34
|
+
#
|
35
|
+
# @return [Object] carrier
|
36
|
+
def inject(carrier, context = Context.current, &setter)
|
37
|
+
@injector.inject(carrier, context, &setter)
|
38
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
39
|
+
OpenTelemetry.logger.warn "Error in Propagator#inject #{e.message}"
|
40
|
+
carrier
|
41
|
+
end
|
42
|
+
|
43
|
+
# Extracts and returns context from a carrier. Returns the provided
|
44
|
+
# context and logs a warning if an error if extraction fails.
|
45
|
+
#
|
46
|
+
# @param [Object] carrier The carrier to extract context from
|
47
|
+
# @param [optional Context] context Context to be updated with the state
|
48
|
+
# extracted from the carrier. Defaults to +Context.current+
|
49
|
+
# @param [optional Callable] getter An optional callable that takes a carrier and a key and
|
50
|
+
# returns the value associated with the key. If omitted the default getter will be used
|
51
|
+
# which expects the carrier to respond to [] and []=.
|
52
|
+
#
|
53
|
+
# @return [Context] a new context updated with state extracted from the
|
54
|
+
# carrier
|
55
|
+
def extract(carrier, context = Context.current, &getter)
|
56
|
+
@extractor.extract(carrier, context, &getter)
|
57
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
58
|
+
OpenTelemetry.logger.warn "Error in Propagator#extract #{e.message}"
|
59
|
+
context
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
require 'opentelemetry/correlation_context/builder'
|
8
|
+
require 'opentelemetry/correlation_context/manager'
|
9
|
+
require 'opentelemetry/correlation_context/propagation'
|
10
|
+
|
11
|
+
module OpenTelemetry
|
12
|
+
# The CorrelationContext module provides functionality to record and propagate
|
13
|
+
# correlations in a distributed trace
|
14
|
+
module CorrelationContext
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module OpenTelemetry
|
8
|
+
module CorrelationContext
|
9
|
+
# No op implementation of CorrelationContext::Builder
|
10
|
+
class Builder
|
11
|
+
def set_value(key, value); end
|
12
|
+
|
13
|
+
def remove_value(key); end
|
14
|
+
|
15
|
+
def clear; end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module OpenTelemetry
|
8
|
+
module CorrelationContext
|
9
|
+
# No op implementation of CorrelationContext::Manager
|
10
|
+
class Manager
|
11
|
+
NOOP_BUILDER = Builder.new
|
12
|
+
private_constant :NOOP_BUILDER
|
13
|
+
|
14
|
+
def build(context: Context.current)
|
15
|
+
yield NOOP_BUILDER
|
16
|
+
context
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_value(key, value, context: Context.current)
|
20
|
+
context
|
21
|
+
end
|
22
|
+
|
23
|
+
def value(key, context: Context.current)
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def remove_value(key, context: Context.current)
|
28
|
+
context
|
29
|
+
end
|
30
|
+
|
31
|
+
def clear(context: Context.current)
|
32
|
+
context
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
require 'opentelemetry/correlation_context/propagation/context_keys'
|
8
|
+
require 'opentelemetry/correlation_context/propagation/text_injector'
|
9
|
+
require 'opentelemetry/correlation_context/propagation/text_extractor'
|
10
|
+
|
11
|
+
module OpenTelemetry
|
12
|
+
module CorrelationContext
|
13
|
+
# The Correlation::Propagation module contains injectors and
|
14
|
+
# extractors for sending and receiving correlation context over the wire
|
15
|
+
module Propagation
|
16
|
+
extend self
|
17
|
+
|
18
|
+
TEXT_EXTRACTOR = TextExtractor.new
|
19
|
+
TEXT_INJECTOR = TextInjector.new
|
20
|
+
RACK_EXTRACTOR = TextExtractor.new(
|
21
|
+
correlation_context_key: 'HTTP_CORRELATION_CONTEXT'
|
22
|
+
)
|
23
|
+
RACK_INJECTOR = TextInjector.new(
|
24
|
+
correlation_context_key: 'HTTP_CORRELATION_CONTEXT'
|
25
|
+
)
|
26
|
+
|
27
|
+
private_constant :TEXT_INJECTOR, :TEXT_EXTRACTOR, :RACK_INJECTOR,
|
28
|
+
:RACK_EXTRACTOR
|
29
|
+
|
30
|
+
# Returns an extractor that extracts context using the W3C Correlation
|
31
|
+
# Context format
|
32
|
+
def text_injector
|
33
|
+
TEXT_INJECTOR
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns an injector that injects context using the W3C Correlation
|
37
|
+
# Context format
|
38
|
+
def text_extractor
|
39
|
+
TEXT_EXTRACTOR
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns an extractor that extracts context using the W3C Correlation
|
43
|
+
# Context format with Rack normalized keys (upcased and prefixed with
|
44
|
+
# HTTP_)
|
45
|
+
def rack_injector
|
46
|
+
RACK_INJECTOR
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns an injector that injects context using the W3C Correlation
|
50
|
+
# Context format with Rack normalized keys (upcased and prefixed with
|
51
|
+
# HTTP_)
|
52
|
+
def rack_extractor
|
53
|
+
RACK_EXTRACTOR
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module OpenTelemetry
|
8
|
+
module CorrelationContext
|
9
|
+
module Propagation
|
10
|
+
# The ContextKeys module contains the keys used to index correlations
|
11
|
+
# in a {Context} instance
|
12
|
+
module ContextKeys
|
13
|
+
extend self
|
14
|
+
|
15
|
+
CORRELATION_CONTEXT_KEY = Context.create_key('correlation-context')
|
16
|
+
private_constant :CORRELATION_CONTEXT_KEY
|
17
|
+
|
18
|
+
# Returns the context key that correlations are indexed by
|
19
|
+
#
|
20
|
+
# @return [Context::Key]
|
21
|
+
def correlation_context_key
|
22
|
+
CORRELATION_CONTEXT_KEY
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
require 'cgi'
|
8
|
+
|
9
|
+
module OpenTelemetry
|
10
|
+
module CorrelationContext
|
11
|
+
module Propagation
|
12
|
+
# Extracts correlations from carriers in the W3C Correlation Context format
|
13
|
+
class TextExtractor
|
14
|
+
include Context::Propagation::DefaultGetter
|
15
|
+
|
16
|
+
# Returns a new TextExtractor that extracts context using the specified
|
17
|
+
# header key
|
18
|
+
#
|
19
|
+
# @param [String] correlation_context_key The correlation context header
|
20
|
+
# key used in the carrier
|
21
|
+
# @return [TextExtractor]
|
22
|
+
def initialize(correlation_context_key: 'Correlation-Context')
|
23
|
+
@correlation_context_key = correlation_context_key
|
24
|
+
end
|
25
|
+
|
26
|
+
# Extract remote correlations from the supplied carrier.
|
27
|
+
# If extraction fails, the original context will be returned
|
28
|
+
#
|
29
|
+
# @param [Carrier] carrier The carrier to get the header from
|
30
|
+
# @param [Context] context The context to be updated with extracted correlations
|
31
|
+
# @param [optional Callable] getter An optional callable that takes a carrier and a key and
|
32
|
+
# returns the value associated with the key. If omitted the default getter will be used
|
33
|
+
# which expects the carrier to respond to [] and []=.
|
34
|
+
# @yield [Carrier, String] if an optional getter is provided, extract will yield the carrier
|
35
|
+
# and the header key to the getter.
|
36
|
+
# @return [Context] context updated with extracted correlations, or the original context
|
37
|
+
# if extraction fails
|
38
|
+
def extract(carrier, context, &getter)
|
39
|
+
getter ||= default_getter
|
40
|
+
header = getter.call(carrier, @correlation_context_key)
|
41
|
+
|
42
|
+
entries = header.gsub(/\s/, '').split(',')
|
43
|
+
|
44
|
+
correlations = entries.each_with_object({}) do |entry, memo|
|
45
|
+
# The ignored variable below holds properties as per the W3C spec.
|
46
|
+
# OTel is not using them currently, but they might be used for
|
47
|
+
# metadata in the future
|
48
|
+
kv, = entry.split(';', 2)
|
49
|
+
k, v = kv.split('=').map!(&CGI.method(:unescape))
|
50
|
+
memo[k] = v
|
51
|
+
end
|
52
|
+
|
53
|
+
context.set_value(ContextKeys.correlation_context_key, correlations)
|
54
|
+
rescue StandardError
|
55
|
+
context
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
require 'cgi'
|
8
|
+
|
9
|
+
module OpenTelemetry
|
10
|
+
module CorrelationContext
|
11
|
+
module Propagation
|
12
|
+
# Injects correlation context using the W3C Correlation Context format
|
13
|
+
class TextInjector
|
14
|
+
include Context::Propagation::DefaultSetter
|
15
|
+
|
16
|
+
# Returns a new TextInjector that injects context using the specified
|
17
|
+
# header key
|
18
|
+
#
|
19
|
+
# @param [String] correlation_context_header_key The correlation context header
|
20
|
+
# key used in the carrier
|
21
|
+
# @return [TextInjector]
|
22
|
+
def initialize(correlation_context_key: 'Correlation-Context')
|
23
|
+
@correlation_context_key = correlation_context_key
|
24
|
+
end
|
25
|
+
|
26
|
+
# Inject in-process correlations into the supplied carrier.
|
27
|
+
#
|
28
|
+
# @param [Carrier] carrier The carrier to inject correlations into
|
29
|
+
# @param [Context] context The context to read correlations from
|
30
|
+
# @param [optional Callable] getter An optional callable that takes a carrier and a key and
|
31
|
+
# returns the value associated with the key. If omitted the default getter will be used
|
32
|
+
# which expects the carrier to respond to [] and []=.
|
33
|
+
# @yield [Carrier, String] if an optional getter is provided, inject will yield the carrier
|
34
|
+
# and the header key to the getter.
|
35
|
+
# @return [Object] carrier with injected correlations
|
36
|
+
def inject(carrier, context, &setter)
|
37
|
+
return carrier unless (correlations = context[ContextKeys.correlation_context_key]) && !correlations.empty?
|
38
|
+
|
39
|
+
setter ||= default_setter
|
40
|
+
setter.call(carrier, @correlation_context_key, encode(correlations))
|
41
|
+
|
42
|
+
carrier
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def encode(correlations)
|
48
|
+
correlations.inject(+'') do |memo, (k, v)|
|
49
|
+
memo << CGI.escape(k.to_s) << '=' << CGI.escape(v.to_s) << ','
|
50
|
+
end.chop!
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|