opentelemetry-api 0.16.0 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -0
  3. data/README.md +3 -3
  4. data/lib/opentelemetry.rb +21 -28
  5. data/lib/opentelemetry/baggage.rb +95 -2
  6. data/lib/opentelemetry/baggage/builder.rb +30 -4
  7. data/lib/opentelemetry/baggage/entry.rb +20 -0
  8. data/lib/opentelemetry/baggage/propagation.rb +9 -18
  9. data/lib/opentelemetry/baggage/propagation/text_map_propagator.rb +111 -0
  10. data/lib/opentelemetry/context.rb +48 -33
  11. data/lib/opentelemetry/context/propagation.rb +35 -5
  12. data/lib/opentelemetry/context/propagation/composite_text_map_propagator.rb +105 -0
  13. data/lib/opentelemetry/context/propagation/noop_text_map_propagator.rb +27 -0
  14. data/lib/opentelemetry/context/propagation/{propagator.rb → text_map_propagator.rb} +23 -16
  15. data/lib/opentelemetry/internal.rb +17 -0
  16. data/lib/opentelemetry/internal/proxy_tracer.rb +38 -0
  17. data/lib/opentelemetry/internal/proxy_tracer_provider.rb +59 -0
  18. data/lib/opentelemetry/trace.rb +10 -0
  19. data/lib/opentelemetry/trace/propagation/trace_context.rb +7 -18
  20. data/lib/opentelemetry/trace/propagation/trace_context/text_map_propagator.rb +73 -0
  21. data/lib/opentelemetry/trace/status.rb +34 -5
  22. data/lib/opentelemetry/trace/tracer.rb +8 -9
  23. data/lib/opentelemetry/version.rb +1 -1
  24. metadata +16 -25
  25. data/lib/opentelemetry/baggage/manager.rb +0 -41
  26. data/lib/opentelemetry/baggage/propagation/text_map_extractor.rb +0 -57
  27. data/lib/opentelemetry/baggage/propagation/text_map_injector.rb +0 -52
  28. data/lib/opentelemetry/context/propagation/composite_propagator.rb +0 -72
  29. data/lib/opentelemetry/context/propagation/noop_extractor.rb +0 -26
  30. data/lib/opentelemetry/context/propagation/noop_injector.rb +0 -26
  31. data/lib/opentelemetry/instrumentation.rb +0 -15
  32. data/lib/opentelemetry/instrumentation/base.rb +0 -307
  33. data/lib/opentelemetry/instrumentation/registry.rb +0 -86
  34. data/lib/opentelemetry/metrics.rb +0 -16
  35. data/lib/opentelemetry/metrics/handles.rb +0 -44
  36. data/lib/opentelemetry/metrics/instruments.rb +0 -105
  37. data/lib/opentelemetry/metrics/meter.rb +0 -72
  38. data/lib/opentelemetry/metrics/meter_provider.rb +0 -22
  39. data/lib/opentelemetry/trace/propagation/trace_context/text_map_extractor.rb +0 -52
  40. data/lib/opentelemetry/trace/propagation/trace_context/text_map_injector.rb +0 -49
  41. data/lib/opentelemetry/trace/util/http_to_status.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2044ecfc3776d70aa668bcbd537f9df904f3a48a19b3b1daa67d0632686b3358
4
- data.tar.gz: 996749298853bb15d62cadff700e06a1f3bcb505f5b49786b713c1daa1796165
3
+ metadata.gz: b873eaad4492b7cefaebdf1a9e5e9998f8af3192340d0d4eae0d2e7c32964e16
4
+ data.tar.gz: a7a4c5c20d299ac33d0cae853104ee8f33a2f8e4436888e5259a706b0061d6cb
5
5
  SHA512:
