Skip to content

Commit

Permalink
Introduce Builder to facilitate multiple modifications to Correlation…
Browse files Browse the repository at this point in the history
…Context

This commit adds a builder to faciliate making multiple modifications to
CorrelationContext without creating multiple, intermediary contexts.
Manager#build_context should be used when making multiple modifications
to the correlation context. When making a single modification, all other
methods should be used. Some may object to the builder and might recommend
a single method with kwargs, but I think this makes for a more fluent API.
  • Loading branch information
mwear committed Dec 25, 2019
1 parent a6d5936 commit 4ce543c
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 0 deletions.
1 change: 1 addition & 0 deletions api/lib/opentelemetry/correlation_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#
# SPDX-License-Identifier: Apache-2.0

require 'opentelemetry/correlation_context/builder'
require 'opentelemetry/correlation_context/manager'
require 'opentelemetry/correlation_context/propagation'

Expand Down
18 changes: 18 additions & 0 deletions api/lib/opentelemetry/correlation_context/builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

# Copyright 2019 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

module OpenTelemetry
module CorrelationContext
# No op implementation of CorrelationContext::Builder
class Builder
def set_value(key, value); end

def remove_value(key); end

def clear; end
end
end
end
8 changes: 8 additions & 0 deletions api/lib/opentelemetry/correlation_context/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ module OpenTelemetry
module CorrelationContext
# No op implementation of CorrelationContext::Manager
class Manager
NOOP_BUILDER = Builder.new
private_constant :NOOP_BUILDER

def build(context: Context.current)
yield NOOP_BUILDER
context
end

def set_value(key, value, context: Context.current)
context
end
Expand Down
1 change: 1 addition & 0 deletions sdk/lib/opentelemetry/sdk/correlation_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#
# SPDX-License-Identifier: Apache-2.0

require 'opentelemetry/sdk/correlation_context/builder'
require 'opentelemetry/sdk/correlation_context/manager'

module OpenTelemetry
Expand Down
40 changes: 40 additions & 0 deletions sdk/lib/opentelemetry/sdk/correlation_context/builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

# Copyright 2019 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

module OpenTelemetry
module SDK
module CorrelationContext
# No op implementation of CorrelationContext::Builder
class Builder
attr_reader :entries

def initialize(entries)
@entries = entries
end

# Set key-value in the to-be-created correlation context
#
# @param [String] key The key to store this value under
# @param [String] value String value to be stored under key
def set_value(key, value)
@entries[key] = value.to_s
end

# Removes key from the to-be-created correlation context
#
# @param [String] key The key to remove
def remove_value(key)
@entries.delete(key)
end

# Clears all correlations from the parent context
def clear
@entries.clear
end
end
end
end
end
15 changes: 15 additions & 0 deletions sdk/lib/opentelemetry/sdk/correlation_context/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ class Manager
EMPTY_CORRELATION_CONTEXT = {}.freeze
private_constant(:CORRELATION_CONTEXT_KEY, :EMPTY_CORRELATION_CONTEXT)

# Used to chain modifications to correlation context. The result is a
# context with an updated correlation context. If only a single
# modification is being made to correlation context, use the other
# methods on +Manager+, if multiple modifications are being made, use
# this one.
#
# @param [optional Context] context The context to update with with new
# modified correlation context. Defaults to +Context.current+
# @return [Context]
def build_context(context: Context.current)
builder = Builder.new(correlations_for(context).dup)
yield builder
context.set_value(CORRELATION_CONTEXT_KEY, builder.entries)
end

# Returns a new context with empty correlations
#
# @param [optional Context] context Context to clear correlations from. Defaults
Expand Down
85 changes: 85 additions & 0 deletions sdk/test/opentelemetry/sdk/correlation_context/manager_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,89 @@
end
end
end

describe '.build_context' do
let(:initial_context) { manager.set_value('k1', 'v1') }

describe 'explicit context' do
it 'sets entries' do
ctx = initial_context
ctx = manager.build_context(context: ctx) do |correlations|
correlations.set_value('k2', 'v2')
correlations.set_value('k3', 'v3')
end
_(manager.value('k1', context: ctx)).must_equal('v1')
_(manager.value('k2', context: ctx)).must_equal('v2')
_(manager.value('k3', context: ctx)).must_equal('v3')
end

it 'removes entries' do
ctx = initial_context
ctx = manager.build_context(context: ctx) do |correlations|
correlations.remove_value('k1')
correlations.set_value('k2', 'v2')
end
_(manager.value('k1', context: ctx)).must_be_nil
_(manager.value('k2', context: ctx)).must_equal('v2')
end

it 'clears entries' do
ctx = initial_context
ctx = manager.build_context(context: ctx) do |correlations|
correlations.clear
correlations.set_value('k2', 'v2')
end
_(manager.value('k1', context: ctx)).must_be_nil
_(manager.value('k2', context: ctx)).must_equal('v2')
end
end

describe 'implicit context' do
it 'sets entries' do
Context.with_current(initial_context) do
ctx = manager.build_context do |correlations|
correlations.set_value('k2', 'v2')
correlations.set_value('k3', 'v3')
end
Context.with_current(ctx) do
_(manager.value('k1')).must_equal('v1')
_(manager.value('k2')).must_equal('v2')
_(manager.value('k3')).must_equal('v3')
end
end
end

it 'removes entries' do
Context.with_current(initial_context) do
_(manager.value('k1')).must_equal('v1')

ctx = manager.build_context do |correlations|
correlations.remove_value('k1')
correlations.set_value('k2', 'v2')
end

Context.with_current(ctx) do
_(manager.value('k1')).must_be_nil
_(manager.value('k2')).must_equal('v2')
end
end
end

it 'clears entries' do
Context.with_current(initial_context) do
_(manager.value('k1')).must_equal('v1')

ctx = manager.build_context do |correlations|
correlations.clear
correlations.set_value('k2', 'v2')
end

Context.with_current(ctx) do
_(manager.value('k1')).must_be_nil
_(manager.value('k2')).must_equal('v2')
end
end
end
end
end
end

0 comments on commit 4ce543c

Please sign in to comment.