6
- metadata.gz: 12c9863e4b90e34f5b4d6e2e3e5b97244d609e5381d554b39d461e77cfff5e7f8130b1389c68743d6fb7ea3080321aa4b12dc56e3ca78cac20fda1cc0100e7b7
7
- data.tar.gz: 990f49fa7ef5e2990283cf4b42af9a6ecaa4989078a7b084568806675a9a2d3ae635bb830bccc9626b51869e3f0bfc9df5406f2cdbfda6c33576e4fd92c26716
6
+ metadata.gz: a9689040364ba9f92dbd9b4af6a95c5d9e0adbffb805ed79f3d0e4a7e2061fd6ac0d5dec6ec50ef5e4fe290dfd74c3779a0331145b9ebee5fe83dc9551bdf58a
7
+ data.tar.gz: 0127d9a7168c4f275a132b63f038d0e4f58105d72475e70ab2db03f3a868dc85d2252e5c50bf5b52af713b0018c33a4d8366a872ba4d1522304e2d8f5e8d5360
data/CHANGELOG.md CHANGED
@@ -1,5 +1,62 @@
1
1
  # Release History: opentelemetry-api
2
2
 
3
+ ### v1.0.0.rc3 / 2021-08-12
4
+
5
+ * BREAKING CHANGE: Remove optional parent_context from in_span
6
+ * BREAKING CHANGE: Refactor Baggage to remove Noop*
7
+ * BREAKING CHANGE: Total order constraint on span.status=
8
+
9
+ * ADDED: Add Tracer.non_recording_span to API
10
+ * ADDED: Make API's NoopTextMapPropagator private
11
+ * FIXED: Remove optional parent_context from in_span
12
+ * FIXED: Reduce span allocation in API
13
+ * FIXED: Refactor Baggage to remove Noop*
14
+ * FIXED: Total order constraint on span.status=
15
+ * FIXED: Return early if carrier is nil
16
+ * FIXED: Update context to match spec
17
+ * FIXED: Return the original context if the baggage header value is empty
18
+ * DOCS: Update docs to rely more on environment variable configuration
19
+
20
+ ### v1.0.0.rc2 / 2021-06-23
21
+
22
+ * BREAKING CHANGE: Remove optional parent_context from in_span [729](https://github.com/open-telemetry/opentelemetry-ruby/pull/729)
23
+ * BREAKING CHANGE: Refactor Baggage to remove Noop* [800](https://github.com/open-telemetry/opentelemetry-ruby/pull/800)
24
+ - The noop baggage manger has been removed.
25
+ - The baggage management methods are now available through OpenTelemetry::Baggage#method, previously OpenTelemetry.baggage#method
26
+ * BREAKING CHANGE: Total order constraint on span.status= [805](https://github.com/open-telemetry/opentelemetry-ruby/pull/805)
27
+ - The OpenTelemetry::Trace::Util::HttpToStatus module has been removed as it was incorrectly setting the span status to OK for codes codes in the range 100..399
28
+ - The HttpToStatus module can be replaced inline as follows `span.status = OpenTelemetry::Trace::Status.error unless (100..399).include?(response_code.to_i)`
29
+ - The `Status.new(code, description:)` initializer has been hidden in favour of simpler constructors for each status code: `Status.ok`, `Status.error` and `Status.unset`. Each constructor takes an optional description.
30
+
31
+ * ADDED: Add Tracer.non_recording_span to API [799](https://github.com/open-telemetry/opentelemetry-ruby/pull/799)
32
+ * FIXED: Reduce span allocation in API [795](https://github.com/open-telemetry/opentelemetry-ruby/pull/795)
33
+ * FIXED: Return early if carrier is nil [835](https://github.com/open-telemetry/opentelemetry-ruby/pull/835)
34
+ * FIXED: Update context to match spec [807](https://github.com/open-telemetry/opentelemetry-ruby/pull/807)
35
+ - The `Context.current` setter has been removed and the previously private attach/detach methods are now available as class methods on the context module.
36
+
37
+ ### v1.0.0.rc1 / 2021-05-21
38
+
39
+ * BREAKING CHANGE: Remove optional parent_context from in_span
40
+
41
+ * FIXED: Remove optional parent_context from in_span
42
+
43
+ ### v0.17.0 / 2021-04-22
44
+
45
+ * BREAKING CHANGE: Replace TextMapInjector/TextMapExtractor pairs with a TextMapPropagator.
46
+
47
+ [Check the propagator documentation](https://open-telemetry.github.io/opentelemetry-ruby/) for the new usage.
48
+ * BREAKING CHANGE: Remove metrics API.
49
+
50
+ `OpenTelemetry::Metrics` and all of its behavior removed until spec stabilizes.
51
+ * BREAKING CHANGE: Extract instrumentation base from api (#698).
52
+
53
+ To take advantage of a base instrumentation class to create your own auto-instrumentation, require and use the `opentelemetry-instrumentation-base` gem.
54
+
55
+ * ADDED: Default noop tracer for instrumentation
56
+ * FIXED: Refactor propagators to add #fields
57
+ * FIXED: Remove metrics API
58
+ * FIXED: Dynamically upgrade global tracer provider
59
+
3
60
  ### v0.16.0 / 2021-03-17
4
61
 
5
62
  * ADDED: Span#add_attributes
data/README.md CHANGED
@@ -29,11 +29,11 @@ Then, use the OpenTelemetry interfaces to produces traces and other telemetry da
29
29
  ```ruby
30
30
  require 'opentelemetry'
31
31
 
32
- # Obtain the current default tracer factory
33
- factory = OpenTelemetry.tracer_factory
32
+ # Obtain the current default tracer provider
33
+ provider = OpenTelemetry.tracer_provider
34
34
 
35
35
  # Create a trace
36
- tracer = factory.tracer('my_app', '1.0')
36
+ tracer = provider.tracer('my_app', '1.0')
37
37
 
38
38
  # Record spans
39
39
  tracer.in_span('my_task') do |task_span|
data/lib/opentelemetry.rb CHANGED
@@ -9,9 +9,8 @@ require 'logger'
9
9
  require 'opentelemetry/error'
10
10
  require 'opentelemetry/context'
11
11
  require 'opentelemetry/baggage'
12
- require_relative './opentelemetry/instrumentation'
13
- require 'opentelemetry/metrics'
14
12
  require 'opentelemetry/trace'
13
+ require 'opentelemetry/internal'
15
14
  require 'opentelemetry/version'
16
15
 
17
16
  # OpenTelemetry is an open source observability framework, providing a
@@ -22,8 +21,10 @@ require 'opentelemetry/version'
22
21
  module OpenTelemetry
23
22
  extend self
24
23
 
25
- attr_writer :tracer_provider, :meter_provider, :propagation, :baggage,
26
- :logger, :error_handler
24
+ @mutex = Mutex.new
25
+ @tracer_provider = Internal::ProxyTracerProvider.new
26
+
27
+ attr_writer :propagation, :logger, :error_handler
27
28
 
28
29
  # @return [Object, Logger] configured Logger or a default STDOUT Logger.
29
30
  def logger
@@ -44,36 +45,28 @@ module OpenTelemetry
44
45
  error_handler.call(exception: exception, message: message)
45
46
  end
46
47
 
48
+ # Register the global tracer provider.
49
+ #
50
+ # @param [TracerProvider] provider A tracer provider to register as the
51
+ # global instance.
52
+ def tracer_provider=(provider)
53
+ @mutex.synchronize do
54
+ if @tracer_provider.instance_of? Internal::ProxyTracerProvider
55
+ logger.debug("Upgrading default proxy tracer provider to #{provider.class}")
56
+ @tracer_provider.delegate = provider
57
+ end
58
+ @tracer_provider = provider
59
+ end
60
+ end
61
+
47
62
  # @return [Object, Trace::TracerProvider] registered tracer provider or a
48
63
  # default no-op implementation of the tracer provider.
49
64
  def tracer_provider
50
- @tracer_provider ||= Trace::TracerProvider.new
51
- end
52
-
53
- # @return [Object, Metrics::MeterProvider] registered meter provider or a
54
- # default no-op implementation of the meter provider.
55
- def meter_provider
56
- @meter_provider ||= Metrics::MeterProvider.new
57
- end
58
-
59
- # @return [Instrumentation::Registry] registry containing all known
60
- # instrumentation
61
- def instrumentation_registry
62
- @instrumentation_registry ||= Instrumentation::Registry.new
63
- end
64
-
65
- # @return [Object, Baggage::Manager] registered
66
- # baggage manager or a default no-op implementation of the
67
- # manager.
68
- def baggage
69
- @baggage ||= Baggage::Manager.new
65
+ @mutex.synchronize { @tracer_provider }
70
66
  end
71
67
 
72
68
  # @return [Context::Propagation::Propagator] a propagator instance
73
69
  def propagation
74
- @propagation ||= Context::Propagation::Propagator.new(
75
- Context::Propagation::NoopInjector.new,
76
- Context::Propagation::NoopExtractor.new
77
- )
70
+ @propagation ||= Context::Propagation::NoopTextMapPropagator.new
78
71
  end
79
72
  end
@@ -4,13 +4,106 @@
4
4
  #
5
5
  # SPDX-License-Identifier: Apache-2.0
6
6
 
7
- require 'opentelemetry/baggage/builder'
8
- require 'opentelemetry/baggage/manager'
9
7
  require 'opentelemetry/baggage/propagation'
8
+ require 'opentelemetry/baggage/builder'
9
+ require 'opentelemetry/baggage/entry'
10
10
 
11
11
  module OpenTelemetry
12
12
  # The Baggage module provides functionality to record and propagate
13
13
  # baggage in a distributed trace
14
14
  module Baggage
15
+ extend self
16
+
17
+ BAGGAGE_KEY = OpenTelemetry::Baggage::Propagation::ContextKeys.baggage_key
18
+ EMPTY_BAGGAGE = {}.freeze
19
+ private_constant(:BAGGAGE_KEY, :EMPTY_BAGGAGE)
20
+
21
+ # Used to chain modifications to baggage. The result is a
22
+ # context with an updated baggage. If only a single
23
+ # modification is being made to baggage, use the other
24
+ # methods on +Baggage+, if multiple modifications are being made, use
25
+ # this one.
26
+ #
27
+ # @param [optional Context] context The context to update with with new
28
+ # modified baggage. Defaults to +Context.current+
29
+ # @return [Context]
30
+ def build(context: Context.current)
31
+ builder = Builder.new(baggage_for(context).dup)
32
+ yield builder
33
+ context.set_value(BAGGAGE_KEY, builder.entries)
34
+ end
35
+
36
+ # Returns a new context with empty baggage
37
+ #
38
+ # @param [optional Context] context Context to clear baggage from. Defaults
39
+ # to +Context.current+
40
+ # @return [Context]
41
+ def clear(context: Context.current)
42
+ context.set_value(BAGGAGE_KEY, EMPTY_BAGGAGE)
43
+ end
44
+
45
+ # Returns the corresponding baggage.entry (or nil) for key
46
+ #
47
+ # @param [String] key The lookup key
48
+ # @param [optional Context] context The context from which to retrieve
49
+ # the key.
50
+ # Defaults to +Context.current+
51
+ # @return [String]
52
+ def value(key, context: Context.current)
53
+ baggage_for(context)[key]&.value
54
+ end
55
+
56
+ # Returns the baggage
57
+ #
58
+ # @param [optional Context] context The context from which to retrieve
59
+ # the baggage.
60
+ # Defaults to +Context.current+
61
+ # @return [Hash]
62
+ def values(context: Context.current)
63
+ baggage_for(context).transform_values(&:value)
64
+ end
65
+
66
+ # @api private
67
+ def raw_entries(context: Context.current)
68
+ baggage_for(context).dup.freeze
69
+ end
70
+
71
+ # Returns a new context with new key-value pair
72
+ #
73
+ # @param [String] key The key to store this value under
74
+ # @param [String] value String value to be stored under key
75
+ # @param [optional String] metadata This is here to store properties
76
+ # received from other W3C Baggage impelmentations but is not exposed in
77
+ # OpenTelemetry. This is condsidered private API and not for use by
78
+ # end-users.
79
+ # @param [optional Context] context The context to update with new
80
+ # value. Defaults to +Context.current+
81
+ # @return [Context]
82
+ def set_value(key, value, metadata: nil, context: Context.current)
83
+ new_baggage = baggage_for(context).dup
84
+ new_baggage[key] = Entry.new(value, metadata)
85
+ context.set_value(BAGGAGE_KEY, new_baggage)
86
+ end
87
+
88
+ # Returns a new context with value at key removed
89
+ #
90
+ # @param [String] key The key to remove
91
+ # @param [optional Context] context The context to remove baggage
92
+ # from. Defaults to +Context.current+
93
+ # @return [Context]
94
+ def remove_value(key, context: Context.current)
95
+ baggage = baggage_for(context)
96
+ return context unless baggage.key?(key)
97
+
98
+ new_baggage = baggage.dup
99
+ new_baggage.delete(key)
100
+ context.set_value(BAGGAGE_KEY, new_baggage)
101
+ end
102
+
103
+ private
104
+
105
+ def baggage_for(context)
106
+ context.value(BAGGAGE_KEY) || EMPTY_BAGGAGE
107
+ end
15
108
  end
16
109
  end
@@ -6,13 +6,39 @@
6
6
 
7
7
  module OpenTelemetry
8
8
  module Baggage
9
- # No op implementation of Baggage::Builder
9
+ # Operational implementation of Baggage::Builder
10
10
  class Builder
11
- def set_value(key, value); end
11
+ # @api private
12
+ attr_reader :entries
12
13
 
13
- def remove_value(key); end
14
+ # @api private
15
+ def initialize(entries)
16
+ @entries = entries
17
+ end
14
18
 
15
- def clear; end
19
+ # Set key-value in the to-be-created baggage
20
+ #
21
+ # @param [String] key The key to store this value under
22
+ # @param [String] value String value to be stored under key
23
+ # @param [optional String] metadata This is here to store properties
24
+ # received from other W3C Baggage impelmentations but is not exposed in
25
+ # OpenTelemetry. This is condsidered private API and not for use by
26
+ # end-users.
27
+ def set_value(key, value, metadata: nil)
28
+ @entries[key] = OpenTelemetry::Baggage::Entry.new(value, metadata)
29
+ end
30
+
31
+ # Removes key from the to-be-created baggage
32
+ #
33
+ # @param [String] key The key to remove
34
+ def remove_value(key)
35
+ @entries.delete(key)
36
+ end
37
+
38
+ # Clears all baggage from the to-be-created baggage
39
+ def clear
40
+ @entries.clear
41
+ end
16
42
  end
17
43
  end
18
44
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ # OpenTelemetry Baggage Implementation
9
+ module Baggage
10
+ # Read-only representation of a baggage entry
11
+ class Entry
12
+ attr_reader :value, :metadata
13
+
14
+ def initialize(value, metadata = nil)
15
+ @value = value
16
+ @metadata = metadata
17
+ end
18
+ end
19
+ end
20
+ end
@@ -5,32 +5,23 @@
5
5
  # SPDX-License-Identifier: Apache-2.0
6
6
 
7
7
  require 'opentelemetry/baggage/propagation/context_keys'
8
- require 'opentelemetry/baggage/propagation/text_map_injector'
9
- require 'opentelemetry/baggage/propagation/text_map_extractor'
8
+ require 'opentelemetry/baggage/propagation/text_map_propagator'
10
9
 
11
10
  module OpenTelemetry
12
11
  module Baggage
13
- # The Baggage::Propagation module contains injectors and
14
- # extractors for sending and receiving baggage over the wire
12
+ # The Baggage::Propagation module contains a text map propagator for
13
+ # sending and receiving baggage over the wire.
15
14
  module Propagation
16
15
  extend self
17
16
 
18
- BAGGAGE_KEY = 'baggage'
19
- TEXT_MAP_EXTRACTOR = TextMapExtractor.new
20
- TEXT_MAP_INJECTOR = TextMapInjector.new
17
+ TEXT_MAP_PROPAGATOR = TextMapPropagator.new
21
18
 
22
- private_constant :BAGGAGE_KEY, :TEXT_MAP_INJECTOR, :TEXT_MAP_EXTRACTOR
19
+ private_constant :TEXT_MAP_PROPAGATOR
23
20
 
24
- # Returns an extractor that extracts context using the W3C Baggage
25
- # format
26
- def text_map_injector
27
- TEXT_MAP_INJECTOR
28
- end
29
-
30
- # Returns an injector that injects context using the W3C Baggage
31
- # format
32
- def text_map_extractor
33
- TEXT_MAP_EXTRACTOR
21
+ # Returns a text map propagator that propagates context using the
22
+ # W3C Baggage format.
23
+ def text_map_propagator
24
+ TEXT_MAP_PROPAGATOR
34
25
  end
35
26
  end
36
27
  end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ require 'cgi'
8
+
9
+ module OpenTelemetry
10
+ module Baggage
11
+ module Propagation
12
+ # Propagates baggage using the W3C Baggage format
13
+ class TextMapPropagator
14
+ # Maximums according to W3C Baggage spec
15
+ MAX_ENTRIES = 180
16
+ MAX_ENTRY_LENGTH = 4096
17
+ MAX_TOTAL_LENGTH = 8192
18
+
19
+ BAGGAGE_KEY = 'baggage'
20
+ FIELDS = [BAGGAGE_KEY].freeze
21
+
22
+ private_constant :BAGGAGE_KEY, :FIELDS, :MAX_ENTRIES, :MAX_ENTRY_LENGTH, :MAX_TOTAL_LENGTH
23
+
24
+ # Inject in-process baggage into the supplied carrier.
25
+ #
26
+ # @param [Carrier] carrier The mutable carrier to inject baggage into
27
+ # @param [Context] context The context to read baggage from
28
+ # @param [optional Setter] setter If the optional setter is provided, it
29
+ # will be used to write context into the carrier, otherwise the default
30
+ # text map setter will be used.
31
+ def inject(carrier, context: Context.current, setter: Context::Propagation.text_map_setter)
32
+ baggage = OpenTelemetry::Baggage.raw_entries(context: context)
33
+
34
+ return if baggage.nil? || baggage.empty?
35
+
36
+ encoded_baggage = encode(baggage)
37
+ setter.set(carrier, BAGGAGE_KEY, encoded_baggage) unless encoded_baggage&.empty?
38
+ nil
39
+ end
40
+
41
+ # Extract remote baggage from the supplied carrier.
42
+ # If extraction fails or there is no baggage to extract,
43
+ # then the original context will be returned
44
+ #
45
+ # @param [Carrier] carrier The carrier to get the header from
46
+ # @param [optional Context] context Context to be updated with the baggage
47
+ # extracted from the carrier. Defaults to +Context.current+.
48
+ # @param [optional Getter] getter If the optional getter is provided, it
49
+ # will be used to read the header from the carrier, otherwise the default
50
+ # text map getter will be used.
51
+ #
52
+ # @return [Context] context updated with extracted baggage, or the original context
53
+ # if extraction fails
54
+ def extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter)
55
+ header = getter.get(carrier, BAGGAGE_KEY)
56
+ return context if header.nil? || header.empty?
57
+
58
+ entries = header.gsub(/\s/, '').split(',')
59
+
60
+ OpenTelemetry::Baggage.build(context: context) do |builder|
61
+ entries.each do |entry|
62
+ # Note metadata is currently unused in OpenTelemetry, but is part
63
+ # the W3C spec where it's referred to as properties. We preserve
64
+ # the properties (as-is) so that they can be propagated elsewhere.
65
+ kv, meta = entry.split(';', 2)
66
+ k, v = kv.split('=').map!(&CGI.method(:unescape))
67
+ builder.set_value(k, v, metadata: meta)
68
+ end
69
+ end
70
+ rescue StandardError => e
71
+ OpenTelemetry.logger.debug "Error extracting W3C baggage: #{e.message}"
72
+ context
73
+ end
74
+
75
+ # Returns the predefined propagation fields. If your carrier is reused, you
76
+ # should delete the fields returned by this method before calling +inject+.
77
+ #
78
+ # @return [Array<String>] a list of fields that will be used by this propagator.
79
+ def fields
80
+ FIELDS
81
+ end
82
+
83
+ private
84
+
85
+ def encode(baggage)
86
+ result = +''
87
+ encoded_count = 0
88
+ baggage.each_pair do |key, entry|
89
+ break unless encoded_count < MAX_ENTRIES
90
+
91
+ encoded_entry = encode_value(key, entry)
92
+ next unless encoded_entry.size <= MAX_ENTRY_LENGTH &&
93
+ encoded_entry.size + result.size <= MAX_TOTAL_LENGTH
94
+
95
+ result << encoded_entry << ','
96
+ encoded_count += 1
97
+ end
98
+ result.chop!
99
+ end
100
+
101
+ def encode_value(key, entry)
102
+ result = +"#{CGI.escape(key.to_s)}=#{CGI.escape(entry.value.to_s)}"
103
+ # We preserve metadata recieved on extract and assume it's already formatted
104
+ # for transport. It's sent as-is without further processing.
105
+ result << ";#{entry.metadata}" if entry.metadata
106
+ result
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end